Andrew Mercer
on this page

What it is

curl transfers data to or from a server using HTTP(S), FTP, SFTP, and dozens of other protocols. It is the default tool for testing web services and APIs from the shell. For recursive downloading and mirroring, see wget. The curl author's comparison of the two: curl vs Wget.

Everyday use

curl https://example.com                         # body to stdout
curl -I https://example.com                      # headers only (HEAD request)
curl -sS -o /dev/null -w '%{http_code}\n' https://example.com   # just the status code
curl -L https://example.com/old                  # follow redirects
curl -O https://example.com/file.tar.gz          # save under the remote name
curl -o out.tar.gz https://example.com/file.tar.gz
curl -C - -O https://example.com/big.iso         # resume an interrupted download

-s silences the progress meter and -S still shows errors, so -sS is the usual pair in scripts. Add -f to fail with a non-zero exit code on HTTP errors (4xx/5xx), otherwise curl exits 0 when the server returns an error page.

Authentication

curl -u username https://example.com/api        # prompts for the password
curl -H "Authorization: Bearer $TOKEN" https://example.com/api

Avoid -u username:password on shared machines: the password lands in shell history and is visible in ps output while curl runs. Use the prompt form, a ~/.netrc file (curl -n), or a token from an environment variable.

Sending data

curl -X POST -H 'Content-Type: application/json' \
     -d '{"name":"test"}' https://example.com/api/items
curl --data-urlencode 'q=hello world' https://example.com/search
curl -F '[email protected]' https://example.com/upload       # multipart upload
curl -d @payload.json -H 'Content-Type: application/json' https://example.com/api

Debugging

curl -v https://example.com                     # request and response headers, TLS handshake
curl --resolve example.com:443:203.0.113.10 https://example.com   # test a specific backend/IP
curl --connect-timeout 5 --max-time 20 https://example.com
curl -w 'dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total}\n' \
     -o /dev/null -s https://example.com

The -w timing line shows where the time goes: DNS, TCP connect, TLS, then time to first byte.

--resolve is the cleanest way to test a load balancer member or a site before DNS is switched: it overrides name resolution while keeping the correct Host header and TLS SNI. -k skips certificate verification. Use it to confirm a certificate problem, never as a permanent fix.

Proxies and IP family

curl -x http://proxy.example.com:3128 https://example.com
curl -4 https://example.com          # force IPv4
curl -6 https://example.com          # force IPv6