What a Redirect Actually Is
A redirect is an HTTP response that, instead of returning a page, tells the client to go somewhere else. The server sends a status code in the 3xx range and a Location header with the new URL. The browser then makes a completely new request to that URL.
That second request is the part people forget. Every redirect is a full extra round trip: a DNS lookup if the hostname changed, a new TCP and TLS handshake if the connection can't be reused, and another wait for the server. One redirect is usually invisible. Three or four stacked on top of each other — a redirect chain — add hundreds of milliseconds on mobile networks and give search engines more opportunities to give up.
You can see a redirect with nothing but curl. The -I flag asks for headers only:
$ curl -sI http://lookmyip.com
HTTP/1.1 308 Permanent Redirect
Location: https://lookmyip.com/The server didn't return the page. It returned an instruction: try https://lookmyip.com/ instead.
301 vs 302 vs 307 vs 308
There are four redirect codes you will meet in practice. They differ on two questions: is the move permanent, and is the client allowed to change the request method?
| Code | Meaning | Permanent? | Method preserved? |
|---|---|---|---|
| 301 | Moved Permanently | Yes | Not guaranteed — POST may become GET |
| 302 | Found | No | Not guaranteed — POST may become GET |
| 307 | Temporary Redirect | No | Yes |
| 308 | Permanent Redirect | Yes | Yes |
The "method" column matters for forms and APIs. Historically, browsers turned a POST that hit a 301 or 302 into a GET on the new URL, silently dropping the request body. 307 and 308 exist to say explicitly "repeat the same request at the new location".
For ordinary page moves — an old URL now lives somewhere else — 301 and 308 are equivalent for search purposes. Google treats both as a strong signal that the target should become the canonical URL and that ranking signals should consolidate there. 302 and 307 are a weak signal: Google keeps the original URL indexed for a while, assuming you'll switch back. If a "temporary" redirect stays in place for months, Google eventually treats it as permanent anyway, but there's no reason to make it guess.
Rule of thumb: use 301 or 308 for anything you don't intend to undo. Use 302 or 307 only when the original URL really will come back — a maintenance page, a geo-specific landing page, a login bounce.
Tracing a Redirect Chain Hop by Hop
curl's -L flag follows redirects. Combined with -I it prints the headers from every hop, which is the quickest way to see a whole chain:
$ curl -sIL http://lookmyip.com | grep -iE '^(HTTP|location)'
HTTP/1.1 308 Permanent Redirect
Location: https://lookmyip.com/
HTTP/2 308
location: https://www.lookmyip.com/
HTTP/2 200That's a real two-hop chain: plain HTTP is upgraded to HTTPS on the bare domain, and then the bare domain is sent to www. Both hops are permanent, the chain stays on HTTPS once it gets there, and it ends in a 200. This is the most common chain on the web, and two hops is acceptable — though the first hop could point straight at https://www.lookmyip.com/ and save a round trip.
To print just the final URL and the number of redirects followed, use curl's write-out variables:
$ curl -sIL -o /dev/null -w '%{num_redirects} redirects -> %{url_effective}\n' http://lookmyip.com
2 redirects -> https://www.lookmyip.com/The Redirect Checker does the same thing from a server rather than your laptop. It follows up to 20 hops, records the status, Location, server and response time of each, and flags loops and HTTPS-to-HTTP downgrades.
Chain Patterns Worth Fixing
Long chains. Each hop costs a round trip. Googlebot follows up to 10 redirect hops before giving up and reporting a redirect error in Search Console, but the practical target is one hop, two at most. Long chains usually build up over time: a site moves from HTTP to HTTPS, later from the bare domain to www, later still renames a section — and nobody collapses the old rules. The fix is to point every old URL directly at its final destination.
Redirect loops. A sends you to B, B sends you back to A, and browsers stop with "too many redirects". The classic cause is two layers disagreeing about the canonical form: a CDN that forces HTTPS while the origin — which only sees plain HTTP from the CDN — also forces HTTPS. Another is one layer adding a trailing slash while another strips it.
HTTPS → HTTP downgrades. A hop from https:// to http:// exposes the request on the network and, on a site using HSTS, may be blocked by the browser. It is almost always a redirect rule hardcoding http:// instead of using a relative or scheme-matched target.
Temporary codes for permanent moves. A 302 left in place after a migration slows down the transfer of ranking signals. If the old URL is never coming back, change it to 301 or 308.
Redirecting everything to the homepage. When pages are removed, it's tempting to send all of them to /. Google treats a redirect to an unrelated page as a soft 404: the old URL drops out and nothing passes to the homepage. Redirect to the closest equivalent page, or let the old URL return a genuine 404 or 410.
Meta refresh and JavaScript redirects. <meta http-equiv="refresh"> and window.location only work after the page has loaded, are invisible to tools that don't render pages, and are slower than an HTTP redirect. Use a server-side 3xx wherever you control the server.
Checking Redirects After a Migration
Site migrations are where redirects go wrong at scale. A practical checklist:
- Export the old URL list before the move — from your sitemap, analytics landing pages, and the Search Console Pages report.
- Map each old URL to one new URL. Not to a category page, not to the homepage: to the page that now holds the same content.
- Test every mapping after launch. A short loop over the list with curl is enough — every line should show a final
200, one redirect, and the URL you expected. - Update internal links to point at the new URLs directly. Redirects are for visitors arriving from outside; your own navigation shouldn't depend on them.
- Keep the redirects in place. Google recommends at least a year. In practice old URLs keep receiving links and bookmarks for much longer, and removing the rule turns all of that into 404s.
while read url; do
curl -sIL -o /dev/null -w "%{http_code} %{num_redirects} %{url_effective} <- $url\n" "$url"
done < old-urls.txtRedirects and Browser Caching
Browsers cache permanent redirects aggressively. A 301 or 308 without explicit cache headers may be remembered indefinitely, so if a wrong permanent redirect goes live, some visitors will keep following it even after you fix the server.
Two habits avoid this:
- Test with a temporary code first. Deploy a new rule as a 302 or 307, confirm it behaves, then switch it to 301 or 308.
- Test from outside your browser. Your browser may be replaying a cached redirect. curl and the Redirect Checker don't cache, so they show what the server is returning right now.
HSTS has a similar effect on the HTTP-to-HTTPS hop. Once a browser has seen a Strict-Transport-Security header, it rewrites http:// to https:// itself — Chrome's DevTools shows this as a "307 Internal Redirect" — without contacting the server at all. That isn't a redirect on your server and it won't appear in curl. The HTTP security headers guide explains how HSTS works.
