curl Command in Linux: Syntax, Options & Practical Examples

Deepak Prasad
Tested on Ubuntu 25.04 (Plucky Puffin)
Package curl 8.12.1
curl 8.12.1
Applies to Ubuntu, Debian, RHEL, Rocky Linux, AlmaLinux, Oracle Linux, CentOS Stream, Fedora, Arch Linux, SUSE, openSUSE, Alpine
Privilege sudo or root
Man page curl(1)
Scope curl transfers data over HTTP, HTTPS, FTP, and other protocols from the shell. Use it to fetch URLs, inspect headers, download files, and send POST and JSON payloads when testing APIs or debugging connectivity.
Related guides Install curl on Ubuntu
grep
Linux commands

curl — quick reference

Fetch and save

Transfer URL content to stdout or to a file. Examples use https://example.com — a safe documentation domain.

When to use Command
Print response body to the terminal curl -s --connect-timeout 5 -m 10 https://example.com
Save under a chosen filename curl -s -o page.html --connect-timeout 5 -m 10 https://example.com
Save using the remote filename from the URL curl -s -O --connect-timeout 5 -m 10 https://example.com/index.html
Redirect body to a file with shell redirection curl -s --connect-timeout 5 -m 10 https://example.com > page.html

HTTP inspection and redirects

When to use Command
Fetch response headers only (HEAD) curl -sI --connect-timeout 5 -m 10 https://example.com
Include response headers with the body curl -si --connect-timeout 5 -m 10 https://example.com
Print only the HTTP status code curl -s -o /dev/null -w '%{http_code}\n' --connect-timeout 5 -m 10 https://example.com
Follow redirects to the final URL curl -sL --connect-timeout 5 -m 10 https://example.com

Script-friendly behavior

When to use Command
Silent mode — no progress meter curl -s URL
Fail silently on HTTP 4xx/5xx (non-zero exit) curl -sf URL
Show errors even when -s is set curl -sS URL

POST, JSON, and custom headers

Use httpbin.org for safe POST echo tests — it reflects what you sent.

When to use Command
POST form fields curl -s -d 'key=value' --connect-timeout 5 -m 20 https://httpbin.org/post
POST JSON with a Content-Type header curl -s -H 'Content-Type: application/json' -d '{"key":"value"}' https://httpbin.org/post
Send a custom request header curl -s -H 'X-Test: demo' https://httpbin.org/headers
Explicit POST method (when not implied by -d) curl -s -X POST -d 'a=1' https://httpbin.org/post

Authentication, TLS, and debugging

When to use Command
HTTP basic authentication curl -s -u user:pass https://example.com
Verbose connection and TLS trace curl -sv --connect-timeout 5 -m 10 https://example.com
Skip TLS certificate verification (lab only) curl -sk https://self-signed.example

Timeouts and local testing

When to use Command
Limit time to connect (seconds) curl --connect-timeout 5 https://example.com
Limit total transfer time (seconds) curl -m 30 https://example.com
Hit a local service without a proxy curl -s --noproxy '*' http://127.0.0.1:8080/

Help and version

When to use Command
Show common options curl --help
List all options curl --help all
Show curl and libcurl version curl -V

curl — command syntax

Synopsis from curl --help on Ubuntu 25.04 (curl 8.12.1):

text
curl [options...] <url>

curl writes the response body to stdout by default. Use -o or -O to save to a file. Combine -s with -w for script-friendly status checks. On hosts with an HTTP proxy in the environment, add --noproxy '*' when testing 127.0.0.1 locally.


curl — command examples

Essential Fetch a URL and print the body

The simplest GET request prints HTML or API output to the terminal. -s hides the progress bar; timeouts keep accidental hangs short.

Run the command:

bash
curl -s --connect-timeout 5 -m 10 https://example.com | head -c 200

Sample output (truncated):

text
<!doctype html><html lang="en"><head><title>Example Domain</title><link rel="icon" href="data:,"><meta name="viewport" content="width=device-width, initial-scale=1"><style>body{background:#eee;width:6

Pipe to grep, jq, or a file when you need structured processing.

Essential Response headers with -I

-I sends a HEAD request — headers only, no body. Use it to check status, Content-Type, and cache headers quickly.

Run the command:

bash
curl -sI --connect-timeout 5 -m 10 https://example.com

Sample output:

output
HTTP/2 200 
date: Wed, 01 Jul 2026 12:23:09 GMT
content-type: text/html
server: cloudflare
last-modified: Tue, 30 Jun 2026 20:56:01 GMT
allow: GET, HEAD
accept-ranges: bytes

The first line is the HTTP status — 200 means the resource is reachable.

Essential Download to a chosen filename with -o

-o writes the response to a path you specify — good when the URL filename is ugly or missing.

Run the command:

bash
curl -s -o /tmp/example-page.html --connect-timeout 5 -m 10 https://example.com
wc -c /tmp/example-page.html
rm -f /tmp/example-page.html

Sample output:

output
559 /tmp/example-page.html

Use -O instead when you want the last path segment of the URL as the local name.

Common Print only the HTTP status code

-w (write-out) formats metadata after the transfer. Send the body to /dev/null when you only care about the code.

Run the command:

bash
curl -s -o /dev/null -w '%{http_code}\n' --connect-timeout 5 -m 10 https://example.com

Sample output:

output
200

In scripts, combine with -f to treat 4xx/5xx as failure without parsing text output.

Common Follow redirects with -L

curl does not follow redirects by default. -L (or --location) requests each redirect target until a final response.

Run the command:

bash
curl -sI -L --connect-timeout 5 -m 10 http://example.com | grep -E '^HTTP' | head -3

Sample output:

output
HTTP/1.1 200 OK

Without -L, you might stop at a 301/302 with an empty body — add -L when the URL chain matters.

Common POST form data with -d

-d sends a POST body. By default curl uses application/x-www-form-urlencoded. httpbin echoes the form for testing.

Run the command:

bash
curl -s --noproxy '*' -d 'name=test&role=demo' --connect-timeout 5 -m 20 https://httpbin.org/post | grep -A3 '"form"'

Sample output:

output
"form": {
    "name": "test", 
    "role": "demo"
  },

Replace the URL with your API endpoint in production; keep httpbin for labs and CI smoke tests.

Common POST JSON with a Content-Type header

APIs expect Content-Type: application/json when the body is JSON. Quote the payload carefully in the shell.

Run the command:

bash
curl -s --noproxy '*' -H 'Content-Type: application/json' \
  -d '{"key":"value"}' --connect-timeout 5 -m 20 https://httpbin.org/post | grep -E '"json"|"data"' | head -4

Sample output:

output
"data": "{\"key\":\"value\"}", 
  "json": {
    "key": "value"
  },

httpbin parses JSON when the header is set — your API may return a different shape; pipe to jq when available.

Common Send a custom header

Repeat -H for multiple headers — tokens, correlation IDs, or Accept negotiation.

Run the command:

bash
curl -s --noproxy '*' -H 'X-Test: demo' --connect-timeout 5 -m 20 https://httpbin.org/headers | grep X-Test

Sample output:

output
"X-Test": "demo"

Never paste production secrets into shell history — use environment variables or a netrc file for credentials.

Advanced Debug connection and TLS with -v

-v traces resolution, TCP, TLS handshake, and request headers on stderr — first stop for HTTPS failures.

Run the command:

bash
curl -sv --noproxy '*' --connect-timeout 5 -m 10 https://example.com 2>&1 | head -18

Sample output:

output
* Host example.com:443 was resolved.
* IPv6: (none)
* IPv4: 172.66.147.243, 104.20.23.154
*   Trying 172.66.147.243:443...
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.3 (IN), TLS handshake, Server hello (2):

Look for certificate errors, proxy CONNECT lines, and which IP address was tried.

Advanced Fail on HTTP errors with -f

-f (--fail) makes curl exit non-zero on HTTP 4xx/5xx instead of printing an error page body — useful in scripts.

Run the command:

bash
curl -sf --noproxy '*' --connect-timeout 5 -m 10 -o /dev/null -w '%{http_code}\n' https://example.com/not-found
echo exit:$?

Sample output:

output
404
exit:22

Exit code 22 means HTTP error with -f. A successful 200 response returns exit 0.


curl — when to use / when not

Use curl when Use something else when
  • You need HTTP/HTTPS from scripts — GET, POST, headers, status codes
  • You are debugging TLS, redirects, or API payloads
  • You want fine control over headers, methods, and write-out formats
  • You upload or download with auth, cookies, or many protocols (FTP, SFTP, …)
  • You want recursive website mirrors or simple file fetch → wget
  • You need rendered HTML in the terminal → elinks
  • You only need reachability, not HTTP → ping or dig

curl vs wget

curl wget
Primary strength APIs, headers, many protocols, upload Non-interactive downloads and mirroring
Output default stdout Saves to file
Recursive crawl No Yes (-r, -p)
REST testing Excellent (-H, -d, -X) Possible but less ergonomic
Typical use CI checks, API calls, debugging Bulk downloads, static site mirrors

Both are standard on Linux — curl for HTTP semantics, wget for pull-down and mirror jobs.


curl — interview corner

What is curl used for?

curl is a command-line client for transferring data with URLs. It speaks HTTP, HTTPS, FTP, SFTP, and many other protocols via libcurl.

Admins and developers use it to download files, probe APIs, inspect headers, and debug TLS — especially in scripts where a GUI browser is unavailable.

A strong answer is:

"curl transfers data from URLs — mostly HTTP/HTTPS for API tests, downloads, and header checks. It's script-friendly and supports dozens of protocols through libcurl."

What is the difference between curl and wget?

wget excels at non-interactive downloads and recursive mirroring — -O, -r, -p.

curl excels at HTTP control — custom methods and headers, -w write-out, uploads, and multi-protocol clients.

Rule of thumb: wget to pull files; curl to talk to APIs and inspect HTTP behavior.

A strong answer is:

"wget for mirroring and simple downloads; curl for APIs, headers, POST bodies, and protocol flexibility."

Does curl follow redirects by default?

No. Without -L, curl returns the redirect response (for example 301/302) and does not fetch the final URL automatically.

Add -L (--location) to follow redirects — common when a short URL expands to the real endpoint.

A strong answer is:

"Redirects are off by default — I add -L when I need the final URL after HTTP redirects."

How do you use curl in shell scripts?

Common pattern:

bash
code=$(curl -sf -o /dev/null -w '%{http_code}' --connect-timeout 5 -m 30 https://example.com)
  • -s — no progress meter
  • -f — fail on HTTP errors
  • -w — print status code
  • -o /dev/null — discard body when only the code matters

Add -S to show errors while staying silent on success output.

A strong answer is:

"I use curl -sf with -w for status codes and timeouts, often discarding the body to /dev/null when checking health endpoints."

When is curl -k appropriate?

-k (--insecure) skips TLS certificate verification. It is only for local labs with self-signed certs — never as a permanent fix on production traffic.

Fix the trust chain (install CA, use Let's Encrypt, correct hostname) instead of leaving -k in scripts.

A strong answer is:

"-k bypasses cert verification — okay briefly in a dev lab with self-signed certs; in production I fix CA trust instead."


Troubleshooting

Symptom Likely cause Fix
Could not resolve host DNS failure or typo Check URL spelling; dig hostname
Connection timed out Firewall, wrong port, or dead host Verify service listens; add --connect-timeout
TLS / certificate errors Expired cert, hostname mismatch, missing CA curl -v for details; fix server cert — avoid -k in prod
Empty body but 301/302 Redirect not followed Add -L
Localhost hits a proxy http_proxy / https_proxy set curl --noproxy '*' http://127.0.0.1:PORT/
HTTP 200 but script fails Missing -f conflated with success body Use -f and check exit code; -w '%{http_code}'
curl: command not found Package missing sudo apt install curl

References

Rohan Timalsina

is a technical writer and Linux enthusiast who writes practical guides on Linux commands and system administration. He focuses on simplifying complex topics through clear explanations.

  • Linux
  • HTML5
  • JavaScript
  • Web Design
  • Front-end Web Development