Overview

curl is the fastest tool for manually testing HTTP endpoints before writing client code. This card collects the invocations for the most common API testing scenarios: CRUD operations, JSON payloads, authentication, file uploads, and response inspection. For the full flag reference see curl-flags; for parsing JSON responses see json-jq-recipes.

GET requests

PatternCommandNotes
Basic GETcurl https://api.example.com/itemsOutputs body to stdout
With query paramscurl "https://api.example.com/items?page=2&limit=10"Quote the URL to prevent shell expansion of &
Follow redirectscurl -L https://example.comFollows 3xx chains
Save to filecurl -o out.json https://api.example.com/dataNamed output file
Show response headerscurl -I https://api.example.com/itemsHEAD request only
Show headers + bodycurl -D - https://api.example.com/items-D - prints headers to stdout before body
Timing breakdowncurl -w "@curl-format.txt" -s -o /dev/null https://example.comCustom format for DNS, connect, TTFB
Verbosecurl -v https://api.example.com/itemsShows request + response headers and TLS handshake
Silent + failcurl -sf https://api.example.com/itemsNo progress; exit code 22 on HTTP error

For API testing, combine -s (silent) and -S (show errors) to suppress progress but not hide curl errors.

POST and PUT with JSON

PatternCommandNotes
POST JSON inlinecurl -X POST https://api.example.com/items -H "Content-Type: application/json" -d '{"name":"foo"}'Single-line JSON body
POST JSON from filecurl -X POST https://api.example.com/items -H "Content-Type: application/json" -d @payload.json@ reads from file
PUT updatecurl -X PUT https://api.example.com/items/42 -H "Content-Type: application/json" -d '{"name":"bar"}'Replace resource
PATCH partialcurl -X PATCH https://api.example.com/items/42 -H "Content-Type: application/json" -d '{"status":"active"}'Partial update
DELETEcurl -X DELETE https://api.example.com/items/42No body required
Accept headercurl https://api.example.com/items -H "Accept: application/json"Request specific format
Multiple headerscurl ... -H "Content-Type: application/json" -H "X-Request-ID: abc123"Repeat -H for each

-d sets method to POST implicitly; add -X POST explicitly for clarity in scripts.

Authentication patterns

Auth typeCommandNotes
Bearer tokencurl -H "Authorization: Bearer $TOKEN" https://api.example.com/protectedStandard JWT or OAuth
Basic authcurl -u username:password https://api.example.com/resourceURL-encodes credentials
Basic auth (prompt)curl -u username https://api.example.com/resourcePrompts for password
API key headercurl -H "X-API-Key: $API_KEY" https://api.example.com/resourceKey name varies by service
API key query paramcurl "https://api.example.com/resource?api_key=$API_KEY"Less secure; logged in URLs
Client certificatecurl --cert client.crt --key client.key https://api.example.com/resourcemTLS
Cookie jarcurl -c cookies.txt -b cookies.txt https://api.example.com/loginSave and send cookies
Digest authcurl --digest -u user:pass https://api.example.com/resourceChallenge-response

Store tokens in environment variables, not inline. export TOKEN=$(cat ~/.tokens/myapi).

File uploads and multipart

PatternCommandNotes
Single file uploadcurl -F "file=@photo.jpg" https://api.example.com/uploadMultipart form
File + fieldcurl -F "file=@photo.jpg" -F "title=My Photo" https://api.example.com/uploadMix file and fields
File with MIME typecurl -F "file=@data.csv;type=text/csv" https://api.example.com/uploadOverride detected type
Binary body (PUT)curl -X PUT --data-binary @image.png -H "Content-Type: image/png" https://api.example.com/images/1Raw binary, no multipart
URL-encoded formcurl -d "name=foo&value=bar" https://api.example.com/formapplication/x-www-form-urlencoded

-F triggers multipart/form-data; -d triggers application/x-www-form-urlencoded. JSON bodies need -H "Content-Type: application/json" explicitly.

Response inspection and scripting

PatternCommandNotes
HTTP status code onlycurl -s -o /dev/null -w "%{http_code}" https://api.example.com/itemsUseful in scripts
Pretty-print JSONcurl -s https://api.example.com/items | jq .Pipe to jq
Extract fieldcurl -s https://api.example.com/item/1 | jq '.name'Single field
Store in variableBODY=$(curl -s https://api.example.com/item/1)Capture for reuse
Retry on failurecurl --retry 3 --retry-delay 2 https://api.example.com/itemsTransient error recovery
Timeoutcurl --max-time 10 https://api.example.com/itemsAbort after 10 seconds
Ignore TLS errorscurl -k https://localhost:8443/itemsDev only; never production
Proxycurl -x http://proxy:3128 https://api.example.com/itemsHTTP proxy

Chain curl with jq for lightweight API scripting: curl -sf https://api.example.com/users | jq '.[].email' dumps all emails.

Common gotchas

  • Single quotes around {} in shell: '{"key":"val"}' is safe; double quotes require escaping internal quotes.
  • -d @file reads the file as-is, including newlines. Minify JSON before sending if the API is picky.
  • curl exits 0 on HTTP 4xx/5xx unless you pass -f/--fail. Scripts that check only $? miss server errors.
  • --compressed enables Accept-Encoding: gzip and decompresses the response automatically. Without it, a gzip response prints binary garbage.
  • Redirect following (-L) may change the method from POST to GET on a 302. Use --post301 and --post302 to preserve POST.
  • -u user:pass appears in process listing on Linux. Prefer -H "Authorization: Basic $(echo -n user:pass | base64)" in automated scripts.