The curl command in Linux
curl transfers data to or from a URL. For developers it is the universal API testing tool: GET, POST, custom headers, authentication, file uploads — everything an HTTP client does, scriptable from the shell. If a service has an API, someone is poking it with curl right now.
How curl works
curl walks the whole client-side journey of a URL: parse it, resolve DNS, open TCP, negotiate TLS (certificate verification included), send an HTTP request, stream back the response — and print the body to stdout, because in the Unix worldview a URL is just another source of bytes to compose with pipes. Run with -v and each of those phases is narrated; most "the API doesn't work" mysteries die right there, visible as a DNS failure, a certificate mismatch or an unexpected 301.
Two design choices explain most day-one surprises. curl does not follow redirects unless told (-L) — it faithfully shows you the 301 rather than the page behind it. And it separates the body (stdout) from diagnostics (stderr), so pipelines receive pure payload. Underneath sits libcurl, the same engine embedded in cars, TVs and a substantial fraction of all software on Earth — the command-line tool is a thin veneer over one of the most deployed libraries in existence.
Syntax
curl [OPTIONS] URL Common options
| Option | What it does |
|---|---|
-o FILE | Write output to a file instead of the terminal. |
-O | Save with the remote file's own name. |
-L | Follow redirects (essential — many URLs redirect). |
-I | Fetch headers only (HEAD request). |
-X METHOD | Set the HTTP method: POST, PUT, DELETE… |
-H "Header: value" | Add a request header. |
-d DATA | Send a request body (implies POST). |
-u user:pass | HTTP basic authentication. |
-s | Silent: no progress bar (for scripts). |
How to use curl: examples
$ curl https://api.github.com/users/torvalds GET a URL and print the response body.
$ curl -LO https://example.com/app.tar.gz Download a file, following redirects, keeping its name.
$ curl -I https://example.com See only the response headers — status code, content type, caching.
$ curl -X POST -H "Content-Type: application/json" -d '{"name":"test"}' https://api.example.com/items POST JSON to an API — the canonical API-testing one-liner.
$ curl -s https://api.example.com/data | python3 -m json.tool Pretty-print a JSON response by piping it through a formatter (or jq).
$ curl -u admin:secret https://example.com/admin Request a page behind basic auth.
Real-world use cases for curl
Testing an API during development
Before writing a single line of client code, hit the endpoint: curl -s -X POST -H "Content-Type: application/json" -d '{"email":"a@b.c"}' localhost:3000/api/users | jq. Wrong status, missing header, malformed JSON — everything surfaces here first, with the exact request visible.
Health checks and monitoring
curl -s -o /dev/null -w "%{http_code} %{time_total}s" https://example.com prints just the status code and response time — the one-liner behind countless uptime scripts and deploy verification steps.
Pro tips and common mistakes
- curl -w "%{http_code}" (write-out) extracts response metadata: status, timings, sizes — perfect for scripts.
- Long commands stay readable with line continuations: end each line with a backslash.
- curl -sS in scripts: silent progress, but errors still print. The bare -s eats error messages too.
- Save and reuse cookies across requests with -c jar.txt (save) and -b jar.txt (send) — enough to script simple login flows.
- Piping curl straight into bash (curl url | bash) executes unreviewed remote code — download first, read, then run.
Frequently asked questions about curl
What is the difference between curl and wget?
wget is a downloader: recursive fetching, resume support, mirror mode. curl is an HTTP swiss-army knife: any method, headers, auth schemes, and it prints to stdout by default. Rule of thumb: download a site → wget; talk to an API → curl.
How do I send JSON with curl?
Set the header and body: curl -X POST -H "Content-Type: application/json" -d '{"key":"value"}' URL. Use single quotes around the JSON so the inner double quotes survive.
Why does curl print nothing for some URLs?
The server probably answered with a redirect (301/302) and an empty body. Add -L to follow redirects, or -I to see what the response actually was.
Related commands
Find lines matching a pattern in files or piped input — the workhorse of text search.
sshLog into remote machines, run remote commands, use keys instead of passwords, and tunnel ports.
wgetDownload files and whole sites, resume interrupted transfers, and fetch in the background.