Curl Commands

The commands people reach for most, in one place and ready to copy. The one below is worth learning by heart: quiet unless something breaks, follows redirects, saves the body, and prints the status code.

Last updated . How this page is checked.

The command

curl -sS -L -o response.json -w "%{http_code}\n" https://httpbin.org/json

Everyday curl commands

TaskCommand
Fetch a URLcurl URL
Show response headers with the bodycurl -i URL
Print only the status codecurl -s -o /dev/null -w "%{http_code}" URL
Send JSONcurl -H "Content-Type: application/json" -d '{"a":1}' URL
Send form fieldscurl -d "name=Ada" -d "role=admin" URL
Upload a filecurl -F "file=@report.pdf" URL
Log in with a passwordcurl -u user:password URL
Send a tokencurl -H "Authorization: Bearer TOKEN" URL
Follow redirectscurl -L URL
Download a file under its own namecurl -LO URL
Resume an interrupted downloadcurl -C - -O URL
Give up after 20 secondscurl --max-time 20 URL
Show everything curl doescurl -v URL

Commands for finding out where the time went

When a request is slow, the total alone does not say why. Curl records a timestamp at each stage and prints them through write-out variables: name lookup, TCP connect, the end of the TLS handshake, the first byte of the response, and the finish. Each value is measured from the start, so the gap between two neighbours is the cost of that stage. A long wait before the first byte with fast earlier stages points at the server, not the network.

curl -s -o /dev/null https://httpbin.org/get -w "dns        %{time_namelookup}s
connect    %{time_connect}s
tls        %{time_appconnect}s
first byte %{time_starttransfer}s
total      %{time_total}s
"

Commands for scripts

An unattended command needs three properties that an interactive one does not. It must stay silent on success yet still print real errors, which is -sS. It must turn an HTTP error into a failing exit status, which is -f. And it must not wait for ever, which is --max-time, with --retry for faults that clear up by themselves. When the script needs to branch on the status code instead, send the body to a file and capture the code in a variable.

# fail loudly, stay quiet otherwise, retry transient errors
curl -fsS --retry 3 --max-time 20 -o data.json https://httpbin.org/json

# body to a file, status code to a variable
status=$(curl -s -o body.json -w "%{http_code}" https://httpbin.org/status/404)
echo "status: $status"

Commands for several requests at once

One curl command can make many requests, and reuses its connection between them. Square brackets in a URL expand to a numeric range and braces to a list; #1 in the output name stands for the current value. --parallel runs the transfers side by side (curl 7.66+). To send requests that differ in more than the URL, separate them with --next, which starts a fresh set of options.

curl -s "https://httpbin.org/anything/page/[1-3]" -o "page_#1.json"
curl -s --parallel --parallel-max 4 "https://httpbin.org/delay/{1,2}" -o "delay_#1.json"
curl -s https://httpbin.org/get --next -s -d "a=1" https://httpbin.org/post

Common mistakes

  • A copied command brings its quoting style with it. Single-quoted JSON works in bash and zsh and breaks in the Windows command prompt; the Windows page shows the equivalents.
  • -o and -O overwrite without asking. Check the target name before running a download in a directory that matters.
  • Flags before --next do not apply after it. Repeat -s, headers and credentials for each group.

Related curl examples

More under Reference

References

These links leave api-tester.com, which is independent of the projects they point to.

FAQ

What are the basic curl commands?

curl URL fetches a page, curl -i URL adds the response headers, curl -d "data" URL sends a POST, curl -H "Name: value" URL adds a header, curl -L URL follows redirects and curl -O URL downloads a file.

How do I see how long a curl request takes?

Use -w with timing variables, for example curl -s -o /dev/null -w "%{time_total}" URL. Variables such as time_namelookup, time_connect and time_starttransfer break the total into stages.

How do I run several curl requests in one command?

List several URLs after curl, put a range such as [1-10] in the URL, or separate differently configured requests with --next. Add --parallel to run them at the same time.