Yes, curl follows redirects, but only when you explicitly tell it to with the -L (or --location) flag. Without that flag, curl fetches the initial URL and stops, showing you the 3xx redirect response instead of the final page. This article explains exactly how redirect handling works in curl, when to use -L, and how to avoid common pitfalls.
How curl Handles Redirects by Default
When you run curl https://example.com/old-page, curl sends a GET request and waits for the response. If the server replies with a 301, 302, 303, 307, or 308 status code plus a Location header, curl simply prints that response (headers included, if you use -i) and exits. It does not automatically request the new URL. This is intentional: many tools and scripts need to see the redirect itself, not silently follow it.
For example, a REST API might return 302 Found with a temporary URL for a resource. A client that blindly follows would miss the original response. curl’s default behavior gives you full control.
Using the -L Flag to Follow Redirects
To make curl follow redirects, add -L or --location:
curl -L https://example.com/old-page
Now curl will:
- Send the initial request.
- Read the redirect response.
- Extract the URL from the
Locationheader. - Send a new request to that URL.
- Repeat until it gets a 200 OK (or another non-redirect status) or hits the maximum redirect limit.
By default, curl follows up to 50 redirects. You can change this with --max-redirs:
curl -L --max-redirs 10 https://example.com/old-page
If the limit is exceeded, curl stops and returns an error message like Maximum (10) redirects followed.
What Happens to POST and Other Methods?
This is where many people get confused. When curl follows a 301 or 302 redirect after a POST request, it changes the method to GET by default. That’s because HTTP standards (and most browsers) treat 301/302 as “movedâ€� and expect a GET for the new location. However, for 307 and 308 status codes, the HTTP spec requires that the method and body be preserved. curl honors that:
- 301, 302, 303: POST becomes GET (unless you use
--post301,--post302, or--post303to force keeping POST). - 307, 308: Method and body are kept as-is.
If you’re sending a POST and you want it to be re-sent as POST after a redirect, use the appropriate flag:
curl -L --post302 -d "key=value" https://example.com/submit
Common Pitfalls and How to Avoid Them
Here are the most frequent issues people run into when following redirects with curl:
- Losing headers or cookies: If the redirect goes to a different domain, curl by default does not forward the
Authorizationheader or cookies unless you use--location-trustedand-b(cookie jar). For cross-domain redirects, this is a security feature. - Relative redirects: Some servers send a
Locationheader like/new-pageinstead of a full URL. curl handles this correctly by resolving against the current URL, but if you’re parsing the header yourself, you must handle it. - Redirect loops: If two URLs point to each other, curl will keep following until it hits the max limit. Use
--max-redirsto prevent infinite loops. - HTTPS to HTTP downgrade: By default, curl will follow a redirect from HTTPS to HTTP. If you want to block that, use
--proto-rediror--proto =httpsto restrict protocols after the first request.
How to See the Redirect Chain
Sometimes you want to know which URLs were visited. Use -v (verbose) or -w (write-out) to see each step:
curl -L -v https://example.com/old-page
The verbose output shows each request line (> GET /old-page HTTP/1.1) and each response (< HTTP/1.1 301 Moved Permanently). For a cleaner list, use -w with %{url_effective} to print the final URL after following:
curl -L -o /dev/null -w "%{url_effective}\n" https://example.com/old-page
This prints the last URL after all redirects, which is useful for scripting.
Alternatives to curl for Redirects
If you’re not using curl, other tools have similar options:
- wget: Follows redirects by default (no flag needed). Use
--max-redirectto limit. - Python requests: Follows redirects automatically for GET, but you can disable with
allow_redirects=False. - Node.js fetch: Follows redirects by default, with
redirect: 'manual'to disable.
In scripts, always decide explicitly whether you want to follow redirects or not, because the default behavior varies between tools.
Security and Safety Considerations
Following redirects can expose you to unexpected destinations. A malicious server could redirect you to a phishing page or a local file URL (though curl blocks file:// by default unless you enable it). Always use --proto-redir to restrict protocols after the first request if you only want HTTP/HTTPS:
curl -L --proto-redir =https https://example.com
Also, be careful with --location-trusted: it sends sensitive headers (like Authorization) to any host the redirect points to, which can leak credentials. Only use it when you trust all involved domains.
Frequently Asked Questions
Does curl follow redirects by default?
No. Without -L, curl shows the redirect response (e.g., a 301 with a Location header) and stops. You must add -L to follow automatically.
How do I make curl follow redirects and save the final file?
Use -L together with -o filename. For example: curl -L -o final.html https://example.com/old-page. The file will contain the content from the final URL after all redirects.
Why does curl say “Maximum redirects followed� even with -L?
That means the server keeps sending redirects in a loop or the chain is longer than your --max-redirs value (default 50). Check the URLs with -v to see where it’s looping.
Does curl follow redirects for POST requests?
It depends on the status code. For 301/302/303, it converts POST to GET by default. For 307/308, it keeps the POST method and body. Use --post301, --post302, or --post303 to force keeping POST.
Can I stop curl from following a redirect to a different domain?
Yes, but there’s no built-in flag for that. You can use --proto-redir to restrict protocols, but for domain checks you’d need to script it: first get the redirect URL with -I (HEAD) and then decide whether to follow manually.
What’s the difference between -L and –location-trusted?
-L follows redirects but strips sensitive headers (like Authorization) on cross-host redirects. --location-trusted follows redirects and sends those headers to the new host as well, which is useful for internal APIs but risky for public sites.
Related
Formula used
in url | URL | - | https://example.com/redirect | 1 | 1000 in max | Max redirects | - | 5 | 0 | 50 out redirects | Redirects followed | - | 0 | 0
Each line is one input (in, sel, list) or one result (out: label, unit, formula, decimals). How the calculators work
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- Motorola Phone Recovery: How to Recover Data
- Poco X3 GT Dimensity 1100 67W Fast Charging Launched?5.00 min/km
- Flash Converter: What It Is & How to Use It
- Choosing a Pipe Flow Meter for Swirling Flow
- Convert 2D Videos to Oculus Rift VR: How-To
- DRAM Light on Motherboard: Meaning & Fixes5.00 min/km