Skip to content

~/avetyan.com/cheatsheets

Cheat sheets

curl cheat sheet

HTTP from the terminal with curl: headers, methods, JSON APIs, auth, downloads, TLS checks and timing a request phase by phase.

3 min read


Basics

bash
curl https://example.com                     # body to stdout
curl -I https://example.com                  # headers only (HEAD request)
curl -i https://example.com                  # headers and body
curl -L https://example.com                  # follow redirects
curl -fsSL https://example.com/install.sh    # scripts: fail on HTTP errors, silent but show errors, follow redirects
curl -v https://example.com                  # request and response headers, TLS handshake

Downloads

bash
curl -O https://example.com/file.tar.gz             # keep the remote name
curl -o app.tgz https://example.com/file.tar.gz     # choose the name
curl -C - -O https://example.com/big.iso            # resume
curl --limit-rate 5M -O https://example.com/big.iso
curl -fsSL https://example.com/app.tar.gz | tar -xzf -

Methods and data

bash
curl -X DELETE https://api.example.com/items/42
curl -d 'name=alice&role=admin' https://example.com/form       # POST, form-encoded
curl -F '[email protected]' https://example.com/upload          # multipart upload
curl -H 'Accept: application/json' -H 'X-Request-Id: test-1' https://api.example.com/

# JSON (curl 7.82+ has --json, which sets the method and both headers)
curl --json '{"name":"alice"}' https://api.example.com/users
curl -H 'Content-Type: application/json' -d @payload.json https://api.example.com/users

-d switches the method to POST by itself; add -X only for PUT, PATCH or DELETE.

Auth

bash
curl -u admin https://example.com/             # prompts for the password
curl -H "Authorization: Bearer $TOKEN" https://api.example.com/
curl --cert client.pem --key client.key https://mtls.example.com/

Avoid -u user:password on shared machines: it ends up in shell history and ps.

Before DNS cutover

bash
curl --resolve example.com:443:203.0.113.10 https://example.com/
curl --connect-to example.com:443:new-lb.example.com:443 https://example.com/
curl -H 'Host: example.com' http://203.0.113.10/      # plain HTTP only

--resolve keeps SNI and certificate checks correct, which the Host header trick doesn’t for HTTPS.

TLS

bash
curl -vI https://example.com 2>&1 | grep -E 'SSL connection|subject:|expire date|issuer:'
curl --tlsv1.3 -I https://example.com          # require TLS 1.3 or newer
curl --tls-max 1.1 -I https://example.com      # should fail on a hardened server
curl --cacert internal-ca.pem https://internal.example/
curl -k https://192.0.2.10:8443/health         # self-signed cert: skip verification
curl --insecure -sS https://dev.example.com/   # the long form of -k

-k (--insecure) accepts any certificate: self-signed, expired or issued for another name. The traffic is still encrypted, but nothing proves who answered. It’s fine for a lab box or a quick check of a service that only has a self-signed cert. For anything you keep, trust that certificate with --cacert instead, and never leave -k in scripts.

Timing

bash
curl -o /dev/null -s -w 'dns %{time_namelookup}\nconnect %{time_connect}\ntls %{time_appconnect}\nttfb %{time_starttransfer}\ntotal %{time_total}\n' https://example.com
curl -o /dev/null -s -w '%{http_code}\n' https://example.com      # status code only

Times are cumulative seconds from the start: tls - connect is the handshake, ttfb - tls is the server’s think time.

Timeouts

bash
curl --connect-timeout 5 --max-time 30 https://example.com
curl --retry 5 --retry-delay 2 --retry-all-errors https://example.com

Set both timeouts in scripts and health checks; by default curl can wait for minutes.

Other bits

bash
curl -c cookies.txt -b cookies.txt https://example.com/login   # save and send cookies
curl -x http://proxy:3128 https://example.com                 # through a proxy
curl --http2 -I https://example.com                           # or --http3 if built with it
curl ifconfig.me                                              # your public IP
curl -s https://api.example.com/items | jq '.[0]'

Comments

Sign in with Google, GitHub or Facebook to comment.

Loading comments…