Follow HTTP redirects
Print the redirect chain (301/302/303/307/308 hops) from a starting URL to its final 2xx destination.
How to follow http redirects in each shell
Bashunix
curl -sSLI -o /dev/null -w "%{url_effective}\n" https://bit.ly/3xyzZshunix
curl -sSLI -o /dev/null -w "%{url_effective}\n" https://bit.ly/3xyzFishunix
curl -sSLI -o /dev/null -w "%{url_effective}\n" https://bit.ly/3xyzPowerShellwindows
(Invoke-WebRequest -Uri https://bit.ly/3xyz -MaximumRedirection 10).BaseResponse.RequestMessage.RequestUri`Invoke-WebRequest` follows redirects by default — `-MaximumRedirection 0` disables to inspect the 30x response itself. `.BaseResponse.RequestMessage.RequestUri` is the FINAL URL on pwsh 7+. On pwsh 5.1 use `(iwr URL).Headers.Location` after `-MaximumRedirection 0`.
cmd.exewindows
curl -sSLI -o NUL -w "%{url_effective}" https://bit.ly/3xyz`/dev/null` does not exist on Windows — use `NUL`. cmd `-w` format string uses `\n` but cmd's own batch quoting often eats it; in a `.bat` you may need `%{url_effective}^\n`.
Equivalents listed for Bash, Zsh, Fish, PowerShell, cmd.exe.
Gotchas & notes
- `-L` (`--location`) follows redirects; without it, curl stops at the first 30x and prints its body (usually an empty redirect HTML stub). Combine with `-I` to see EACH hop's status line + headers — the output is multiple HTTP/1.1 blocks separated by blank lines.
- Cap the chain: `curl --max-redirs 10 -L URL` (default is 50). Without a cap, a redirect loop (`A → B → A`) will spin until 50 hops are exhausted, then error. Most public shorteners (bit.ly, t.co, goo.gl-archived) have at most 1–2 hops; deeper chains usually indicate misconfigured server-side rewriting.
- Body-leakage across hosts: when `curl -L` follows a redirect to a DIFFERENT origin, by default `Authorization:` and `Cookie:` headers are STRIPPED from the next request (CVE-2014-3613 fixed this). But custom headers (`-H "X-API-Key: …"`) are RE-SENT to the redirect target — if your `-H` carries a secret and the redirect is attacker-controlled, your secret leaks. Use `--location-trusted` ONLY when you trust every host in the chain.
- Inspect just the final URL: `curl -sSLI -o /dev/null -w "%{url_effective}\n" URL`. The full status code chain: `curl -sSLI URL | awk '/^HTTP/ {print}'`. PowerShell version: `(Invoke-WebRequest URL).BaseResponse.RequestMessage.RequestUri.AbsoluteUri`. For richer trace: `curl --trace-ascii -` (HUGE output, use only when debugging).
Related commands
Related tasks
- Send an HTTP POST request— POST a JSON body (or form fields, or a file) to a URL and capture the response.
- Get HTTP response headers— Inspect just the response headers of a URL — useful for debugging redirects, caching, CORS, and TLS.
- Check if a URL is reachable— Test whether a URL returns 2xx/3xx — useful for healthchecks, wait-for-it scripts, and CI smoke tests.
- Check SSL certificate expiry— Print the notBefore / notAfter dates of a remote site's TLS certificate (or a local .pem file).