curl
curl moves data over almost any protocol — HTTP, HTTPS, FTP, file. The Unix-pipeline-friendly way to test APIs, download files, mirror sites, debug TLS. Pair with jq to query JSON responses.
Methods, auth, files, debug, jq
EXAMPLE
# 1) GET (default)
curl https://api.github.com/users/octocat
curl -s https://api.github.com/users/octocat # silent (no progress meter)
# Pretty-print JSON
curl -s https://api.github.com/users/octocat | jq
# 2) Methods
curl -X POST https://api.example.com/users
curl -X PUT https://api.example.com/users/42
curl -X DELETE https://api.example.com/users/42
curl -X PATCH https://api.example.com/users/42
# 3) Headers
curl -H 'Accept: application/json' \
-H 'Authorization: Bearer $TOKEN' \
https://api.example.com/me
# 4) JSON body
curl -X POST https://api.example.com/posts \
-H 'Content-Type: application/json' \
-d '{"title":"hello","body":"first post"}'
# From a file
curl -X POST -H 'Content-Type: application/json' -d @post.json https://api.example.com/posts
# 5) Form data (application/x-www-form-urlencoded)
curl -X POST -d 'name=ada&email=a@x.com' https://api.example.com/users
# URL-encode automatically with --data-urlencode
curl -X POST \
--data-urlencode 'comment=hi there & welcome' \
--data-urlencode 'rating=5' \
https://api.example.com/comments
# Multipart upload (file + fields)
curl -X POST \
-F 'avatar=@/path/to/photo.png' \
-F 'caption=My photo' \
https://api.example.com/upload
# 6) Authentication
# Basic auth
curl -u user:pass https://api.example.com/private
curl -u 'user:$TOKEN' https://api.example.com/private
# Bearer
curl -H 'Authorization: Bearer $TOKEN' https://api.example.com/me
# Read password from a file (avoid passing in argv)
curl --user 'user' --next ' ' --netrc-file ~/.netrc https://api.example.com
# 7) Save output
curl -o page.html https://example.com
curl -O https://example.com/file.zip # use the URL's last path segment as filename
# Resume an interrupted download
curl -C - -O https://example.com/large.zip
# 8) Follow redirects
curl -L https://example.com
curl -L --max-redirs 5 https://example.com
# 9) Show response headers
curl -I https://example.com # HEAD request — headers only
curl -i https://example.com # full response with headers
# Print only response body, suppress everything else
curl -s -o /dev/null -w '%{http_code}\n' https://example.com
# Output: 200
# Print stats — timing, status, size
curl -s -o /dev/null -w 'status=%{http_code} time=%{time_total}s size=%{size_download}\n' https://example.com
# Full custom output
curl -s -o /dev/null -w 'lookup=%{time_namelookup} connect=%{time_connect} ttfb=%{time_starttransfer} total=%{time_total}\n' https://api.example.com/me
# 10) Debug
curl -v https://example.com # verbose: requests + responses
curl --trace-ascii trace.txt https://example.com # full trace to a file
# Time how long DNS / TCP / TLS / TTFB / total take:
curl -w '@curl-format.txt' -o /dev/null -s https://example.com
# curl-format.txt:
# time_namelookup: %{time_namelookup}\n
# time_connect: %{time_connect}\n
# time_appconnect: %{time_appconnect}\n
# time_pretransfer: %{time_pretransfer}\n
# time_starttransfer: %{time_starttransfer}\n
# time_total: %{time_total}\n
# 11) Cookies
curl -c cookies.txt https://example.com/login # save cookies
curl -b cookies.txt https://example.com/account # send cookies
curl -b 'session=abc; user=42' https://example.com
# 12) Proxy
curl --proxy http://proxy.example.com:8080 https://example.com
export HTTPS_PROXY=http://proxy:8080 # all subsequent curls
curl --proxy-user user:pass --proxy http://proxy:8080 https://example.com
# 13) TLS
curl --cacert ./ca.pem https://internal.example.com
curl --cert ./client.crt --key ./client.key https://api.example.com # mTLS
curl --tls-max 1.2 https://example.com # restrict TLS version
curl -k https://self-signed.example.com # skip cert validation (DANGER)
# Show TLS handshake details
curl -v --trace-time https://example.com 2>&1 | grep -E 'SSL|TLS|server certificate'
# 14) Practical recipes
# Check a webhook signature
curl -X POST https://hooks.example.com/incoming \
-H 'X-Signature: sha256=...' \
-d @payload.json
# Test an endpoint with retry
for i in 1 2 3 4 5; do
code=$(curl -s -o /dev/null -w '%{http_code}' https://api.example.com/health)
[ "$code" = '200' ] && break
sleep 2
done
# Download a list of files
xargs -n 1 curl -O < urls.txt
# Pipe to jq for JSON queries
curl -s https://api.github.com/repos/torvalds/linux | jq '.stargazers_count'
curl -s https://api.github.com/users/octocat/repos | jq -r '.[].name'
# Pipe to grep for HTML scraping (consider HTML parsing instead)
curl -s https://example.com | grep -oE 'href="[^"]+"'
# Test a graphql query
curl -X POST https://api.example.com/graphql \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer $TOKEN' \
-d '{"query":"query { me { id email } }"}'
# 15) Useful flags cheat sheet
# -s silent
# -L follow redirects
# -X METHOD set HTTP method
# -H 'K: V' add header
# -d 'data' request body
# -F 'key=@file' multipart
# -o FILE write to file
# -O use remote filename
# -I HEAD only
# -i include headers in output
# -v / -vv verbose
# -k skip TLS verification (DANGER)
# -u user:pw basic auth
# -w FORMAT custom output
# --resolve host:port:ip override DNS for testing
# --next separate calls in one invocation
# --compressed request + decode gzip
# --connect-timeout / --max-time set timeouts
# 16) Alternatives
# wget — file download, recursive mirroring
# httpie — friendlier syntax: `http POST api.example.com name=Ada email=a@x.com`
# xh / hurl — modern curl-style with niceties
# Postman / Insomnia / Bruno — GUI for repeated requests + collections
Why it matters
Pair curl -s + jq for any JSON API debugging. curl -w \"@format.txt\" + a template file gives you DNS / connect / TTFB / total timings — the cheapest perf diagnostic in your toolbox.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
curl -fsSL https://api.example.com/users
curl -X POST -H 'Content-Type: application/json' -d '{"name":"Ada"}' /api/users
Try it Yourself »
Discussion
Loading…