Meta refresh and JavaScript redirects
Not every redirect happens on the server. A meta refresh tag or a line of JavaScript can also send visitors to another URL. Here is how these client-side redirects work, how Google handles them and why they should only be your fallback.
Server-side vs. client-side redirects
With a normal server-side redirect (301, 302, 307, 308), the server answers the request with a 3xx status code and a Location header. No content is delivered, and the browser immediately requests the new URL.
With a client-side redirect, the server answers with 200 OK and a regular HTML page. Only once the browser has loaded and processed that page does an instruction inside it trigger the redirect. There are two variants: the meta refresh tag and JavaScript.
That difference sounds technical, but it has consequences for speed, for search engines and for every tool that does not behave like a full browser.
How a meta refresh redirect works
A meta refresh is a meta element in the head of the page:
<meta http-equiv="refresh" content="0; url=https://example.com/new-page/">
The content attribute contains two parts: the delay in seconds and, after a semicolon, the target URL. 0 means "redirect immediately", 5 means "show this page for five seconds, then redirect". Without a url= part, the tag simply reloads the current page, which is a separate use case.
The same instruction can also be sent as an HTTP header instead of in the HTML:
HTTP/1.1 200 OK
Refresh: 0; url=https://example.com/new-page/
This Refresh header is not part of the HTTP specification, but it is described in the HTML standard and supported by browsers. It still delivers a 200, so it has the same drawbacks as the meta tag.
How JavaScript redirects work
A JavaScript redirect changes window.location:
<script>
window.location.replace('https://example.com/new-page/');
</script>
Prefer location.replace() over location.href = .... With href, the redirecting page stays in the browser history. When the visitor clicks "Back", they land on the redirect page again, which immediately sends them forward again: the classic back-button trap. replace() swaps the history entry, so the back button works as expected.
JavaScript redirects are common in single-page applications, on pages where the target depends on something only the browser knows (such as a login state stored client-side), and in tracking or affiliate scripts.
How Google treats meta refresh and JavaScript redirects
According to Google Search Central:
- An instant meta refresh (delay
0) is treated like a permanent redirect, similar to a 301. - A delayed meta refresh is treated like a temporary redirect, similar to a 302. The original URL is more likely to stay in the index.
- JavaScript redirects are followed as well, but only once Google renders the page. Rendering can happen later than the crawl and can fail, for example if scripts are blocked or time out. Google therefore recommends using JavaScript redirects only if server-side redirects or a meta refresh are not possible.
In other words: Google copes with client-side redirects, but they are a weaker and slower signal than a real 3xx response. And Google is not the only client. Other search engines, social media link previews, SEO crawlers, feed readers and many HTTP libraries do not execute JavaScript, and some ignore meta refresh as well. For them, the old page simply answers 200 OK and the redirect does not exist.
Why server-side redirects are better
| 301/308 (server) | Meta refresh (0 s) | Meta refresh (delayed) | JavaScript | |
|---|---|---|---|---|
| Status code of old URL | 301/308 | 200 | 200 | 200 |
| Google interpretation | Permanent | Permanent | Temporary | Followed after rendering |
| Works without JavaScript | Yes | Yes | Yes | No |
| Works for PDFs, images, APIs | Yes | No | No | No |
| Speed | Fastest | Old page must load first | Deliberately slow | Page and script must load first |
| Recognized by simple bots and tools | Yes | Partly | Partly | Rarely |
The main reasons in detail:
- Speed: with a 3xx, the browser gets a tiny response and moves on. With a client-side redirect it downloads and parses an HTML page first, maybe loads scripts, and only then starts the real request. On mobile connections that is a noticeable delay.
- Clear semantics: a 301 unambiguously says "permanently moved", for every client. A
200with an embedded redirect is open to interpretation. - Works for every resource: you can put a meta tag in HTML, but not in a PDF, an image or a JSON API response. Server-side redirects work for everything.
- Accessibility: timed refreshes that move users away without warning are a known accessibility problem. The MDN documentation on the meta element points out that pages with a delayed refresh can be disorienting, especially for screen reader users.
- Security: JavaScript redirects that read the target from the URL (such as
?next=...) without validation are a common source of open redirects, which attackers abuse for phishing.
When a client-side redirect is acceptable
Sometimes you simply have no access to the server configuration, for example on a static host that does not support redirect rules, or on a hosted platform with limited settings. Then a meta refresh is the next best option, followed by JavaScript. Make it as robust as possible:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>This page has moved</title>
<link rel="canonical" href="https://example.com/new-page/">
<meta http-equiv="refresh" content="0; url=https://example.com/new-page/">
</head>
<body>
<p>This page has moved to <a href="https://example.com/new-page/">example.com/new-page/</a>.</p>
</body>
</html>
- Use a delay of 0, so Google treats it as permanent and users do not wait.
- Add a
rel="canonical"pointing to the target as an additional signal. - Include a visible link for clients that do not follow the refresh.
- Put the meta tag early in the
head, so it is found even if a tool only reads the beginning of the document.
Before you settle for a meta refresh, check whether your platform offers real redirects after all. Many do, often hidden in a config file: see the guides for Vercel and Netlify, Cloudflare (which can redirect in front of any origin) and WordPress. If you have Apache or nginx, a 301 is one line, as shown in the 301 redirect guide.
How to find meta refresh and JavaScript redirects
Client-side redirects are easy to miss, because in the browser they look like any other redirect. Our redirect checker reads the beginning of every HTML response it receives. If it finds a meta refresh tag, it follows it, shows it as a separate hop and adds a hint that a server-side redirect would be better. That way you see at a glance whether your "redirect" is a real 301 or a 200 page with a meta tag.
JavaScript redirects are different: the checker, like most crawlers and HTTP tools, does not execute JavaScript. If the checker shows 200 OK for a URL but your browser ends up somewhere else, a JavaScript redirect is the likely cause. To see what Google makes of it, use the URL Inspection tool in Google Search Console, which shows the rendered page.
When you replace client-side redirects with server-side ones, test again and make sure the result is a single 301 or 308 hop straight to a 200 page, without a leftover meta refresh creating a redirect chain.
Frequently asked questions
- Is a meta refresh redirect bad for SEO?
Not necessarily. Google treats an instant meta refresh like a permanent redirect. It is still slower than a 301 and not understood by every bot, so use it only when you cannot set up a server-side redirect.
- What delay should a meta refresh have?
Zero. Google treats an instant meta refresh as permanent and a delayed one as temporary. A delay also makes users wait and is an accessibility problem. If you want to show a message first, a visible link is the better solution.
- Does Google follow JavaScript redirects?
Yes, once it renders the page. Rendering can happen later than crawling and can fail, which is why Google recommends JavaScript redirects only as a last resort. Many other crawlers and tools do not execute JavaScript at all.
- Can I combine a meta refresh with a 301?
There is no need to. A 301 response is not rendered as a page, so the browser never sees a meta tag inside it. If you can send a 301, do that and remove the meta refresh, otherwise you may end up with an extra hop.
Related guides
-
301 vs. 302 redirect
A 301 says "this URL has moved for good", a 302 says "look over there for now". The difference sounds small, but it affects which URL Google indexes, how long browsers remember the redirect and how easy it is to undo.
-
307 vs. 308 redirect
307 and 308 are the strict siblings of 302 and 301: they guarantee that a POST stays a POST. Here is what that means in practice, why you often see a 307 that your server never sent, and when a 308 is the better permanent redirect.
-
301 redirect
A 301 redirect permanently sends visitors and search engines from an old URL to a new one. It is the standard tool for relaunches, domain moves and URL changes. Here is how it works, how to set it up and how to avoid the classic mistakes.