From Christoph's Personal Wiki
Jump to: navigation, search

cURL is a command line tool for transferring files with URL syntax, supporting FTP, FTPS, HTTP, HTTPS, TFTP, Telnet, DICT, FILE and LDAP. cURL supports HTTPS certificates, HTTP POST, HTTP PUT, FTP uploading, Kerberos, HTTP form based upload, proxies, cookies, user+password authentication (Basic, Digest, NTLM and Negotiate for HTTP and kerberos4 for FTP), file transfer resume, http proxy tunneling and many other features. cURL is open source/free software distributed under MIT License.

The main purpose and use for cURL is to automate unattended file transfers or sequences of operations. It is for example a good tool for simulating a user's actions at a web browser.

Libcurl is the corresponding library/API that users may incorporate into their programs; cURL acts as a stand-alone wrapper to the libcurl library. libcurl is being used to provide URL transfer capabilities to numerous applications, Open Source as well as many commercial ones.

Simple usage

  • Get the main page from firefox's web-server:
$ curl
  • Get the README file the user's home directory at funet's ftp-server:
$ curl
  • Get a web page from a server using port 8000:
$ curl
  • Get a list of a directory of an FTP site:
$ curl
  • Get a gopher document from a gopher server:
$ curl gopher://
$ curl gopher://
  • Get the definition of curl from a dictionary:
$ curl dict://
  • Fetch two documents at once:
$ curl
$ curl -I
HTTP/1.1 301 Moved Permanently
Date: Wed, 15 Apr 2015 21:24:28 GMT
Server: Apache/2.2.15 (CentOS)
Connection: close
Content-Type: text/html; charset=iso-8859-1

# redirects to
# So, use "-L" to follow that redirect:
$ curl -L

Miscellaneous examples

  • Check on the amount of time it takes to load a website (lookup/connect/transfer times):
$ for i in $(seq 1 3); do curl -so /dev/null \
   -w "time_namelookup: %{time_namelookup}\
       \ttime_connect: %{time_connect}\
       \ttime_starttransfer: %{time_starttransfer}\
       \ttime_total: %{time_total}\n"; done
time_namelookup: 0.004  time_connect: 0.005     time_starttransfer: 0.854       time_total: 0.964
time_namelookup: 0.004  time_connect: 0.005     time_starttransfer: 0.575       time_total: 0.617
time_namelookup: 0.004  time_connect: 0.005     time_starttransfer: 0.550       time_total: 0.555

Download to a file

  • Get a web page and store in a local file:
$ curl -o thatpage.html
  • Get a web page and store in a local file, make the local file get the name of the remote document (if no file name part is specified in the URL, this will fail):
$ curl -O
  • Fetch two files and store them with their remote names:
$ curl -O -O</pre>

Using cURL for fast downloads

Suppose you want to download the Ubuntu 14.04.3 LTS (Trusty Tahr; 64-bit) ISO from the following three mirrors:

$ curl -sI |\
    awk '/^Content-Length/{iso_size=$2/1024^2; print iso_size}'
$ url1=
$ url2=
$ url3=

Get the total size (in bytes) of the ISO:

$ iso_size=$(curl -sI ${ISOURL} | awk '/^Content-Length/{print $2}')

The total size of the ISO is 1054867456 bytes (~1.0GB). Using cURL's "--range" option, we can download that ISO in 3 parts from the above 3 different mirrors simultaneously with the following commands (do not forget the "&" at the end so each download is backgrounded):

$ curl -r 0-499999999 -o ubuntu-14.04.3-desktop-amd64.iso.part1 $url1 &         # 1st 500MB
$ curl -r 500000000-999999999 -o ubuntu-14.04.3-desktop-amd64.iso.part2 $url2 & # 2nd 500MB
$ curl -r 1000000000- -o ubuntu-14.04.3-desktop-amd64.iso.part3 $url3 &         # remaining bytes

After all three parts have downloaded, `cat` them all together into a single ISO

$ cat ubuntu-14.04.3-desktop-amd64.iso.part? > ubuntu-14.04.3-desktop-amd64.iso

Finally, check the integrity of the ISO using the MD5SUM for the original ISO:

$ wget -c
$ grep ubuntu-14.04.3-desktop-amd64.iso MD5SUMS
$ md5sum ubuntu-14.04.3-desktop-amd64.iso

The two values should be identical. Et voilà! You have downloaded that ISO (potentially) much faster than downloading it as one single ISO.

Note: You could automate the process in a script. You would use the ${iso_size} from above together with the following lines:

$ blocksize=$(expr 1024 \* 512)
$ curl -\# -r $sum-$(($sum+$blocksize)) -o ubuntu-14.04.3-desktop-amd64.iso.part${num} $url1 &

The "-\#" is to switch from the regular meter to a progress "bar".

Write out variables

With curl "write-out" variables, one can make curl display information on STDOUT after a completed transfer. The format is a string that may contain plain text mixed with any number of variables. The format can be specified as a literal "string", or you can have curl read the format from a file with "@filename" and to tell curl to read the format from STDIN you write "@-".

The variables present in the output format will be substituted by the value or text that curl thinks fit, as described below. All variables are specified as %{variable_name} and to output a normal "%" you just write them as "%%". You can output a newline by using "\n", a carriage return with "\r", or a tab space with "\t".

As an example on how to use write out variables, consider my personal URL shortener (or TinyURL) website:

$ curl -I
HTTP/1.1 200 OK
Date: Wed, 17 Feb 2016 01:39:21 GMT
Server: Apache/2.2.15 (CentOS)
Last-Modified: Sun, 17 May 2015 21:22:51 GMT
ETag: "2a073-d2-5164dadfec0c0"
Accept-Ranges: bytes
Content-Length: 210
X-CLI: Website by Christoph Champ
Connection: close
Content-Type: text/html; charset=UTF-8
$ read -r -d '' WRITE_OUT_VARS <<'EOF'
content_type: %{content_type}
http_code: %{http_code}
http_connect: %{http_connect}
local_ip: %{local_ip}
local_port: %{local_port}
num_connects: %{num_connects}
num_redirects: %{num_redirects}
redirect_url: %{redirect_url}
remote_ip: %{remote_ip}
remote_port: %{remote_port}
size_download: %{size_download}
size_header: %{size_header}
size_upload: %{size_upload}
speed_download: %{speed_download}
speed_upload: %{speed_upload}
ssl_verify_result: %{ssl_verify_result}
time_connect: %{time_connect}
time_namelookup: %{time_namelookup}
time_redirect: %{time_redirect}
time_starttransfer: %{time_starttransfer}
time_total: %{time_total}
url_effective: %{url_effective}

If I pass a TinyURL to my website, I get the following:

$ curl -sw "${WRITE_OUT_VARS}\n" -o /dev/null
content_type: text/html; charset=iso-8859-1
http_code: 301
http_connect: 000
local_ip: 10.x.x.x
local_port: 56646
num_connects: 1
num_redirects: 0
remote_port: 80
size_download: 338
size_header: 257
size_upload: 0
speed_download: 3238.000
speed_upload: 0.000
ssl_verify_result: 0
time_connect: 0.055
time_namelookup: 0.004
time_redirect: 0.000
time_starttransfer: 0.104
time_total: 0.104
url_effective: HTTP://

If I tell curl to follow the redirect URL (i.e., with "-L"), I get the following:

$ curl -sLw "${WRITE_OUT_VARS}\n" -o /dev/null
content_type: text/html; charset=UTF-8
http_code: 200
http_connect: 000
local_ip: 10.x.x.x
local_port: 54964
num_connects: 2
num_redirects: 2
remote_port: 80
size_download: 66120
size_header: 1132
size_upload: 0
speed_download: 91268.000
speed_upload: 0.000
ssl_verify_result: 0
time_connect: 0.000
time_namelookup: 0.000
time_redirect: 0.466
time_starttransfer: 0.167
time_total: 0.724

Note how the "redirect_url", "url_effective", "remote_ip", "num_redirects", etc. have changed.

See also

External links