curl Mastery
Overview
curl is the Swiss Army knife of HTTP. Master these patterns for API debugging, automation, security testing, and data extraction.
Essential Options
| Option | Purpose | Example |
|---|---|---|
|
Silent (no progress) |
|
|
Show errors with silent |
|
|
Fail silently on HTTP errors |
|
|
Follow redirects |
|
|
Output to file |
|
|
Save with remote filename |
|
|
Headers only (HEAD request) |
|
|
Include headers in output |
|
|
Verbose (debug) |
|
|
Skip TLS verification |
|
|
Custom output format |
|
HTTP Methods
# GET (default)
curl https://api.example.com/users
# POST with JSON
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-d '{"name": "John", "email": "john@example.com"}'
# PUT
curl -X PUT https://api.example.com/users/123 \
-H "Content-Type: application/json" \
-d '{"name": "John Updated"}'
# PATCH
curl -X PATCH https://api.example.com/users/123 \
-H "Content-Type: application/json" \
-d '{"email": "new@example.com"}'
# DELETE
curl -X DELETE https://api.example.com/users/123
# HEAD (check if resource exists)
curl -I https://api.example.com/users/123
Authentication
Basic Auth
# Inline (avoid - visible in history)
curl -u username:password https://api.example.com
# Prompt for password
curl -u username https://api.example.com
# From variable (better)
curl -u "$USER:$PASS" https://api.example.com
# Netrc file (best for automation)
curl -n https://api.example.com
# Requires ~/.netrc with: machine api.example.com login USER password PASS
Headers
# Single header
curl -H "Accept: application/json" https://api.example.com
# Multiple headers
curl -H "Accept: application/json" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Request-ID: $(uuidgen)" \
https://api.example.com
# Custom User-Agent
curl -A "MyApp/1.0" https://api.example.com
# Referer
curl -e "https://google.com" https://example.com
Data Sending
JSON Body
# Inline JSON
curl -X POST https://api.example.com/data \
-H "Content-Type: application/json" \
-d '{"key": "value"}'
# From file
curl -X POST https://api.example.com/data \
-H "Content-Type: application/json" \
-d @payload.json
# From stdin
echo '{"key": "value"}' | curl -X POST https://api.example.com/data \
-H "Content-Type: application/json" \
-d @-
Form Data
# URL-encoded form
curl -X POST https://example.com/login \
-d "username=admin&password=secret"
# Multipart form (file upload)
curl -X POST https://example.com/upload \
-F "file=@/path/to/file.pdf" \
-F "description=My document"
# Multiple files
curl -X POST https://example.com/upload \
-F "files[]=@file1.jpg" \
-F "files[]=@file2.jpg"
Response Processing
JSON Response with jq
# Pretty print
curl -s https://api.example.com/users | jq
# Extract field
curl -s https://api.example.com/users | jq '.[0].name'
# Filter array
curl -s https://api.example.com/users | jq '.[] | select(.active == true)'
# Transform to CSV
curl -s https://api.example.com/users | jq -r '.[] | [.id, .name, .email] | @csv'
Timing and Performance
Detailed Timing
curl -w @- -o /dev/null -s https://example.com << 'EOF'
time_namelookup: %{time_namelookup}s
time_connect: %{time_connect}s
time_appconnect: %{time_appconnect}s
time_pretransfer: %{time_pretransfer}s
time_redirect: %{time_redirect}s
time_starttransfer: %{time_starttransfer}s
----------
time_total: %{time_total}s
EOF
TLS/SSL Inspection
API Patterns
Cloudflare API
# Verify token
curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
https://api.cloudflare.com/client/v4/user/tokens/verify | jq
# List zones
curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
https://api.cloudflare.com/client/v4/zones | jq '.result[] | {name, id}'
# Create DNS record
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"A","name":"test","content":"10.0.0.1","ttl":1}' | jq
GitHub API
# User info
curl -s -H "Authorization: token $GITHUB_TOKEN" \
https://api.github.com/user | jq '{login, name, email}'
# List repos
curl -s -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/user/repos?per_page=100" | jq '.[].full_name'
# Create repo
curl -s -X POST -H "Authorization: token $GITHUB_TOKEN" \
https://api.github.com/user/repos \
-d '{"name":"new-repo","private":true}' | jq
GitLab API
# List projects
curl -s -H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://gitlab.com/api/v4/projects?owned=true" | jq '.[].path_with_namespace'
# Create project
curl -s -X POST -H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://gitlab.com/api/v4/projects" \
-d "name=new-project&visibility=private" | jq
Loops and Automation
Pagination
page=1
while true; do
response=$(curl -s "https://api.example.com/items?page=$page&per_page=100")
count=$(echo "$response" | jq 'length')
[[ "$count" == "0" ]] && break
echo "$response" | jq -r '.[].name'
((page++))
done
Security Testing
Check Security Headers
curl -sI https://example.com | grep -iE '^(strict-transport|x-frame|x-content-type|content-security|x-xss)'
Test CORS
curl -sI -H "Origin: https://attacker.com" https://api.example.com | grep -i access-control
Proxy and Network
One-Liners
Config File
Create ~/.curlrc for persistent defaults:
# Progress bar
progress-bar
# Follow redirects
location
# Silent mode
silent
# Show errors
show-error
# User agent
user-agent = "MyCLI/1.0"
# Default headers
header = "Accept: application/json"