indexing.io
All posts
Migrations

301 Redirect Not Working? 9 Causes and How to Fix Each

A 301 redirect that is not working is usually cache, a rule matching first, or Google simply not having recrawled yet. Nine causes, in the order worth checking.

By the Indexing team

August 2026 · 9 min read

Coverage Console
White-hat · official methods
Presets

Ready to check coverage

Paste a sitemap to sweep every URL for index status, then submit the missing ones through the official Google Indexing API and Bing IndexNow.

Not indexed Discovered, not indexed Indexed ✓

Coverage

indexed

Submitting via

Avg time to index

URLs submitted

Now eligible

Live, interactive · sample data · official methods only

Official Google Indexing API · Bing IndexNow · verified sitemaps · no spam, no PBNs

A 301 redirect that "is not working" is almost always one of three things: your browser cached the old response, another rule is matching before yours, or the redirect is fine and Google simply has not recrawled the old URL yet. The last case is the most common and the least satisfying, because there is nothing to fix. Google has to visit the old address before it can learn the page moved, and on a page it crawls every six weeks, that is how long the move takes.

The rest of the causes are real bugs, and they fall into a short list. Work through them in the order below, because the cheap checks eliminate most cases before you start reading server config.

First, confirm what the server is actually sending

Before anything else, look at the raw response rather than the browser. A browser shows you the destination, which looks identical whether you sent a 301, a 302, or three hops of both.

curl -sIL https://example.com/old-page | grep -Ei "^HTTP|^location"

That prints every hop and its status code. You are checking three things: the status code is 301 or 308, there is exactly one hop, and the final URL is the one you intended. If all three are right, the redirect is not the problem and you can skip to the last two sections. If any is wrong, one of the causes below explains it.

1. Your browser cached the permanent redirect

This causes more false alarms than every real bug combined. Permanent means permanent to a browser too, so browsers cache 301s aggressively and some hold them until you clear site data. You fix the rule, reload, and land on the old destination anyway.

Test in a private window, on a different device, or with curl, which does not cache. Only after that should you conclude the fix did not take. This is also a good argument for using a 302 while you are still working out the mapping and switching to a 301 once it is settled, since a wrong 302 is far cheaper to undo in the wild.

2. Another rule is matching first

Redirect rules are evaluated in order, and the first match usually wins. In a file with two hundred rules written by four people over three years, a broad pattern near the top will quietly swallow the specific rule you just added at the bottom.

The classic collision is a trailing slash rule or a hostname canonicalization rule catching the request before your page-level rule ever runs. Search the whole config for anything matching the path prefix, not just for your exact URL, and move the specific rules above the general ones.

3. A CDN or edge rule is overriding the origin

If you run Cloudflare, Fastly, or any edge layer, redirects can live in two places, and the edge answers first. The origin config you are staring at may be correct and simply never reached. This one is hard to spot because the two systems are usually owned by different people, and the person debugging has access to only one of them.

Test by hitting the origin directly, bypassing the CDN. If the origin returns the right redirect and the public URL does not, your answer is at the edge. While you are there, write down where the rule lives, because the next person to debug this will start in the same wrong place you did.

4. You sent a 302 where you meant a 301

This is the failure that does not look like a failure. Users reach the new page, analytics fills up, the response is valid, and Google refuses to move.

Google's redirect documentation draws the line clearly. For permanent redirects, "the indexing pipeline uses the redirect as a signal that the redirect target should be canonical", and search results show the new URL. For temporary redirects, "Googlebot follows the redirect, but the indexing pipeline doesn't use the redirect as a signal that the redirect target should be canonical", and results keep showing the old URL. So a 302 gets followed and then ignored for the one purpose you cared about. If your complaint is that Google still shows the old address, check the status code before anything else. The full breakdown of 301 vs 302 status codes and what each does to your index covers the other codes too.

5. The target redirects again

Chains build up honestly. A restructure two years ago, a domain change last year, and the original URL now takes three hops to arrive. Google does follow chains, and publishes the limit: "by default, Google's crawlers follow up to 10 redirect hops". So a short chain is not fatal on its own.

It is still worth flattening. Every hop is crawl capacity spent, and every hop is a separate rule that a future config change can break, at which point you lose the original URL rather than one link in the chain. Point old URLs directly at their final destination. The curl command above shows you the whole chain in one go.

6. The target has a noindex or a canonical pointing back

Here the redirect works perfectly and the move still fails, which is why it takes people so long to find. Googlebot follows your 301, arrives at the new page, and reads a meta robots noindex left over from staging, or a canonical tag still naming the old URL. Either one cancels the instruction you just gave.

The canonical version is especially common after a migration, because canonicals are usually generated from a base URL setting that somebody forgot to update. It is invisible from the server side and invisible in the browser unless you read the source. View the rendered HTML of the target and check the robots meta tag and the canonical link. Our walkthrough of what to verify after a website migration covers the rest of the template-level checks that survive a launch.

7. A deploy overwrote the rules

Redirects that live outside version control disappear. An .htaccess file edited over SSH, a plugin database table restored from an older backup, a container image rebuilt from a config that predates the change: all of these silently remove redirects that worked yesterday.

The fix is procedural rather than technical. Keep the redirect map in the repository, deploy it like code, and add a handful of the most valuable redirects to whatever smoke test runs after a release. A redirect nobody monitors is a redirect that will be gone within a year.

8. You redirected everything to the homepage

Bulk-redirecting retired URLs to the homepage is fast, and it is why the pages never recover. Google is being told the old page was replaced by something that does not answer its queries at all, and none of the history transfers usefully.

Redirect each old URL to its closest genuine equivalent, and where none exists, let it 404. Google treats a 404 as a strong signal not to crawl that URL again, which is exactly the outcome you want for a page that is truly gone. When you are deciding on the target, look at what each old URL was actually earning first: a map of which queries belong to which page makes the right destination obvious, and it usually reveals a handful of old URLs still pulling traffic that nobody on the current team knew existed.

9. Nothing is broken and Google has not recrawled yet

If curl shows one clean 301 to the right target, and the target is indexable, then the redirect is working and you are waiting on a crawl. Google's guidance on site moves says "as a general rule, a medium-sized website can take a few weeks for most pages to move in our index; larger sites can take longer".

Because the work happens per URL, progress looks uneven. Pages Googlebot visits daily move within days. A deep product page it visits every six weeks moves in six weeks. For that period the index genuinely holds a mixture of old and new addresses, and a report showing both is accurate rather than broken. Give a normal site four weeks before you conclude anything is wrong.

What you can do meanwhile is make the old URLs easier to recrawl. They need to be reachable and crawlable, so do not block them in robots.txt to "clean them up", because a blocked URL is one Google can never fetch and therefore never sees the redirect on. That single mistake strands old URLs in the index indefinitely.

How to tell which cause you have, in order

Run the checks cheapest first. Each one eliminates several causes at once.

  1. curl the old URL and read the hops. Wrong status code points at cause 4, multiple hops at cause 5, no redirect at all at causes 1, 2, 3 or 7.
  2. Retry in a private window. If it now works, it was cause 1 and there is nothing to fix.
  3. Hit the origin directly, bypassing the CDN. A different answer means cause 3.
  4. Grep the whole config for the path prefix, not the exact URL. An earlier broad match is cause 2.
  5. Read the rendered HTML of the target for a noindex or a canonical naming the old URL. That is cause 6, and it is the one that survives every server-side check.
  6. Check the git history of the redirect map against the last deploy. A gap is cause 7.
  7. If all of the above are clean, it is cause 9 and the answer is time.

How to confirm the move actually finished

A working redirect and a completed move are different things, and only one of them is visible from your server. The redirect proves the instruction exists. The move requires Google to recrawl the old URL, follow the redirect, accept the target as canonical, and index it, and each of those can fail while your redirect stays perfectly healthy.

In Search Console, an old URL that has been processed correctly appears under the Page with redirect status, which means Google has seen the redirect and stopped indexing that address. That is the outcome you want on the source side, and our explanation of the "page with redirect" status covers how to read it. On the target side you want the new URL indexed. Checking one side without the other is how half-finished migrations get signed off.

For anything past a few dozen URLs, sampling in Search Console is not enough, partly because Google states that "the list of example URLs in the report is limited to 1,000 items, and isn't guaranteed to show all URLs in a given status, even when less than 1,000 items". Check both lists in bulk instead, so you can watch old URLs leaving the index as new ones arrive. When the two do not move together, something on this page is the reason, and watching which pages dropped out of the index is usually how the problem surfaces before anyone notices it in traffic.

One last note on retention, because it costs more traffic than any bug listed above. Google says to "keep the redirects for as long as possible, generally at least 1 year". After a domain change that is longer than the 180 days the Change of Address tool forwards signals for, and teams read the shorter number as the length of the migration. If you are in the middle of a domain move, our piece on whether changing your domain name hurts SEO goes through that timing gap in detail.

See Indexing sweep your coverage

Indexing bulk-submits your URLs through official methods, monitors coverage, diagnoses what is not indexed in plain English, and auto-resubmits. White-hat only, no spam, no guarantees that Google must index, just faster discovery.

Get every page indexed

Indexing bulk-submits your URLs through the official Google Indexing API, Bing IndexNow and sitemaps, monitors coverage, tells you in plain English why a page is not indexed, and auto-resubmits until it is found.

Official methods only · Coverage monitored in real time · Auto-resubmit

White-hat only · No spam, no PBNs, no black-hat · We speed discovery and re-crawl but Google decides what to index.