curl is the universal HTTP client. Every developer should know it well—for debugging, testing, and automation.
Basic Requests# 1
2
3
4
5
6
7
8
9
10
11
# GET (default)
curl https://api.example.com/users
# POST with data
curl -X POST https://api.example.com/users \
-d '{"name":"alice"}'
# With headers
curl -H "Content-Type: application/json" \
-H "Authorization: Bearer token123" \
https://api.example.com/users
JSON APIs# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# POST JSON (sets Content-Type automatically)
curl -X POST https://api.example.com/users \
--json '{"name":"alice","email":"alice@example.com"}'
# Or explicitly
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-d '{"name":"alice"}'
# Pretty print response
curl -s https://api.example.com/users | jq .
# From file
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-d @payload.json
HTTP Methods# 1
2
3
4
5
6
7
curl -X GET https://api.example.com/users/1
curl -X POST https://api.example.com/users -d '...'
curl -X PUT https://api.example.com/users/1 -d '...'
curl -X PATCH https://api.example.com/users/1 -d '...'
curl -X DELETE https://api.example.com/users/1
curl -X HEAD https://api.example.com/users # Headers only
curl -X OPTIONS https://api.example.com/users # CORS preflight
Authentication# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Bearer token
curl -H "Authorization: Bearer eyJhbGc..." \
https://api.example.com/me
# Basic auth
curl -u username:password https://api.example.com/users
# Or
curl -H "Authorization: Basic $( echo -n 'user:pass' | base64) " \
https://api.example.com/users
# API key in header
curl -H "X-API-Key: secret123" https://api.example.com/data
# API key in query
curl "https://api.example.com/data?api_key=secret123"
Response Inspection# 1
2
3
4
5
6
7
8
9
10
11
12
13
# Show headers
curl -I https://api.example.com/users # HEAD request
curl -i https://api.example.com/users # Include headers with body
# Verbose (see full request/response)
curl -v https://api.example.com/users
# Just status code
curl -s -o /dev/null -w "%{http_code}" https://api.example.com/users
# Multiple stats
curl -s -o /dev/null -w "code: %{http_code}\ntime: %{time_total}s\nsize: %{size_download} bytes\n" \
https://api.example.com/users
File Uploads# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Form upload
curl -X POST https://api.example.com/upload \
-F "file=@document.pdf"
# Multiple files
curl -X POST https://api.example.com/upload \
-F "file1=@doc1.pdf" \
-F "file2=@doc2.pdf"
# With additional form fields
curl -X POST https://api.example.com/upload \
-F "file=@photo.jpg" \
-F "description=Profile photo" \
-F "public=true"
# Binary data
curl -X POST https://api.example.com/upload \
-H "Content-Type: application/octet-stream" \
--data-binary @file.bin
Handling Redirects# 1
2
3
4
5
6
7
8
# Follow redirects
curl -L https://example.com/shortened-url
# Show redirect chain
curl -L -v https://example.com/shortened-url 2>& 1 | grep "< location"
# Limit redirects
curl -L --max-redirs 3 https://example.com/url
Timeouts and Retries# 1
2
3
4
5
6
7
8
9
10
11
# Connection timeout (seconds)
curl --connect-timeout 5 https://api.example.com/
# Max time for entire operation
curl --max-time 30 https://api.example.com/slow-endpoint
# Retry on failure
curl --retry 3 --retry-delay 2 https://api.example.com/
# Retry on specific errors
curl --retry 3 --retry-all-errors https://api.example.com/
Saving Output# 1
2
3
4
5
6
7
8
9
10
11
# Save to file
curl -o response.json https://api.example.com/users
# Use remote filename
curl -O https://example.com/file.zip
# Save headers separately
curl -D headers.txt -o body.json https://api.example.com/users
# Append to file
curl https://api.example.com/users >> all_responses.json
Cookie Handling# 1
2
3
4
5
6
7
8
9
10
11
12
# Send cookies
curl -b "session=abc123; token=xyz" https://api.example.com/
# Save cookies to file
curl -c cookies.txt https://api.example.com/login \
-d "user=admin&pass=secret"
# Use saved cookies
curl -b cookies.txt https://api.example.com/dashboard
# Both save and send
curl -b cookies.txt -c cookies.txt https://api.example.com/
Testing Webhooks# 1
2
3
4
5
6
7
8
9
10
11
12
# Simulate GitHub webhook
curl -X POST http://localhost:3000/webhook \
-H "Content-Type: application/json" \
-H "X-GitHub-Event: push" \
-H "X-Hub-Signature-256: sha256=..." \
-d @github-payload.json
# Stripe webhook
curl -X POST http://localhost:3000/stripe/webhook \
-H "Content-Type: application/json" \
-H "Stripe-Signature: t=...,v1=..." \
-d @stripe-event.json
SSL/TLS Options# 1
2
3
4
5
6
7
8
# Skip certificate verification (development only!)
curl -k https://self-signed.example.com/
# Use specific CA bundle
curl --cacert /path/to/ca-bundle.crt https://api.example.com/
# Client certificate
curl --cert client.crt --key client.key https://mtls.example.com/
Proxy Configuration# 1
2
3
4
5
6
7
8
# HTTP proxy
curl -x http://proxy:8080 https://api.example.com/
# SOCKS5 proxy
curl --socks5 localhost:1080 https://api.example.com/
# No proxy for specific hosts
curl --noproxy "localhost,*.internal" https://api.example.com/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Time breakdown
curl -s -o /dev/null -w "\
namelookup: %{time_namelookup}s\n\
connect: %{time_connect}s\n\
appconnect: %{time_appconnect}s\n\
pretransfer: %{time_pretransfer}s\n\
redirect: %{time_redirect}s\n\
starttransfer: %{time_starttransfer}s\n\
total: %{time_total}s\n" \
https://api.example.com/
# Loop for load testing (basic)
for i in { 1..100} ; do
curl -s -o /dev/null -w "%{http_code} %{time_total}\n" \
https://api.example.com/
done
Config Files# Create ~/.curlrc for defaults:
# # # # - - - - A l D m S s U u l o e a h h s s w c f x o o e e a a a - w w r r y t u t - - s i l i e e a a o t m r r g g f n e r r e e o t o o n n l i 3 r r t t l m 0 s o e " w o m u y r t c e u d r i l r / e 1 c . t 0 s " Practical Scripts# Health Check# 1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
URL = "https://api.example.com/health"
STATUS = $( curl -s -o /dev/null -w "%{http_code}" --max-time 5 " $URL " )
if [ " $STATUS " = "200" ] ; then
echo "OK"
exit 0
else
echo "FAIL: HTTP $STATUS "
exit 1
fi
API Test Suite# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash
BASE = "https://api.example.com"
TOKEN = "Bearer $( cat .token) "
# Test endpoints
test_endpoint() {
local method = $1 path = $2 expected = $3
status = $( curl -s -o /dev/null -w "%{http_code}" \
-X " $method " -H "Authorization: $TOKEN " " $BASE$path " )
if [ " $status " = " $expected " ] ; then
echo "✓ $method $path "
else
echo "✗ $method $path (got $status , expected $expected )"
fi
}
test_endpoint GET /users 200
test_endpoint GET /users/1 200
test_endpoint GET /users/999 404
test_endpoint POST /users 401 # No body
test_endpoint DELETE /admin 403
Download with Progress# 1
2
curl -L -# -o large-file.zip \
https://example.com/large-file.zip
Common Options Reference# Option Purpose -X METHODHTTP method -H "Header: value"Add header -d "data"POST data -F "field=value"Form data -o fileOutput to file -OUse remote filename -LFollow redirects -vVerbose -sSilent -iInclude headers -IHeaders only -u user:passBasic auth -b cookiesSend cookies -c fileSave cookies -kInsecure (skip TLS verify) --max-time NTimeout --retry NRetry count
curl is the debugging tool you’ll use for the rest of your career. Master it.
📬 Get the Newsletter Weekly insights on DevOps, automation, and CLI mastery. No spam, unsubscribe anytime.