Docket / Fix it / meta refresh

Meta refresh: the redirect your tools cannot see

A meta refresh sends the visitor onward and the browser obeys, so from a chair it is indistinguishable from a redirect. It is not one. The page answers 200 with a normal body, which means every tool that reads status codes — including your link checker, including most audits — sees a page with content on it and moves on.

What it looks like

<meta http-equiv="refresh" content="0;url=https://example.com/new-page/">

A visitor lands, the browser waits the stated interval, and off they go. Nothing is broken. Nobody complains. That is exactly the problem.

Why the invisibility is the cost

A server redirect announces itself in the status line, and everything downstream can act on it. A meta refresh announces itself only in the body, so:

The damage is not that the visitor fails to arrive. They arrive. It is that your own tooling quietly stops describing your site accurately, and you keep trusting it.

The honest caveat, which most advice skips

Search engines support meta refresh and follow it. A server-side redirect is preferred because it is faster and unambiguous — but plenty of hosting cannot issue one. Static hosts commonly have no mechanism to return a 301 for a moved page, and on those a refresh stub is the only tool available.

So this is not a fault to be ashamed of. If you can issue a real redirect, do. If your host will not let you, a zero-delay refresh stub with a canonical pointing at the new URL is a reasonable second best, and it is worth knowing that is what you are relying on.

A delay above zero is a different, worse thing

Zero means the hop is instant. Anything above it leaves a visitor looking at a page that is not the page they wanted and is not going to stay — and search engines treat a delayed refresh as a weaker signal than an immediate one. If you are stuck with a refresh, set it to zero.

The wrong fixes

Adding a canonical and considering it handled. The canonical is worth having alongside a refresh stub, but it does not make the page a redirect and it does not make the hop visible to your tooling. Two weak signals are not a strong one.

Swapping it for JavaScript. A location.replace() in a script has the same shape and the same invisibility, with the added condition that something has to run it. If the goal was a redirect a crawler can rely on, this is further from it, not closer.

Finding them

curl -s https://example.com/old-page/ | grep -i 'http-equiv'

Check the URLs you moved. Renames and site migrations are where these accumulate, because each one is created at a moment when somebody is thinking about the new URL rather than about how the old one will be audited a year later.

If you can replace them with real redirects, the redirect rules are worth getting right too.

Common questions

Is a meta refresh bad for SEO?

Search engines support it and follow it, so it is not a broken page. A server-side redirect is preferred because it is faster and unambiguous. The bigger cost is that the page answers 200, so link checkers and redirect reports read it as content and your own tooling stops describing the site accurately.

Why does my link checker not flag meta refresh redirects?

Because at the HTTP level there is nothing to flag. The page returns 200 with a normal body; the hop lives in the markup, not the status line.

What if my host cannot issue a 301?

Then a refresh stub is a reasonable second best, and plenty of static hosting offers nothing else. Set the delay to zero and add a canonical pointing at the new URL. It is worth knowing that is what you are relying on.

Does the delay value matter?

Yes. Zero makes the hop instant. Anything above it leaves the visitor on a page they did not want, and search engines treat a delayed refresh as a weaker signal than an immediate one.

Is a JavaScript redirect better?

No. location.replace has the same shape and the same invisibility to status-code tooling, and it additionally requires something to run the script. If you want a redirect a crawler can rely on, that is further away, not closer.