JavaScript Redirects
What a JavaScript redirect is, how Google's render pipeline treats it differently from a server-side 301, when it's an acceptable last resort, and how to implement and detect one — plus where meta refresh and the History API fit.
1 evidence signal on this page
- Related live toolrobots.txt Tester
A JavaScript redirect sends users and crawlers to a new URL with client-side code (window.location.replace() or .href). It's the least reliable redirect type because Google only sees it after rendering — which can be delayed, or fail entirely, with no fixed timeline either way. Google's official order of preference is server-side (301/302/307/308) → meta refresh → JavaScript, and its docs say plainly: only use JS redirects if you can't do the other two. Once Google successfully interprets one, the target becomes a canonicalization signal — but that's not a proven guarantee of identical PageRank or ranking outcomes to a 301, so treat it as a last resort rather than a like-for-like swap. Use them on constrained platforms with no server access, for SPA error pages that point to a real 404, and little else. If you must use one, use window.location.replace() in the <head>, drop the source URL from your sitemap, and point internal links at the final destination. Meta refresh is a separate HTML-level redirect, and history.pushState()/replaceState() aren't redirects at all.
TL;DR — A JavaScript redirectA JavaScript redirect is a client-side redirect that uses code like window.location.replace() to send a visitor (and crawler) to a different URL. Because it only fires after the page is downloaded and rendered, Google prefers server-side and meta refresh redirects above it. uses code in the page to send you to a different URL after the page loads. It works for people, but search engines handle it less reliably than a “real” server redirectA redirect sends browsers and crawlers from a requested URL to a different one. An HTTP redirect specifically is a 3xx status code paired with a Location header; meta refresh and JavaScript redirects achieve a similar navigation without being a 3xx response themselves. Permanent redirects (301/308) are Google's signal the target should be canonical; temporary ones (302/303/307) aren't. (a 301). If you can set up a 301 instead, do that. Save JavaScript redirects for when you have no other option.
What a JavaScript redirect is
A JavaScript redirect changes navigation through script execution rather than an HTTP 3xx response. Evidence for this claim Primary standard or official documentation supporting the adjacent article claim. Scope: Protocol semantics and Search behavior are kept separate; no indexing, ranking, or migration-timing guarantee is inferred. Confidence: high · Verified: Google: JavaScript redirects Google can process JavaScript redirects but recommends server-side redirects when possible. Evidence for this claim Primary standard or official documentation supporting the adjacent article claim. Scope: Protocol semantics and Search behavior are kept separate; no indexing, ranking, or migration-timing guarantee is inferred. Confidence: high · Verified: Google: Redirects and Search
There are two broad ways to send someone from one URL to another.
The first is a server-side redirect. Before the page even loads, the server says “that page moved — go here instead” using a status code like 301 (permanent) or 302 (temporary). The browser and the search engine both get that message immediately.
The second is a JavaScript redirect. The page loads normally, and then a bit of code runs in the browser and sends you somewhere else. Something like:
<script>
window.location.replace("https://example.com/new-page/");
</script>For a person clicking around, the two feel almost the same. For a search engine, they’re very different — and that difference is the whole reason this page exists.
Why search engines treat them differently
Google reads your page in stages. First it crawls (downloads the raw HTML). Later it renders the page — actually running the JavaScript, the way a browser would. A server-side 301 is visible in that first step. A JavaScript redirect isn’t visible until the renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. step, which can come much later — or, sometimes, not at all.
Google says it directly: “Only use JavaScript redirects if you can’t do server-side or meta refreshA meta refresh redirect is a client-side redirect written as an HTML <meta http-equiv=\"refresh\"> tag (or an equivalent HTTP Refresh header) — not an HTTP status code. The server returns a normal 200, then the browser navigates after the page loads. An instant (0-second) one is read by Google as permanent; a delayed one as temporary. redirects.” (Google Search Central)
So a JavaScript redirect isn’t bad — it’s just less reliable. Google will usually get there eventually, but a real 301 is faster and more certain.
The simple rule
- Can you set a 301 (or 302)? Do that. It’s the gold standard.
- Can’t touch the server, but can edit the HTML
<head>? A 0-second meta refresh is the next-best option. - Neither? Then a JavaScript redirect is a fine last resort.
A couple of things people get wrong:
- A meta refresh is not a JavaScript redirect. It’s a
<meta>tag in your HTML, and Google handles it earlier and more reliably than JS. history.pushState()is not a redirect. It just changes what’s in the address bar — it doesn’t send anyone anywhere, and search engines don’t follow it.
Want the render-pipeline timing, the implementation details, and how to find JS redirects in a crawl? Switch to the Advanced tab.
TL;DR — A JavaScript redirectA JavaScript redirect is a client-side redirect that uses code like window.location.replace() to send a visitor (and crawler) to a different URL. Because it only fires after the page is downloaded and rendered, Google prefers server-side and meta refresh redirects above it. is a client-side redirectA redirect sends browsers and crawlers from a requested URL to a different one. An HTTP redirect specifically is a 3xx status code paired with a Location header; meta refresh and JavaScript redirects achieve a similar navigation without being a 3xx response themselves. Permanent redirects (301/308) are Google's signal the target should be canonical; temporary ones (302/303/307) aren't. (
window.location.replace(),.href,.assign()) that Google only processes after renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. — phase three of crawl → render → indexStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed.. A server-side 301 is seen at crawl time; a JS redirect waits on the render queue, and Google gives no fixed timeline for that wait — it can be quick or it can take a long while, and renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. can fail outright. Google’s documented preference order is server-side → meta refreshA meta refresh redirect is a client-side redirect written as an HTML <meta http-equiv=\"refresh\"> tag (or an equivalent HTTP Refresh header) — not an HTTP status code. The server returns a normal 200, then the browser navigates after the page loads. An instant (0-second) one is read by Google as permanent; a delayed one as temporary. → JavaScript, and the docs say to use JS redirects only when you can’t do the other two. Once Google successfully interprets one, the target becomes a permanent canonicalizationHow search engines pick one canonical URL among duplicates and consolidate signals onto it. signal — even Google used them on their own blog when nothing else worked — but that’s not documented proof of identical PageRankPageRank is Google's original recursive link-graph algorithm: a page's score depends on the scores of the pages linking to it, and in the published model each page's score is split across its outbound links (the simplified version: links are weighted votes). Google says it's evolved since launch but still part of its core ranking systems. or ranking outcomes to a 301, so they’re a last resort, not a spam signal. The legitimate uses are constrained platforms with no server config and SPA error pages that point at a real 404. Implement withwindow.location.replace()in the<head>, drop the source from your sitemapA sitemap is a file that lists the pages, images, videos, and other files on your site so search engines can discover them. It helps discovery, but submitting a sitemap doesn't guarantee crawling or indexing., repoint internal linksAn internal link is a hyperlink from one page on a website to another page on the same website. Internal links help search engines discover your pages and pass ranking signals (PageRank and anchor-text context) between them., and confirm GooglebotGooglebot is Google's web crawler — the software that fetches pages so Google can index and rank them. It comes in two variants, Googlebot Smartphone (primary, under mobile-first indexing) and Googlebot Desktop, and runs an evergreen Chromium renderer. can fetch the JS. Meta refresh is HTML-level (0s = permanent, any delay = temporary), andhistory.pushState()/replaceState()aren’t redirects at all.
What counts as a JavaScript redirect
Script navigation depends on rendering and execution, so it is not protocol-equivalent to an HTTP redirect. Evidence for this claim Primary standard or official documentation supporting the adjacent article claim. Scope: Protocol semantics and Search behavior are kept separate; no indexing, ranking, or migration-timing guarantee is inferred. Confidence: high · Verified: Google: JavaScript redirects Processing is possible, not an exact-timing or indexingStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed. guarantee. Evidence for this claim Primary standard or official documentation supporting the adjacent article claim. Scope: Protocol semantics and Search behavior are kept separate; no indexing, ranking, or migration-timing guarantee is inferred. Confidence: high · Verified: Google: Redirects and Search
A JavaScript redirect navigates the browser to a new URL with client-side code. The common methods, and how they differ:
window.location.replace("url")— navigates and removes the original URL from session history. This is the one to use: the back button skips the redirect source instead of bouncing the user straight back.window.location.href = "url"— navigates but keeps the original in history, so the back button returns to the redirecting page (and can create a loop).document.location.hrefandwindow.location.assign("url")behave the same way.history.pushState()/history.replaceState()— not redirects. They rewrite the address bar without any navigation or HTTP signal, so crawlersA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index. don’t treat them as redirects. SPAs use them for in-app URL changes; they need real<a href>links (or actual navigations) to be crawlable.
The dividing line that matters: .replace(), .href, and .assign() all trigger
a real document navigation (the difference between them is only what happens to
session history), while pushState()/replaceState() never navigate at all —
they touch history state and the address bar and nothing else. None of the four is
an HTTP 301; “redirect” here is shorthand for client-side navigation, not a status
code.
Meta refresh (<meta http-equiv="refresh" content="0;url=...">) is often
lumped in with JS redirects, but it’s an HTML directive parsed before JavaScript
runs — a separate, more reliable category, covered below.
How Google processes a JavaScript redirect
This is the cruxChrome User Experience Report — Google's public dataset of real-world (field) performance data from eligible Chrome users. It's the official field-data source behind the Core Web Vitals program.. Google’s pipeline runs in stages, and a JS redirect and a server-side redirect get caught at different ones:
- Crawl — GooglebotGooglebot is Google's web crawler — the software that fetches pages so Google can index and rank them. It comes in two variants, Googlebot Smartphone (primary, under mobile-first indexing) and Googlebot Desktop, and runs an evergreen Chromium renderer. fetches the URL and reads the raw HTML. A server-side 301/302/307/308 is seen right here.
- Render queue — pages that return
200wait to be rendered. Google’s docs note the page “may stay on this queue for a few seconds, but it can take longer than that.” Google doesn’t publish a fixed service-level timeline beyond that, so treat the wait as unpredictable — it can be quick, or it can drag — rather than assuming any specific number of days or weeks. - Render + index — headless Chromium runs the JavaScript. This is the first moment a JS redirect exists as far as Google is concerned.
The same idea I make on CrawlingCrawling is how search engines use automated bots (like Googlebot and Bingbot) to discover URLs and download pages. A page has to be crawlable to be indexed, but crawling on its own isn't a ranking factor. and in JavaScript SEO applies here: rendering is a separate step from fetching, and anything that depends on it inherits that delay and that risk.
And the risk is real. Google: “While Google attempts to render every URL Googlebot crawled, rendering may fail for various reasons. This means that if you set a JavaScript redirect, Google might never see it if rendering of the content failed.” (Google Search Central) During the window before the redirect is processed — and forever, if rendering fails — Google may keep the empty source page in its index.
Google’s official preference order
The redirects documentation lays out a hierarchy from most to least reliable:
- Server-side redirects — 301/308 (permanent), 302/307 (temporary). Best for everything: seen at crawl time, unambiguous.
- Meta refresh — HTML-level. A 0-second meta refresh is treated as a permanent redirect (like a 301); any delayed meta refresh is treated as temporary.
- JavaScript redirects — last resort.
Google’s words: “Only use JavaScript redirects if you can’t do server-side or meta refresh redirectsA meta refresh redirect is a client-side redirect written as an HTML <meta http-equiv=\"refresh\"> tag (or an equivalent HTTP Refresh header) — not an HTTP status code. The server returns a normal 200, then the browser navigates after the page loads. An instant (0-second) one is read by Google as permanent; a delayed one as temporary..” Permanent redirects pass the canonical signal to the target; temporary ones keep the original in results. (How that interacts with canonical selection is over on CanonicalizationHow search engines pick one canonical URL among duplicates and consolidate signals onto it..)
Does link equity pass through?
Google’s own redirects documentation lists JavaScript location navigation among its permanent redirection methods, and says the target becomes the canonicalizationHow search engines pick one canonical URL among duplicates and consolidate signals onto it. signal once Google has interpreted it — so the flat “JS redirects don’t pass PageRankPageRank is Google's original recursive link-graph algorithm: a page's score depends on the scores of the pages linking to it, and in the published model each page's score is split across its outbound links (the simplified version: links are weighted votes). Google says it's evolved since launch but still part of its core ranking systems.” claim is false. What the documentation doesn’t establish is that the outcome is identical, immediate, or as reliable as a server-side 301 — it describes the canonical signal, not a guarantee of matching PageRank flow, ranking, or timing. The honest framing: a 301 passes the signal at crawl time with near-certainty; a JS redirect passes it only if and when rendering succeeds, and Google doesn’t promise the result will match a 301’s outcome one-for-one. That gap — not lost equity — is the real cost of choosing JavaScript.
This is also why JS redirects aren’t a penalty trigger on their own. They only become a spam problem when they’re used for cloaking — showing crawlers one page and redirecting users to something different, or sending mobile users to an unrelated domain. Google’s sneaky redirects policy is about that intent, not the technique.
When a JavaScript redirect is the right tool
There are legitimate cases:
- Constrained platforms. Some shared hosting, CDN, or CMSA content management system (CMS) is software that lets users create, manage, and publish digital content — like blog posts and pages — without writing raw code. WordPress, Drupal, and Joomla are the most common open-source CMS platforms. setups give you no access to server-side redirect rules. A JS redirect is a valid fallback — and notably, Google used JS redirects on their own Webmaster blog because, as Gary Illyes put it, “that was the only thing we could use for 1:1 redirects, and it works on Google” (OnCrawl).
- SPA error handling. Google explicitly endorses this: “Use a JavaScript
redirect to a URL for which the server responds with a
404HTTP status codeAn HTTP status code is the three-digit number a server returns with every response to tell a browser or crawler what happened to its request — success, redirect, client error, or server error. For SEO the code matters as much as the content: it tells Google and Bing whether to index a page, follow a redirect, retry later, or drop the URL from the index..” (Google Search Central) A single-page app that resolves a bad route can redirect to a real 404 endpoint so Google processes the error correctly instead of indexing a soft 404A soft 404 is a URL that returns a success status code (usually 200 OK) even though the page is empty, missing, or shows a 'not found' message. It isn't a status code a server sends — it's a label search engines apply after comparing the response code against the rendered content, and they treat the page like a 404 for indexing..
For permanent URL migrations, this is not the tool — use a 301. I make the same point in site migrationsA site migration is any significant change to a website's URL structure, domain, platform, protocol, or hosting that can affect how search engines crawl, index, and rank it. The risk scales with how much you change at once.: JavaScript redirects are a last resort, and Google may never see them.
Static site generators: the Hugo aliases trap
A common surprise: Hugo’s aliases: frontmatter has historically generated
meta refresh HTML pages, not server-side 301s — and other static generators
have done similar things by default. Generator defaults change between versions,
so check your current deployed version’s actual output rather than assuming; if
aliases: isn’t giving you 301s, you need platform-level redirect rules (Netlify
_redirects, Cloudflare WorkersA serverless function that runs at Cloudflare's global edge, close to every user., Vercel vercel.json) plus (on Hugo)
disableAliases: true. I cover this in detail in
Hugo SEOHugo SEO is the practice of optimizing sites built with Hugo, the Go-based static site generator. Hugo outputs finished HTML at build time, so content is in the raw HTML on the first fetch — but that alone doesn't guarantee good Core Web Vitals or rankings, and canonicals, taxonomy duplication, and aliases-vs-301s still need hands-on configuration..
Implementation best practices
If a JavaScript redirect is genuinely your only option:
- Use
window.location.replace(), not.href. As Search Engine Journal puts it, JS redirects “typically usewindow.location.replace()function rather thanwindow.location.hrefto avoid UX redirect loopsA redirect loop is a chain of redirects that circles back on itself instead of ever reaching a live page — URL A redirects to B and B redirects back to A (or a longer cycle). No page ever returns a 200, so browsers show ERR_TOO_MANY_REDIRECTS and crawlers can't index anything.” (SEJ). - Put it in the
<head>, not the<body>. Browsers parse HTML sequentially and run scripts as they hit them, so “position JavaScript redirects in the<head>tag rather than<body>to minimize delay” (OnCrawl). - Redirect to the final destination in one hop. A JS redirect to a page that itself 301s elsewhere makes a chain; chains waste crawl budgetThe number of URLs an engine will crawl in a timeframe. and can surface in GSC as a redirect errorA Google Search Console Page Indexing status meaning Googlebot couldn't follow a redirect — a chain too long, a loop, a URL over the max length, or a bad/empty URL in the chain. It's a broken redirect to fix, not the normal \"Page with redirect.\".
- Remove the source URL from your XML sitemapAn XML sitemap is a UTF-8 file listing the canonical URLs on your site (with optional lastmod) so search engines can discover and prioritize them. It's a discovery and diagnostic aid, not a guarantee of indexing — and Google ignores its priority and changefreq tags.. SitemapsA sitemap is a file that lists the pages, images, videos, and other files on your site so search engines can discover them. It helps discovery, but submitting a sitemap doesn't guarantee crawling or indexing. should list canonical, indexable URLs — not redirecting ones.
- Repoint internal linksAn internal link is a hyperlink from one page on a website to another page on the same website. Internal links help search engines discover your pages and pass ranking signals (PageRank and anchor-text context) between them. at the destination, so they don’t route through the redirect at all.
- Make sure Googlebot can fetch the JS. If the redirect lives in an external
script blocked by
robots.txt, Google can’t render it and won’t see the redirect.
How to detect JavaScript redirects
They don’t announce themselves like a 301 in a header, so you have to render:
- A crawler with JS rendering on. OnCrawl recommends crawlingCrawling is how search engines use automated bots (like Googlebot and Bingbot) to discover URLs and download pages. A page has to be crawlable to be indexed, but crawling on its own isn't a ranking factor. with
“JavaScript rendering enabled (5-second timeout minimum)”; Screaming Frog and
Ahrefs Site Audit can both render. Without rendering, a JS-redirecting page just
looks like a normal
200. - Chrome DevTools. The Network tab (with “Preserve log”) shows the client-side navigation; the Redirect Path extension flags it too.
- In Search ConsoleGoogle's free tool for monitoring crawling, indexing, and search performance., a successfully processed JS redirect shows up under Page with redirectA Google Search Console Page Indexing status for a URL that redirects elsewhere. It's not indexed by design because it's a redirect — the destination is a separate question, and Google says the target may or may not end up indexed — usually expected, not an error (unlike the separate \"Redirect error\"). — the same status as any redirected URL, which is normal for non-canonical sources. That label isn’t guaranteed on any given check, though: it reflects whatever Google fetched, rendered, interpreted, and canonicalized at the sampled moment, so a URL can show a different status (or no redirect status yet) between checks without that being an error on your end.
What I’d actually do
Server-side first, every time. Meta refresh (0-second) when you can edit HTML but
not server config. JavaScript only when both are off the table — and then with
window.location.replace() in the <head>, a clean sitemap, and a check that the
redirect actually renders for Googlebot. For anything permanent or high-value, the
extra reliability of a 301 is worth almost any effort to obtain.
AI summary
A condensed take on the Advanced version:
- A JavaScript redirectA JavaScript redirect is a client-side redirect that uses code like window.location.replace() to send a visitor (and crawler) to a different URL. Because it only fires after the page is downloaded and rendered, Google prefers server-side and meta refresh redirects above it. is client-side (
window.location.replace(),.href,.assign()). It’s only processed after renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. — phase three of crawl → render → indexStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed. — whereas a server-side 301 is seen at crawl time. - The render queue is the risk: a page “may stay on this queue for a few seconds, but it can take longer,” with no fixed service-level timeline, and renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. can fail entirely, in which case Google may never see the redirectA redirect sends browsers and crawlers from a requested URL to a different one. An HTTP redirect specifically is a 3xx status code paired with a Location header; meta refresh and JavaScript redirects achieve a similar navigation without being a 3xx response themselves. Permanent redirects (301/308) are Google's signal the target should be canonical; temporary ones (302/303/307) aren't. and keeps the source page indexed.
- Google’s preference order: server-side (301/302/307/308) → meta refreshA meta refresh redirect is a client-side redirect written as an HTML <meta http-equiv=\"refresh\"> tag (or an equivalent HTTP Refresh header) — not an HTTP status code. The server returns a normal 200, then the browser navigates after the page loads. An instant (0-second) one is read by Google as permanent; a delayed one as temporary. → JavaScript. Docs: “Only use JavaScript redirects if you can’t do server-side or meta refresh redirectsA meta refresh redirect is a client-side redirect written as an HTML <meta http-equiv=\"refresh\"> tag (or an equivalent HTTP Refresh header) — not an HTTP status code. The server returns a normal 200, then the browser navigates after the page loads. An instant (0-second) one is read by Google as permanent; a delayed one as temporary..”
- The target becomes a canonicalizationHow search engines pick one canonical URL among duplicates and consolidate signals onto it. signal once Google interprets a JS redirect — so the “JS redirects don’t pass PageRankPageRank is Google's original recursive link-graph algorithm: a page's score depends on the scores of the pages linking to it, and in the published model each page's score is split across its outbound links (the simplified version: links are weighted votes). Google says it's evolved since launch but still part of its core ranking systems.” myth is false — but Google doesn’t document that the outcome matches a server-side redirect’s PageRankPageRank is Google's original recursive link-graph algorithm: a page's score depends on the scores of the pages linking to it, and in the published model each page's score is split across its outbound links (the simplified version: links are weighted votes). Google says it's evolved since launch but still part of its core ranking systems. flow, ranking, or timing exactly. JS redirects aren’t a penalty trigger unless used for cloaking (sneaky redirects).
- Legitimate uses: constrained platforms (Google itself used them on their blog), and SPA error pages that redirect to a real 404 (Google-endorsed).
- Meta refresh ≠ JS redirect: it’s HTML-level; 0s = permanent, any delay =
temporary.
history.pushState()/replaceState()aren’t redirects — no HTTP signal, crawlersA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index. don’t follow them. - Hugo
aliases:are meta refresh, not 301s — a common trap on static generators. - Implementation:
window.location.replace()in the<head>, single hop to the destination, remove source from sitemapA sitemap is a file that lists the pages, images, videos, and other files on your site so search engines can discover them. It helps discovery, but submitting a sitemap doesn't guarantee crawling or indexing., repoint internal linksAn internal link is a hyperlink from one page on a website to another page on the same website. Internal links help search engines discover your pages and pass ranking signals (PageRank and anchor-text context) between them., ensure GooglebotGooglebot is Google's web crawler — the software that fetches pages so Google can index and rank them. It comes in two variants, Googlebot Smartphone (primary, under mobile-first indexing) and Googlebot Desktop, and runs an evergreen Chromium renderer. can fetch the JS. - Detection: crawl with JS rendering on, Chrome DevTools / Redirect Path, “Page with redirectA Google Search Console Page Indexing status for a URL that redirects elsewhere. It's not indexed by design because it's a redirect — the destination is a separate question, and Google says the target may or may not end up indexed — usually expected, not an error (unlike the separate \"Redirect error\").” in GSC.
Official documentation
Primary-source guidance on redirectsA redirect sends browsers and crawlers from a requested URL to a different one. An HTTP redirect specifically is a 3xx status code paired with a Location header; meta refresh and JavaScript redirects achieve a similar navigation without being a 3xx response themselves. Permanent redirects (301/308) are Google's signal the target should be canonical; temporary ones (302/303/307) aren't. and JavaScript.
- Redirects and Google Search — the preference hierarchy (server-side → meta refreshA meta refresh redirect is a client-side redirect written as an HTML <meta http-equiv=\"refresh\"> tag (or an equivalent HTTP Refresh header) — not an HTTP status code. The server returns a normal 200, then the browser navigates after the page loads. An instant (0-second) one is read by Google as permanent; a delayed one as temporary. → JavaScript), permanent vs. temporary handling, and the meta refresh delay rules.
- JavaScript SEO Basics — the render pipeline and the endorsed SPA-404 redirect use case.
- Fix search-related JavaScript problems — soft 404sA soft 404 is a URL that returns a success status code (usually 200 OK) even though the page is empty, missing, or shows a 'not found' message. It isn't a status code a server sends — it's a label search engines apply after comparing the response code against the rendered content, and they treat the page like a 404 for indexing., renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM., and debugging JS that Google can’t process.
- Sneaky redirects (spam policies) — when a redirect crosses into cloaking and becomes a policy violation.
Bing / Microsoft
- Bing Webmaster Help — entry point for Bing’s current guidance. (At the time of writing, Bing had no dedicated redirects help page at a stable URL; BingbotBingbot is Microsoft Bing's primary web crawler — the bot that discovers, fetches, and renders pages to build the Bing index. That index also powers Yahoo, DuckDuckGo, Ecosia, and Microsoft Copilot, so Bingbot's reach is far wider than Bing's own search-market share. renders JavaScript less reliably than GooglebotGooglebot is Google's web crawler — the software that fetches pages so Google can index and rank them. It comes in two variants, Googlebot Smartphone (primary, under mobile-first indexing) and Googlebot Desktop, and runs an evergreen Chromium renderer., which makes JS-only redirects riskier for Bing indexation.)
Quotes from the source
On-the-record statements from Google and the people who work on Search. Each Google-docs link is a deep link that jumps to the quoted passage.
Google — the preference order and the renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. risk
- “Only use JavaScript redirectsA JavaScript redirect is a client-side redirect that uses code like window.location.replace() to send a visitor (and crawler) to a different URL. Because it only fires after the page is downloaded and rendered, Google prefers server-side and meta refresh redirects above it. if you can’t do server-side or meta refreshA meta refresh redirect is a client-side redirect written as an HTML <meta http-equiv=\"refresh\"> tag (or an equivalent HTTP Refresh header) — not an HTTP status code. The server returns a normal 200, then the browser navigates after the page loads. An instant (0-second) one is read by Google as permanent; a delayed one as temporary. redirectsA redirect sends browsers and crawlers from a requested URL to a different one. An HTTP redirect specifically is a 3xx status code paired with a Location header; meta refresh and JavaScript redirects achieve a similar navigation without being a 3xx response themselves. Permanent redirects (301/308) are Google's signal the target should be canonical; temporary ones (302/303/307) aren't..” — Google Search Central docs. Jump to quote
- “While Google attempts to render every URL GooglebotGooglebot is Google's web crawler — the software that fetches pages so Google can index and rank them. It comes in two variants, Googlebot Smartphone (primary, under mobile-first indexing) and Googlebot Desktop, and runs an evergreen Chromium renderer. crawled, renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. may fail for various reasons. This means that if you set a JavaScript redirect, Google might never see it if rendering of the content failed.” — Google Search Central docs. Jump to quote
Google — the endorsed SPA use case
- “Use a JavaScript redirect to a URL for which the server responds with a
404HTTP status codeAn HTTP status code is the three-digit number a server returns with every response to tell a browser or crawler what happened to its request — success, redirect, client error, or server error. For SEO the code matters as much as the content: it tells Google and Bing whether to index a page, follow a redirect, retry later, or drop the URL from the index. (for example/not-found).” — Google Search Central docs. Jump to quote
Gary Illyes, Google
- On JS redirects generally: “Js redirects are probably not a good idea though.” (July 8, 2020)
- On Google using them anyway when nothing else worked: “We used JS redirects on webmasters.googleblog.com because that was the only thing we could use for 1:1 redirects, and it works on Google.” Coverage
Search Engine Journal — implementation and link equityPageRank is Google's original recursive link-graph algorithm: a page's score depends on the scores of the pages linking to it, and in the published model each page's score is split across its outbound links (the simplified version: links are weighted votes). Google says it's evolved since launch but still part of its core ranking systems.
- “JavaScript redirects typically use
window.location.replace()function rather thanwindow.location.hrefto avoid UX redirect loopsA redirect loop is a chain of redirects that circles back on itself instead of ever reaching a live page — URL A redirects to B and B redirects back to A (or a longer cycle). No page ever returns a 200, so browsers show ERR_TOO_MANY_REDIRECTS and crawlers can't index anything..” Read - “JavaScript redirects are not SEO-friendly and should be avoided when alternatives exist… Only implement JavaScript redirects when server-side alternatives are genuinely unavailable.” Read
Redirect types — cheat sheet
When Google sees it, and how it’s treated
| Method | When Google sees it | Treated as | Reliability |
|---|---|---|---|
Server-side 301 / 308 | Crawl time | Permanent | Highest |
Server-side 302 / 307 | Crawl time | Temporary | Highest |
Meta refreshA meta refresh redirect is a client-side redirect written as an HTML <meta http-equiv=\"refresh\"> tag (or an equivalent HTTP Refresh header) — not an HTTP status code. The server returns a normal 200, then the browser navigates after the page loads. An instant (0-second) one is read by Google as permanent; a delayed one as temporary., 0 seconds | HTML parse time | Permanent | High |
Meta refresh, delayed (>0s) | HTML parse time | Temporary | High |
| JavaScript redirectA JavaScript redirect is a client-side redirect that uses code like window.location.replace() to send a visitor (and crawler) to a different URL. Because it only fires after the page is downloaded and rendered, Google prefers server-side and meta refresh redirects above it. | After renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. | Follows the navigation | Lowest |
history.pushState() / replaceState() | — | Not a redirectA redirect sends browsers and crawlers from a requested URL to a different one. An HTTP redirect specifically is a 3xx status code paired with a Location header; meta refresh and JavaScript redirects achieve a similar navigation without being a 3xx response themselves. Permanent redirects (301/308) are Google's signal the target should be canonical; temporary ones (302/303/307) aren't. | n/a |
JavaScript redirect methods
| Code | History behavior | Use it? |
|---|---|---|
window.location.replace("url") | Removes source from history | Yes — recommended |
window.location.href = "url" | Keeps source (back-button loop) | Avoid for redirects |
window.location.assign("url") | Same as .href | Avoid for redirects |
document.location.href = "url" | Alias for .href | Avoid for redirects |
Fast facts
- Google’s order: server-side → meta refresh → JavaScript. Use JS only when the first two are impossible.
- Once interpreted, a JS redirect’s target is a canonicalizationHow search engines pick one canonical URL among duplicates and consolidate signals onto it. signal — the “JS redirects don’t pass PageRankPageRank is Google's original recursive link-graph algorithm: a page's score depends on the scores of the pages linking to it, and in the published model each page's score is split across its outbound links (the simplified version: links are weighted votes). Google says it's evolved since launch but still part of its core ranking systems.” myth is false. Google doesn’t document that outcome as identical to a 301’s, so the real risk is delay / render failure, not a documented PageRankPageRank is Google's original recursive link-graph algorithm: a page's score depends on the scores of the pages linking to it, and in the published model each page's score is split across its outbound links (the simplified version: links are weighted votes). Google says it's evolved since launch but still part of its core ranking systems. penalty.
- JS redirects are not a penalty unless used for cloaking.
- Hugo
aliases:= meta refresh, not 301. - A processed JS redirect appears as “Page with redirectA Google Search Console Page Indexing status for a URL that redirects elsewhere. It's not indexed by design because it's a redirect — the destination is a separate question, and Google says the target may or may not end up indexed — usually expected, not an error (unlike the separate \"Redirect error\").” in GSCA free Google service that reports how a site performs in Google Search and surfaces problems with how Google crawls, indexes, and serves it. It's first-party data straight from Google — but you don't need it to appear in results..
Should I use a JavaScript redirect? — decision checklist
Walk this top to bottom; stop at the first “yes.”
- Can I set a server-side
301/302/307/308? → Do that. Stop here. - Can I edit the HTML
<head>but not server config? → Use a 0-second meta refreshA meta refresh redirect is a client-side redirect written as an HTML <meta http-equiv=\"refresh\"> tag (or an equivalent HTTP Refresh header) — not an HTTP status code. The server returns a normal 200, then the browser navigates after the page loads. An instant (0-second) one is read by Google as permanent; a delayed one as temporary. for permanent moves. Stop here. - Neither is possible (locked-down platform), or it’s a SPA error page that should hit a real 404? → A JavaScript redirectA JavaScript redirect is a client-side redirect that uses code like window.location.replace() to send a visitor (and crawler) to a different URL. Because it only fires after the page is downloaded and rendered, Google prefers server-side and meta refresh redirects above it. is acceptable. Continue.
If you’re using a JavaScript redirect
- Use
window.location.replace()(not.href/.assign()). - Place the script in the
<head>, as early as possible. - RedirectA redirect sends browsers and crawlers from a requested URL to a different one. An HTTP redirect specifically is a 3xx status code paired with a Location header; meta refresh and JavaScript redirects achieve a similar navigation without being a 3xx response themselves. Permanent redirects (301/308) are Google's signal the target should be canonical; temporary ones (302/303/307) aren't. straight to the final destination — no chain through another redirect.
- Remove the source URL from your XML sitemapAn XML sitemap is a UTF-8 file listing the canonical URLs on your site (with optional lastmod) so search engines can discover and prioritize them. It's a discovery and diagnostic aid, not a guarantee of indexing — and Google ignores its priority and changefreq tags..
- Repoint internal linksAn internal link is a hyperlink from one page on a website to another page on the same website. Internal links help search engines discover your pages and pass ranking signals (PageRank and anchor-text context) between them. to the destination.
- Confirm the redirect’s JS is not blocked in
robots.txtso GooglebotGooglebot is Google's web crawler — the software that fetches pages so Google can index and rank them. It comes in two variants, Googlebot Smartphone (primary, under mobile-first indexing) and Googlebot Desktop, and runs an evergreen Chromium renderer. can render it. - You are not showing crawlersA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index. one page and redirecting users elsewhere (cloaking).
- Verify by crawlingCrawling is how search engines use automated bots (like Googlebot and Bingbot) to discover URLs and download pages. A page has to be crawlable to be indexed, but crawling on its own isn't a ranking factor. with JS renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. on and checking “Page with redirectA Google Search Console Page Indexing status for a URL that redirects elsewhere. It's not indexed by design because it's a redirect — the destination is a separate question, and Google says the target may or may not end up indexed — usually expected, not an error (unlike the separate \"Redirect error\").” in GSC.
The recommended JavaScript redirect
Put this in the <head> so it executes as early as possible in parse order:
<head>
<script>
window.location.replace("https://example.com/new-page/");
</script>
</head>replace() is the key choice — it drops the redirecting URL from session history,
so the back button doesn’t bounce the user straight back into the redirectA redirect sends browsers and crawlers from a requested URL to a different one. An HTTP redirect specifically is a 3xx status code paired with a Location header; meta refresh and JavaScript redirects achieve a similar navigation without being a 3xx response themselves. Permanent redirects (301/308) are Google's signal the target should be canonical; temporary ones (302/303/307) aren't..
The 0-second meta refresh (next-best when you can’t do server-side)
Not JavaScript, but the right fallback when you can edit HTML and not server config. A 0-second delay is treated by Google as a permanent redirectA 301 redirect is the HTTP status code for a permanent move: it tells browsers and search engines a URL has moved for good, and it's the strongest signal for consolidating a page's ranking signals onto the new URL. Google says permanent redirects don't cause a loss in PageRank.:
<head>
<meta http-equiv="refresh" content="0; url=https://example.com/new-page/">
</head>What NOT to use as a redirect
history.pushState() rewrites the address bar but performs no navigation and
sends no HTTP signal — crawlersA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index. won’t follow it:
// NOT a redirect — only changes the URL bar, no navigation happens
history.pushState({}, "", "/new-page/");If you need an SPA route change to be crawlable, give it a real <a href> link or
a genuine navigation, not just a History API call.
SPA error page → real 404 (Google-endorsed pattern)
When a single-page app resolves an unknown route, send it to an endpoint that
returns an actual 404 so Google processes the error instead of a soft 404A soft 404 is a URL that returns a success status code (usually 200 OK) even though the page is empty, missing, or shows a 'not found' message. It isn't a status code a server sends — it's a label search engines apply after comparing the response code against the rendered content, and they treat the page like a 404 for indexing.:
// On an unresolved route in your SPA:
window.location.href = "/not-found"; // /not-found must return HTTP 404 Patrick's relevant free tools
- Raw vs. Rendered HTML Checker — See what's in your page's initial HTML versus after JavaScript runs — headless-Chrome rendering only when the page actually needs it, a rendering-strategy verdict (SSR / prerendered / CSR / hybrid), ~15 calibrated JavaScript-SEO checks (noindex, canonicals, robots.txt blocking, links, soft 404s), a side-by-side raw-vs-rendered diff, and shareable reports.
- Redirect Chain Mapper — Trace every hop of a redirect chain — status codes, what changed at each step (HTTPS, www, slash, domain, path), a severity verdict, meta-refresh detection, and cleanup rules exportable for Cloudflare, .htaccess, and nginx. Single URL or batch of 8.
- HTTP Status & Redirect Checker — Paste up to 500 URLs — status codes, full redirect chains, final destinations, per-hop and total latency, response-header evidence, canonical checks, and redirect-system clues. Filter, compare snapshots, and export CSV. No signup, nothing stored.
Tools for finding and checking JavaScript redirects
- Screaming Frog SEO SpiderA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index. — enable JavaScript renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. (with a sufficient
renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. timeout) so JS-redirecting pages don’t just look like plain
200s. - Ahrefs Site Audit — renders pages and surfaces redirectsA redirect sends browsers and crawlers from a requested URL to a different one. An HTTP redirect specifically is a 3xx status code paired with a Location header; meta refresh and JavaScript redirects achieve a similar navigation without being a 3xx response themselves. Permanent redirects (301/308) are Google's signal the target should be canonical; temporary ones (302/303/307) aren't., chains, and redirected internal linksAn internal link is a hyperlink from one page on a website to another page on the same website. Internal links help search engines discover your pages and pass ranking signals (PageRank and anchor-text context) between them..
- Chrome DevTools — Network tab — turn on “Preserve log” and watch the client-side navigation fire.
- Redirect Path (Chrome extension) — flags client-side redirects alongside server-side ones in a quick popup.
- Google Search ConsoleA free Google service that reports how a site performs in Google Search and surfaces problems with how Google crawls, indexes, and serves it. It's first-party data straight from Google — but you don't need it to appear in results. — URL InspectionA Google Search Console feature that reports how Google sees one specific URL on a property you own. By default it shows the last-indexed snapshot; a separate \"Test live URL\" mode fetches the current version. — see how a single URL was crawled and rendered, and whether Google landed on “Page with redirectA Google Search Console Page Indexing status for a URL that redirects elsewhere. It's not indexed by design because it's a redirect — the destination is a separate question, and Google says the target may or may not end up indexed — usually expected, not an error (unlike the separate \"Redirect error\")..”
- GSC — Page indexing reportThe Google Search Console report (formerly Index Coverage) showing how many of your URLs are indexed vs. not indexed, and grouping the not-indexed ones by reason. — “Page with redirectA Google Search Console Page Indexing status for a URL that redirects elsewhere. It's not indexed by design because it's a redirect — the destination is a separate question, and Google says the target may or may not end up indexed — usually expected, not an error (unlike the separate \"Redirect error\").” lists redirected URLs; “Redirect errorA Google Search Console Page Indexing status meaning Googlebot couldn't follow a redirect — a chain too long, a loop, a URL over the max length, or a bad/empty URL in the chain. It's a broken redirect to fix, not the normal \"Page with redirect.\"” surfaces chains and loops.
Mistakes to avoid with JavaScript redirects
- Using
window.location.href(or.assign()) instead of.replace()..hrefkeeps the redirecting page in session history, so the back button bounces the user straight back into the redirectA redirect sends browsers and crawlers from a requested URL to a different one. An HTTP redirect specifically is a 3xx status code paired with a Location header; meta refresh and JavaScript redirects achieve a similar navigation without being a 3xx response themselves. Permanent redirects (301/308) are Google's signal the target should be canonical; temporary ones (302/303/307) aren't. — a loop. Do instead: usewindow.location.replace(), which drops the source from history. - Reaching for a JS redirect on a permanent, high-value migration when a 301 is available. JS redirects are only processed after renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM., which can be delayed or fail outright — the wrong risk to take on a page that matters. Do instead: use a server-side 301; save JavaScript for constrained platforms and SPA error pages.
- Chaining the JS redirect into another redirect instead of landing on the final destination in one hop. Chains waste crawl budgetThe number of URLs an engine will crawl in a timeframe. and can surface as a redirect errorA Google Search Console Page Indexing status meaning Googlebot couldn't follow a redirect — a chain too long, a loop, a URL over the max length, or a bad/empty URL in the chain. It's a broken redirect to fix, not the normal \"Page with redirect.\" in GSCA free Google service that reports how a site performs in Google Search and surfaces problems with how Google crawls, indexes, and serves it. It's first-party data straight from Google — but you don't need it to appear in results.. Do instead: point the JS redirect straight at the destination URL.
- Leaving the source URL in the XML sitemapAn XML sitemap is a UTF-8 file listing the canonical URLs on your site (with optional lastmod) so search engines can discover and prioritize them. It's a discovery and diagnostic aid, not a guarantee of indexing — and Google ignores its priority and changefreq tags.. SitemapsA sitemap is a file that lists the pages, images, videos, and other files on your site so search engines can discover them. It helps discovery, but submitting a sitemap doesn't guarantee crawling or indexing. should list canonical, indexable URLs, not redirecting ones. Do instead: remove the source from the sitemapA sitemap is a file that lists the pages, images, videos, and other files on your site so search engines can discover them. It helps discovery, but submitting a sitemap doesn't guarantee crawling or indexing. once the redirect is live.
- Letting
robots.txtblock the script that fires the redirect. If GooglebotGooglebot is Google's web crawler — the software that fetches pages so Google can index and rank them. It comes in two variants, Googlebot Smartphone (primary, under mobile-first indexing) and Googlebot Desktop, and runs an evergreen Chromium renderer. can’t fetch the JS, it can’t render the redirect, and the source page can sit indexedStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed. indefinitely. Do instead: confirm the script is crawlable — the robots.txt tester checks exactly this. - Assuming Hugo’s
aliases:frontmatter gives you a 301. It has historically generated a meta refreshA meta refresh redirect is a client-side redirect written as an HTML <meta http-equiv=\"refresh\"> tag (or an equivalent HTTP Refresh header) — not an HTTP status code. The server returns a normal 200, then the browser navigates after the page loads. An instant (0-second) one is read by Google as permanent; a delayed one as temporary. HTML page, not a server-side redirect — verify your deployed version’s actual output rather than assuming. Do instead: use platform-level redirect rules (Netlify_redirects, Cloudflare WorkersA serverless function that runs at Cloudflare's global edge, close to every user., Vercelvercel.json) plusdisableAliases: true, as covered in Hugo SEOHugo SEO is the practice of optimizing sites built with Hugo, the Go-based static site generator. Hugo outputs finished HTML at build time, so content is in the raw HTML on the first fetch — but that alone doesn't guarantee good Core Web Vitals or rankings, and canonicals, taxonomy duplication, and aliases-vs-301s still need hands-on configuration.. - Treating
history.pushState()/replaceState()as a redirect. They only rewrite the address bar — no navigation, no HTTP signal, and crawlersA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index. don’t follow them. Do instead: use a real<a href>link or an actual navigation for anything that needs to be crawlable. - Showing crawlers one page and sending users somewhere else (cloaking). This is what turns a legitimate JS redirect into a sneaky redirects policy violation — it’s about intent, not the technique. Do instead: send everyone, bots included, to the same destination.
Common issues with JavaScript redirects
The source URL stays indexed long after the redirect went live
- Likely cause: the page is still sitting in Google’s render queue, or renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. failed outright.
- Fix + check: run a Live Test in Google Search ConsoleA free Google service that reports how a site performs in Google Search and surfaces problems with how Google crawls, indexes, and serves it. It's first-party data straight from Google — but you don't need it to appear in results.’s URL
Inspection tool on the source URL. If it hasn’t rendered yet, wait — Google
gives no fixed timeline for the render queue, so recheck periodically rather
than assuming a specific window. If renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. keeps failing, confirm the
redirectA redirect sends browsers and crawlers from a requested URL to a different one. An HTTP redirect specifically is a 3xx status code paired with a Location header; meta refresh and JavaScript redirects achieve a similar navigation without being a 3xx response themselves. Permanent redirects (301/308) are Google's signal the target should be canonical; temporary ones (302/303/307) aren't. script isn’t blocked (see the
robots.txtissue below).
The back button returns straight to the redirecting page
- Likely cause: the redirect uses
window.location.hrefor.assign()instead of.replace(), so the source URL stays in session history. - Fix + check: switch the script to
window.location.replace(). Confirm by landing on the destination and pressing back — it should skip the redirect source entirely.
GSC shows “Crawled – currently not indexed” instead of “Page with redirect”
- Likely cause: Google hasn’t rendered the page yet, or rendering is failing for that URL.
- Fix + check: crawl the URL with a JS-rendering crawlerA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index. (Screaming Frog or
Ahrefs Site Audit, rendering enabled) to confirm the redirect actually fires
client-side. Also check that the redirect script isn’t blocked in
robots.txt— the robots.txt tester confirms whether GooglebotGooglebot is Google's web crawler — the software that fetches pages so Google can index and rank them. It comes in two variants, Googlebot Smartphone (primary, under mobile-first indexing) and Googlebot Desktop, and runs an evergreen Chromium renderer. can fetch it.
An unresolved SPA route shows up as a soft 404 in GSC
- Likely cause: the route redirects somewhere, but the destination doesn’t
actually return an HTTP
404status. - Fix + check: point the redirect at an endpoint that genuinely responds
with
404(Google’s endorsed pattern), then re-run URL InspectionA Google Search Console feature that reports how Google sees one specific URL on a property you own. By default it shows the last-indexed snapshot; a separate \"Test live URL\" mode fetches the current version. to see the status change from soft 404A soft 404 is a URL that returns a success status code (usually 200 OK) even though the page is empty, missing, or shows a 'not found' message. It isn't a status code a server sends — it's a label search engines apply after comparing the response code against the rendered content, and they treat the page like a 404 for indexing. to a clean 404.
A JS-redirecting page still looks like a plain 200 in a crawl report
- Likely cause: the crawlerA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index. ran without JavaScript rendering enabled, so it only saw the initial HTML response, not the client-side navigation.
- Fix + check: re-crawl with JS rendering turned on (a 5-second timeout minimum is a reasonable starting point) and confirm the redirect now shows up.
Proving the redirect actually took effect
| Test to run | Expected result | Failure interpretation | Monitoring window | Rollback trigger |
|---|---|---|---|---|
| robots.txt tester on the redirectA redirect sends browsers and crawlers from a requested URL to a different one. An HTTP redirect specifically is a 3xx status code paired with a Location header; meta refresh and JavaScript redirects achieve a similar navigation without being a 3xx response themselves. Permanent redirects (301/308) are Google's signal the target should be canonical; temporary ones (302/303/307) aren't. script’s URL | Script is Allowed for GooglebotGooglebot is Google's web crawler — the software that fetches pages so Google can index and rank them. It comes in two variants, Googlebot Smartphone (primary, under mobile-first indexing) and Googlebot Desktop, and runs an evergreen Chromium renderer. | Disallowed — Google can’t fetch the script, so it can never render the redirect | Immediate | Fix or remove the blocking robots.txt rule before relying on the redirect |
| Crawl the source URL with JS renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. enabled (Screaming Frog / Ahrefs Site Audit) | CrawlerA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index. reports a client-side navigation to the intended destination | Page still reports a plain 200 with no navigation — renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. isn’t firing | Immediate (single crawl) | If it still doesn’t fire after fixing robots.txt, use a 0-second meta refreshA meta refresh redirect is a client-side redirect written as an HTML <meta http-equiv=\"refresh\"> tag (or an equivalent HTTP Refresh header) — not an HTTP status code. The server returns a normal 200, then the browser navigates after the page loads. An instant (0-second) one is read by Google as permanent; a delayed one as temporary. or server-side redirect instead |
| GSCA free Google service that reports how a site performs in Google Search and surfaces problems with how Google crawls, indexes, and serves it. It's first-party data straight from Google — but you don't need it to appear in results. URL InspectionA Google Search Console feature that reports how Google sees one specific URL on a property you own. By default it shows the last-indexed snapshot; a separate \"Test live URL\" mode fetches the current version. — Live Test on the source URL | Rendered result shows the redirect executing to the destination | Rendering fails, or the rendered HTML shows no navigation | Immediate for the live test itself | If Live Test repeatedly fails to render, treat this platform as unable to support a JS redirect — get server access or use meta refresh |
| GSC — Page indexing reportThe Google Search Console report (formerly Index Coverage) showing how many of your URLs are indexed vs. not indexed, and grouping the not-indexed ones by reason. for the source URL | Source URL is listed under “Page with redirectA Google Search Console Page Indexing status for a URL that redirects elsewhere. It's not indexed by design because it's a redirect — the destination is a separate question, and Google says the target may or may not end up indexed — usually expected, not an error (unlike the separate \"Redirect error\").” | Still shows as indexed, “Crawled – currently not indexedA Google Search Console Page Indexing status meaning Googlebot fetched the page but Google decided not to index it — usually a content- or site-quality signal, not a technical error.,” or duplicate contentThe same or very similar primary content reachable at more than one URL. There's no general duplicate content penalty — the real costs are possible signal dilution, the wrong URL getting chosen, and less-efficient crawling. | 2–4 weeks (indexingStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed. status updates on Google’s own schedule) | If still not classified as a redirect after 4+ weeks, revisit the render-blocking checks above |
| Manual back-button check in a browser after landing on the destination | Back button skips the source page entirely | Back button returns to the source page | Immediate | Switch the script from .href/.assign() to window.location.replace() |
Test yourself: JavaScript Redirects
Five quick questions on how JavaScript redirectsA JavaScript redirect is a client-side redirect that uses code like window.location.replace() to send a visitor (and crawler) to a different URL. Because it only fires after the page is downloaded and rendered, Google prefers server-side and meta refresh redirects above it. work and when to use them. Pick an answer for each, then check.
Resources worth your time
My related writing
- JavaScript SEO Issues & Best Practices — the renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. side, which is why JS redirectsA redirect sends browsers and crawlers from a requested URL to a different one. An HTTP redirect specifically is a 3xx status code paired with a Location header; meta refresh and JavaScript redirects achieve a similar navigation without being a 3xx response themselves. Permanent redirects (301/308) are Google's signal the target should be canonical; temporary ones (302/303/307) aren't. carry their timing risk.
- The Beginner’s Guide to Technical SEO — where redirects and renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. fit in the bigger picture.
My speaking
- How Search Works (SlideShare) — my walkthrough of crawlingCrawling is how search engines use automated bots (like Googlebot and Bingbot) to discover URLs and download pages. A page has to be crawlable to be indexed, but crawling on its own isn't a ranking factor., rendering, indexingStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed., and ranking — the pipeline that makes a JS redirect a phase-three event. (My standing disclaimer applies: “This is my understanding of systems… not going to be 100% complete or accurate.”)
From around the industry
- Redirects and Google Search (Google Search Central) — the official preference hierarchy and permanent-vs-temporary handling.
- Sneaky redirects (Google Search Central) — the spam-policy line that separates a legitimate redirect from cloaking.
- JavaScript Redirects & SEO: When & How To Use Them (Search Engine Journal) — practical implementation guidance and the
replace()vs.hrefdistinction. - Are JavaScript Redirects SEO-Friendly? (Search Engine Journal) — the “avoid when alternatives exist” summary.
- JavaScript Redirects and SEO: The Ultimate Guide (OnCrawl) — head-placement guidance, detection tooling, and the full Gary Illyes quote.
- Are JavaScript Redirects Bad for SEO? (Conductor) — a concise FAQ-style answer for the informational query.
- A Guide to Redirect Types (Lumar) — broader redirect taxonomy with JS redirects in context.
JavaScript Redirect
A JavaScript redirect is a client-side redirect that uses code like window.location.replace() to send a visitor (and crawler) to a different URL. Because it only fires after the page is downloaded and rendered, Google prefers server-side and meta refresh redirects above it.
Related: Rendering, Canonicalization
JavaScript Redirect
A JavaScript redirectA redirect sends browsers and crawlers from a requested URL to a different one. An HTTP redirect specifically is a 3xx status code paired with a Location header; meta refresh and JavaScript redirects achieve a similar navigation without being a 3xx response themselves. Permanent redirects (301/308) are Google's signal the target should be canonical; temporary ones (302/303/307) aren't. sends a user (and a search engine crawlerA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index.) to a different URL using client-side JavaScript — most commonly window.location.replace() or window.location.href. Unlike a server-side redirect, which is communicated through an HTTP status codeAn HTTP status code is the three-digit number a server returns with every response to tell a browser or crawler what happened to its request — success, redirect, client error, or server error. For SEO the code matters as much as the content: it tells Google and Bing whether to index a page, follow a redirect, retry later, or drop the URL from the index. (301, 302, 307, 308) before any content is sent, a JavaScript redirect only fires after the browser has downloaded the HTML, parsed it, and executed the script.
That timing is the whole story for SEO. A server-side 301 is seen by GooglebotGooglebot is Google's web crawler — the software that fetches pages so Google can index and rank them. It comes in two variants, Googlebot Smartphone (primary, under mobile-first indexing) and Googlebot Desktop, and runs an evergreen Chromium renderer. at crawl time; a JavaScript redirect isn’t processed until the page is rendered, which can happen seconds, hours, or longer after the crawl — and renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. isn’t guaranteed. Google’s own guidance is explicit: “Only use JavaScript redirects if you can’t do server-side or meta refreshA meta refresh redirect is a client-side redirect written as an HTML <meta http-equiv=\"refresh\"> tag (or an equivalent HTTP Refresh header) — not an HTTP status code. The server returns a normal 200, then the browser navigates after the page loads. An instant (0-second) one is read by Google as permanent; a delayed one as temporary. redirects.”
When Google does successfully render and process a JavaScript redirect, the target becomes a canonicalizationHow search engines pick one canonical URL among duplicates and consolidate signals onto it. signal, the same as a permanent server-side redirect — so the “JS redirects don’t pass PageRankPageRank is Google's original recursive link-graph algorithm: a page's score depends on the scores of the pages linking to it, and in the published model each page's score is split across its outbound links (the simplified version: links are weighted votes). Google says it's evolved since launch but still part of its core ranking systems.” claim is false. Google doesn’t document that the resulting PageRankPageRank is Google's original recursive link-graph algorithm: a page's score depends on the scores of the pages linking to it, and in the published model each page's score is split across its outbound links (the simplified version: links are weighted votes). Google says it's evolved since launch but still part of its core ranking systems. flow, ranking, or timing matches a server-side redirect exactly, though; the documented problem is the uncertainty of whether and when renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. succeeds, not a proven loss of equity — and other crawlersA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index. (notably BingbotBingbot is Microsoft Bing's primary web crawler — the bot that discovers, fetches, and renders pages to build the Bing index. That index also powers Yahoo, DuckDuckGo, Ecosia, and Microsoft Copilot, so Bingbot's reach is far wider than Bing's own search-market share.) render JavaScript less reliably than Google.
A meta refresh (<meta http-equiv="refresh">) is a separate, HTML-level redirect processed at parse time, not a JavaScript redirect; a 0-second meta refresh is treated as permanent, any delay as temporary. And history.pushState() / replaceState() are not redirects at all — they rewrite the address bar without issuing any HTTP signal, so crawlers don’t follow them.
Related: Rendering, Canonicalization
Build-time retrieval analysis plus live signals for this exact article. The automatic chunk report includes a deterministic readiness score and is ready without a model download.
Search Console
sampleGA4 traffic (28d)
sampleCloudflare traffic (7d)
sampledCrUX field data (28d, phone)
sampleGoogle NLP entities
localChangelog
Updated Jul 18, 2026.
Editorial summary and recorded change details.Summary
Walked back an unproven PageRank/ranking-parity claim to what Google actually documents (a canonicalization signal, not identical outcomes to a 301), removed a fixed 'seconds to weeks' render-queue timing claim Google doesn't publish, added a caveat that the GSC 'Page with redirect' label reflects a sampled state rather than a guarantee, softened a blanket claim about Hugo's aliases behavior to account for version drift, and added an explicit navigation-vs-history-state distinction for the JS redirect method table.
Change details
-
Does link equity pass through? now cites the verified canonicalization-signal claim instead of asserting PageRank flows 'comparably' to a server-side redirect; mirrored into the ai-summary, cheat-sheets, and both TLDRs.
-
Removed the unsupported 'anywhere from seconds to weeks for low-priority URLs' render-queue timing claim; Google documents no fixed timeline.
-
Added a caveat that the GSC 'Page with redirect' label reflects the sampled fetch/render/canonicalization state, not a permanent guarantee.
-
Softened the Hugo aliases claim from a blanket 'generates meta refresh' statement to account for version-to-version drift.
Full comparison unavailable — no prior snapshot was archived for this revision.