curl follow redirects Guide: Master From Basics to Advanced
Enable and customize redirect handling in curl, preserve methods, debug chains, and integrate GoProxy for reliable scraping.
Oct 21, 2025
Practical curl get guide with examples, headers, auth, redirects, retries, partial downloads and troubleshooting.
cURL is versatile and powerful in web development, API testing, and data retrieval. It performs an HTTP GET by default — use it to fetch endpoints, save responses, add headers/auth, follow redirects, resume downloads, automate with retries/backoff, and diagnose network or TLS issues. This guide walks you from one-line commands to production-ready scripts with examples and troubleshooting tips.
Who this guide is for
If you only need one command, go to One-line Quick Start. If you plan to script or automate, follow Beginner → Intermediate → Advanced.
Simple GET (prints body):
curl https://api.example.com/endpoint
Expected: response body (HTML or JSON) printed to terminal.
Save to file:
curl -o response.json https://api.example.com/endpoint
Expected: file response.json created with response body.
Show headers + body:
curl -i https://api.example.com/endpoint
Expected: HTTP response headers appear, then the body.
curl is a compact, cross-platform command-line tool (and library) for transferring data with URLs. It supports many protocols (HTTP/HTTPS, FTP, etc.), advanced options (headers, cookies, TLS settings, HTTP/2/3), and is designed to run interactively or in scripts/CI.
An HTTP GET requests a representation of a resource (web page, file, or JSON). Parameters are typically placed in the URL query string. GET requests are intended to retrieve data without changing server state.
Instant, reproducible testing of endpoints.
Scriptable for automation, monitoring, and CI tasks.
Low dependency and available in minimal environments.
Full debugging visibility: headers, TLS handshake, redirects (-v, -i, --trace).
Fine control: headers, cookies, partial download, retry/backoff, and bandwidth throttling.
Avoid using curl for large-scale scraping or high-concurrency crawling — prefer official bulk APIs or dedicated data platforms and always respect site policies.
Before we jump into commands, ensure cURL is installed.
curl --version
This prints the curl version and compiled features (e.g., HTTP/2 or HTTP/3, SSL backend). If it prints a version, you’re ready.
Debian/Ubuntu:
sudo apt update && sudo apt install curl
Red Hat / Fedora:
sudo dnf install curl
Arch family:
sudo pacman -S curl
macOS: often preinstalled; verify with curl --version. Use your system’s package manager to update if needed.
Windows: recent system versions include a curl binary. In PowerShell, call curl.exe if behavior differs.
command not found: ensure installation completed and PATH includes the binary; reopen your terminal.
Older curl missing flags: update via your package manager.
curl https://example.com/path
Expected: raw response printed to terminal.
curl -o file.txt https://example.com/path
Expected: file.txt contains the response.
Use -O to save with the remote filename when appropriate.
Headers + body:
curl -i https://example.com/path
Headers only (HEAD request):
curl -I https://example.com/path
Append manually:
curl 'https://api.example.com/search?q=hello%20world&limit=10'
Safer (automatic encoding) — preferred in scripts:
curl -G --data-urlencode "q=hello world" -d "limit=10" https://api.example.com/search
Important: without -G, -d will send a POST. With -G, -d becomes URL query parameters for GET.
curl -H "Accept: application/json" -H "User-Agent: CLI-Client/1.0" https://api.example.com/endpoint
What to check: verify HTTP status and inspect response structure (JSON keys or HTML content).
Basic auth
curl -u 'username:password' https://api.example.com/secure
Bearer token
curl -H "Authorization: Bearer $API_TOKEN" https://api.example.com/user
Tip: store tokens in environment variables; do not hardcode them.
Save cookies after login(cookie jar):
curl -c cookies.txt -d "username=myuser&password=$PASS" https://site.example/login
Reuse saved cookies:
curl -b cookies.txt https://site.example/dashboard
Login + follow redirects while saving cookies:
curl -s -c cookies.txt -d "username=myuser&password=$PASS" https://site.example/login
curl -s -b cookies.txt -L https://site.example/dashboard
curl -L https://short.example/abc
curl -s -o /dev/null -w '%{url_effective}\n' -L https://short.example/abc
For details, please check our curl follow redirects Guide.
Resume a download:
curl -C - -o bigfile.zip https://cdn.example.com/bigfile.zip
Download a byte range:
curl -r 0-999 -o head.part https://cdn.example.com/video.mp4
Quick verbose:
curl -v https://api.example.com/
Full trace (ASCII) to file:
curl --trace-ascii trace.txt https://api.example.com/
Built-in retry options:
curl --retry 5 --retry-delay 2 --retry-connrefused -O https://api.example.com/resource
Use scripted exponential backoff for complex needs (see Recipes).
curl -f -s -S -o response.json https://api.example.com/data || echo "Request failed"
Notes: -f exits non-zero on HTTP 4xx/5xx; -s silences progress; -S shows errors when -s is used.
status=$(curl -s -w '%{http_code}' -o response.json https://api.example.com/data)
echo "HTTP status: $status"
curl -s -D headers.txt -o body.json https://api.example.com/data
Check: headers.txt contains response headers; body.json contains the payload.
cat urls.txt | xargs -n1 -P6 curl -O
Warning: respect rate limits and server load — prefer bulk APs when available.
curl --limit-rate 100K -o partial.json https://api.example.com/large
HTTP/2:
curl -I --http2 https://api.example.com/
HTTP/3 (if supported):
curl --http3 https://api.example.com/
Note: not all builds support newer protocols; check curl --version.
curl -v --connect-timeout 10 https://api.example.com/
For testing only (unsafe): -k disables verification.
Safer: provide CA bundle:
curl --cacert /path/to/ca.pem https://secure.example.com/
Verify path & query string. Test with:
curl -I https://api.example.com/resource
Check credentials and required headers (Authorization, User-Agent).
Inspect Retry-After:
curl -sI https://api.example.com/endpoint | grep -i '^Retry-After:'
Add delays/backoff and reduce concurrency.
Use -v to see the Location chain and identify the loop.
status=$(curl -s -w '%{http_code}' -o response.json \
-H "Accept: application/json" -H "Authorization: Bearer $API_TOKEN" \
"https://api.example.com/user")
if [ "$status" -ne 200 ]; then
echo "Request failed with status $status"
exit 1
fi
# response.json contains the payload
cursor=""
while :; do
url="https://api.example.com/items?limit=100${cursor:+&cursor=$cursor}"
result=$(curl -s -H "Authorization: Bearer $API_TOKEN" "$url")
echo "$result" > "page_${cursor:-start}.json"
next=$(echo "$result" | python -c "import sys,json; j=json.load(sys.stdin); print(j.get('next',''))")
[ -z "$next" ] && break
cursor=$next
sleep 1 # polite delay
done
attempt=0
max=5
delay=1
url="https://cdn.example.com/dataset.zip"
outfile="dataset.zip"
until curl --retry 3 --retry-delay 5 -C - -o "$outfile" "$url"; do
attempt=$((attempt+1))
if [ $attempt -ge $max ]; then
echo "Failed after $attempt attempts"
exit 1
fi
echo "Retrying in $delay seconds..."
sleep $delay
delay=$((delay*2))
done
Do not hardcode secrets. Use environment variables or secret managers.
Respect site policies and robots.txt. For heavy data needs, request official API access.
Throttle and back off. Use polite delays, --limit-rate, and exponential backoff.
Verify TLS in production. Do not use -k for production; use --cacert if needed.
Sanitize logs. Avoid logging secrets or tokens.
-i include response headers
-I headers only (HEAD)
-H add header (repeatable)
-G convert -d into query params (GET)
-d data (with -G becomes query)
-L follow redirects
-o save to file (name)
-O save using remote name
-u basic auth user:pass
-b cookie string or file
-c cookie jar to save cookies
-v verbose
--trace-ascii FILE detailed trace
--limit-rate RATE throttle
--retry N --retry-delay S --retry-connrefused
-r byte range
-f fail on HTTP error (4xx/5xx)
-w '%{http_code}' write status code
--connect-timeout S limit connect wait time (seconds)
--data-urlencode url-encode data for GET query params
Q: How do I check only the HTTP status code?
A: curl -s -o /dev/null -w '%{http_code}\n' https://api.example.com/
Q: How to resume a download?
A: curl -C - -o filename URL
Q: How to include a bearer token?
A: curl -H "Authorization: Bearer $API_TOKEN" https://api.example.com/endpoint
Q: How to avoid exposing API keys?
A: Store them in environment variables and reference $API_TOKEN in scripts.
URL correct and reachable
Secrets stored securely (env vars / secret manager)
Query parameters encoded or sent with -G/--data-urlencode
Required headers included(Accept/Authorization)
Retry/backoff and rate control present for loops
Verbose logging enabled during development only
curl is a deceptively small tool that unlocks a huge range of practical workflows — from simple one-off checks to robust, production-ready fetch and retry scripts. Start with the Quick Start examples to build confidence, then layer in authentication, cookie handling, and retries as your use case demands.
Always prioritize safety: keep secrets out of code, respect server load and site policies, and test TLS and protocol compatibility on staging systems before deploying scripts in production.
< Previous
Next >