Table of Contents

curl

Requests

curl https://api.example.com                    # GET
curl -X POST <url>                              # bare POST
curl -X PUT|PATCH|DELETE <url>
curl -d 'a=1&b=2' <url>                         # POST form data
curl -d @file.json -H 'Content-Type: application/json' <url>   # body from file
curl -F 'file=@photo.jpg' -F 'name=x' <url>     # multipart upload
curl --data-binary @payload.bin <url>           # raw body, no processing
curl -G -d 'q=search' -d 'page=2' <url>         # -d as QUERY params

Headers & auth

curl -H 'Accept: application/json' <url>
curl -H 'Authorization: Bearer TOKEN' <url>
curl -u user:pass <url>                         # basic auth
curl -u user <url>                              # prompts for pass
curl --oauth2-bearer TOKEN <url>
curl --netrc <url>                              # creds from ~/.netrc

Downloading

curl -O <url>                    # remote filename
curl -o out.bin <url>            # your filename
curl -C - -O <url>               # resume partial download
curl --retry 5 --retry-delay 2 --retry-all-errors <url>
curl --limit-rate 1M -O <url>    # bandwidth cap (kind to a slow link)
curl -L <url>                    # follow redirects (usually wanted)
curl -f <url>                    # fail (nonzero exit) on HTTP errors

Inspecting responses

curl -I <url>                    # HEAD request, headers only
curl -i <url>                    # headers + body
curl -v <url>                    # verbose: request+TLS+response trace
curl -sS <url>                   # silent but show errors: script default
curl -D headers.txt <url>        # save headers to file

`-w`: timing and metadata

curl -so /dev/null -w '%{http_code}\n' <url>            # just the status
curl -so /dev/null -w '%{time_total}s %{speed_download}B/s\n' <url>
curl -o /dev/null -w '%{size_download} %{http_code} %{url_effective}\n' <url>

Common vars: http_code time_total time_namelookup time_connect speed_download size_download remote_ip redirect_url url_effective.

Cookies & sessions

curl -c jar.txt <url>            # save cookies
curl -b jar.txt <url>            # send them
curl -c jar -b jar <url>         # both: keeps a session across calls
curl -b 'name=val' <url>         # one-off cookie

Tricks

curl --resolve host:443:1.2.3.4 https://host/    # bypass DNS
curl --connect-to ::staging:443 https://prod/    # hit staging as prod
curl -A 'Mozilla/5.0' <url>                      # user-agent
curl --compressed <url>                          # accept gzip/br
curl -k https://self-signed/                     # skip TLS verify (debug only)
curl --cacert cert.pem <url>                     # custom CA
curl --proxy http://127.0.0.1:8080 <url>         # via proxy
curl --noproxy '*' <url>                         # force direct

In scripts

code=$(curl -so /dev/null -w '%{http_code}' "$url")
curl -fsSL "$url" || die "download failed"      # -f = exit !=0 on HTTP error
body=$(curl -fsS "$api" )                       # capture response
echo "$body" | jq '.items[0]'

~/.curlrc for defaults (e.g. retry = 3, fail).

Debug a bad response

curl -sv <url> 2>&1 | less       # whole exchange incl. TLS
curl --trace-ascii - <url>       # even more detail

Suspects, in order: DNS (time_namelookup huge / Could not resolve), TLS handshake, 4xx auth, 5xx their problem. curl -w splits timing per phase to isolate where it's slow.

See Also