curl is already installed on virtually every server, which makes it the first thing you reach for when confirming “it works on my laptop but not on the box.”

Basics

  curl https://api.example.com/users            # GET, body only
curl -i https://api.example.com/users         # include response headers
curl -I https://api.example.com/users         # headers only (HEAD)
curl -s https://api.example.com/users | jq    # quiet, piped into jq
curl -o users.json https://api.example.com/users   # save to a file
  

Flags worth knowing

FlagMeaning
-X POSTSet the method
-H "Key: value"Add a header (repeatable)
-d '{"a":1}'Send a body (implies POST)
--data-urlencodeURL-encode a form value
-F file=@a.pngMultipart file upload
-u user:passBasic auth
-LFollow redirects
-s / -SHide progress / still show errors
-fFail the exit code on HTTP errors (essential in scripts)
-kSkip certificate verification (debugging only)
--max-time 10Overall timeout in seconds
-vPrint the whole request and response exchange

Calling a JSON API

  curl -sS -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"name":"Alex Kim","email":"alex@example.com"}' | jq
  

A long body reads better from a file:

  curl -sS -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -d @payload.json | jq
  

Debugging

  # see the full exchange
curl -v https://api.example.com/health

# just the status code
curl -s -o /dev/null -w "%{http_code}\n" https://example.com

# where the time actually goes
curl -s -o /dev/null -w \
  "dns:%{time_namelookup} connect:%{time_connect} tls:%{time_appconnect} total:%{time_total}\n" \
  https://example.com
  

That last line tells you in one shot whether a slow API is DNS, the TLS handshake, or the server.

Safely in scripts

  set -euo pipefail
curl -fsS --max-time 10 --retry 3 --retry-delay 2 \
  -H "Authorization: Bearer $TOKEN" \
  https://api.example.com/health
  

Without -f, a 404 exits 0 and the failure goes unnoticed. Always include it in automation.

Reproducing a browser request

Chrome DevTools → Network → right-click the request → Copy as cURL. Pasting it reproduces the headers and cookies exactly, which is the fastest way to debug an API behind authentication.

Careful: what you copied contains session cookies and tokens. Strip them before pasting into an issue or a chat.

Next

For syntax that’s easier to read and write → HTTPie

Last updated 19 Aug 2026, 00:00 UTC. history