A link lands somewhere it should not, and you need to know what happened between the click
and the final page. The standard first move is curl, and it is the right one: the
60 second gclid test on this site is built on
curl -sIL, and for server redirects it tells the truth. Then the chain looks clean in the
terminal while the browser still ends up somewhere else, and the tool has quietly run out.
The reason is that only some redirects live in HTTP responses. The rest happen inside the
page, or inside the browser itself, and no amount of -L will surface them. This article is
about seeing a chain, not building one; every way to create a redirect on Cloudflare is
its own comparison.
Three redirects curl cannot show you
A JavaScript redirect is a 200. The server answers with a normal page, the page runs
location.replace() or sets location.href, and the browser navigates. curl prints
HTTP/2 200, reports no redirect at all, and exits. Every interstitial, every tracking hop
built on a script, every “checking your browser” page falls in this class.
A meta refresh is also a 200. <meta http-equiv="refresh" content="0;url=..."> sits in
the HTML body, and curl does not parse HTML. Same clean status line, same silent
navigation in the browser.
An HSTS upgrade never leaves the browser. After one visit to a site that sends
Strict-Transport-Security, the browser rewrites http:// to https:// before any request
is made. DevTools shows it as 307 Internal Redirect, a response the server never sent.
curl keeps no HSTS state by default, so it hits the http:// URL fresh every time and
shows you the server’s 301, a hop your returning visitors stopped taking long ago.
On top of the mechanics there is the session. curl carries no cookies, so a chain that
branches on login state, a consent cookie, or an A/B assignment sends curl down a
different path than the person who reported the problem. The chain you tested is not the
chain they followed, even when both are real.
DevTools shows it, if you hold it right
The browser obviously knows the full chain, and the Network panel will show it, with
ceremony. Preserve log has to be on, otherwise the panel clears itself on every navigation
and the hop you care about erases its own evidence. The Doc filter cuts the noise from the
hundred subrequests a modern page makes. Server hops then appear as separate rows with their
301 and 302 statuses.
The client side hops are there too, but unlabeled. A JavaScript redirect is just another document request; nothing in the row says “this was a redirect”, and connecting it to the page that triggered it means reading the Initiator column. A meta refresh looks the same. Do this once and it is five minutes of archaeology. Do it for every report and you start wanting the browser to just keep the record.
A recorder instead of a stakeout
That is what Redirect Inspector
does. It is our own open source extension (Apache 2.0, code on GitHub),
and version 2.3 shipped as its largest update yet, which is the occasion for this article.
The extension listens to the browser’s own request pipeline and records every chain as you
browse: server hops with their status codes, client side navigations (a script or a meta
refresh) marked with a JS badge, and the browser’s internal upgrades marked HSTS.
Chains are grouped by browsing session, tracking
pixels and ad beacons are filtered out by default, and each card carries the total chain
time with per hop timing in the analysis drawer.
What 2.3 added, briefly:
- Check a URL without visiting it. Paste a URL into the dock at the bottom of the panel; it opens in an invisible background tab, the chain is captured through the normal pipeline, and the tab closes itself. The suspicious link from the report gets traced without ever taking over your screen.
- Export that fits a bug report. Copy a clean summary, download the raw chain as JSON,
or copy a ready
curlcommand that reproduces the server side of the chain, which closes the loop back to the terminal where the investigation started. - A side panel instead of a popup on Chrome and Edge, so the chain list stays open while you browse. Firefox keeps the popup.
- Local analysis. Nine checks per chain: loops, hops that bounce back and forth, chain length, mixed redirect types, auth bounces, consent hops, tracking noise, CDN detection, final outcome.
- Search across all captured URLs, an undoable Clear, keyboard shortcuts, and full UI translations in seven languages.
The part that matters for a tool watching your traffic: everything runs locally. No accounts, no analytics, no telemetry, and by default no network requests at all; captured chains live in browser storage and never leave the machine. It is on the Chrome Web Store, Firefox Add-ons, and Edge Add-ons.
Which tool sees what
| You need | curl -sIL | DevTools Network | Redirect Inspector |
|---|---|---|---|
| Server hops (301, 302, 307, 308) | yes | with Preserve log on | yes, recorded as you browse |
| HSTS upgrade | no, sees the server 301 every time | shown as 307 Internal Redirect | labeled HSTS |
| JS and meta refresh | no, both are a 200 | an unlabeled document request | captured, marked as a client redirect |
| The chain your session gets (cookies, login) | no | yes | yes |
| Timing | one total with -w |
per request, spread across rows | total per chain, delta per hop |
| A record you can search and export later | no | cleared when the panel closes | sessions, search, JSON and curl export |
Online redirect checkers are missing from the table on purpose: they request the URL from
their own datacenter, so a chain that branches on country, language, or cookies shows you
the datacenter’s version, which is the same blind spot curl has plus somebody else’s IP.
Where the extension stops
The extension records what your browser was sent. A chain that branches by geography still shows you the branch for your country and nobody else’s, and what Googlebot sees on the same URL is a different question entirely. The URL check is a real navigation in an inactive tab, so your cookies apply and the visit lands in your history; it is a convenience, not an isolation chamber. And it can only look at chains one browser at a time, on the machine where it is installed.
For debugging the link in front of you, that is the whole job, and the extension is free. The point where it stops is the point where the question changes from “what happened to this click” to “which of my domains are redirecting wrong right now”. Answering that means sending the same probe to every domain on a schedule and comparing against yesterday, which no browser tool can do. The audit script is the manual version of that answer, and 301.st is the version that runs continuously, across the portfolio, with an alert when a chain changes. For the tab you have open, install the extension and read the chain.