// blog / migrations

How I choose between a 301 and a 302 redirect, and avoid chains

A 301 redirect tells Google a page has moved for good, so Google normally indexes the new URL in its place, while a 302 says the move is temporary and the old URL usually stays in results. I use 301 for anything permanent, 302 only for short-term cases, and I point every redirect straight at its final address.

By Muhammad Younus Updated 10 min read Migrations

Migrations and redesigns, SEO side: illustration for "301 vs 302 redirects, and avoiding chains"
// 01 - the codes

301 vs 302 redirect: what does each code tell Google?

Each code is a short statement of intent. A 301 says the page has a new address and isn't coming back. A 302 says it's somewhere else for now. Google reads that statement when it decides which URL to keep, and it matters most during a move, when hundreds of old addresses have to hand their place in results to their replacements. That's where most of my site migration SEO help goes.

Google's redirects documentation is plain about it. With a permanent redirect, Googlebot follows it and the indexing pipeline uses it as a signal that the target should be canonical. With a temporary one, Googlebot still follows it, but the pipeline doesn't use it as that signal. Google's page on HTTP status codes calls the 301 a strong signal and the 302 a weak one. Weak isn't zero, and strong isn't a promise: Google weighs redirects alongside canonical tags and sitemaps, and it can still pick a different canonical than the one you'd like.

The worst redirect is the one that's missing. On one WooCommerce store, daily clicks fell from 162 to 49 in three days after a redesign changed URLs without mapping the old ones to the new, and they came back once each old URL had a 301 to its closest new page.

The redirect codes, what Google does with each, and when I use them
CodeWhat it saysHow Google treats itWhen I use it
301 Moved PermanentlyThe page has a new permanent addressA strong signal the target should be canonical; the target shows in resultsRenamed pages, merged pages, domain and URL moves
308 Permanent RedirectSame as a 301, and the request method is keptEquivalent to a 301Fine when a server or CDN sends it
302 FoundThe page is somewhere else for nowA weak signal; the source page shows in resultsA page that's coming back
307 Temporary RedirectSame as a 302, and the request method is keptEquivalent to a 302The same short-term cases as a 302
303 See OtherFetch a different resource insteadTreated as temporary, like a 302Almost never for a page that should rank

Two other kinds turn up on WordPress sites. An instant meta refresh, set to 0 seconds, is read as permanent, and a delayed one as temporary. A JavaScript redirect is the last resort, because Google only sees it if the page renders. So when I audit redirects, I read the status code in the response headers, not a plugin screen that says a redirect exists.

// 02 - the exceptions

When should I use a 301 vs a 302?

Use a 301 for anything permanent and a 302 only when the old URL is coming back. My test is a single question: is it coming back? If the honest answer's yes, and soon, a 302 fits. If it's no, or nobody knows, it's a 301.

Google's own example of a temporary redirect is a service that's unavailable for a while, where you send visitors to a page that explains what's happening. Its testing guidance adds another: when a test sends visitors from the original URL to a variant, use a 302, not a 301, and remove the test once it's done. A seasonal page that's switched off until next year goes in the same bucket.

What I don't use a 302 for is a permanent change dressed up as a temporary one, and the usual culprit is a default nobody changed. WordPress's own wp_redirect() function sends a 302 unless the code passes another status, so a custom snippet that moves pages for good can quietly send the temporary code. The browser lands in the same place either way, so nobody notices.

If a 302 has sat on a page that's never coming back, I change it to a 301. And a deleted page with nothing close to replace it doesn't get a redirect of either kind; sending it to the homepage only hides the dead end.

// watch out

Check the code, not the destination. Clicking an old link only shows where it lands. curl -I on the old URL prints the status line, and in Chrome DevTools the Network panel's Status column shows each hop's code, with Preserve log ticked so nothing clears between page loads. That code is the part Google reads.

// 03 - caching

301 vs 302 redirect caching: does a browser remember a 301?

It can, and a 302 usually isn't remembered at all. The HTTP standard, RFC 9110, says "A 301 response is heuristically cacheable", and it gives the 308 the same line. Neither 302 nor 307 is on that list, so a browser only stores one when the server sends explicit cache headers for it.

That matters most while you're testing. A browser that's saved a 301 can skip the server and go straight to the new address, so if you publish a 301 to the wrong page and then fix it, your own browser may keep following the old rule while everyone else gets the new one. I test unsure targets with the cache disabled, and I check the code from the command line before I call it done.

Rather have me do this? One person, whole job.

Book a call on Upwork
// 04 - chains

What's a redirect chain, and how do I find them?

A chain is one URL passing through more than one redirect before it reaches a page. A to B to C is a chain of two hops. Google's crawlers follow up to 10 hops by default, so a short chain usually still gets there, but Google's site move guidance still advises redirecting to the final destination directly. Every extra hop is another request for the browser and for Googlebot, and another rule that can break.

Chains pile up one sensible change at a time. Take an address first published before the site had HTTPS. Later the domain changed, and later still a restructure moved posts under /blog/. A link on another site still points at the oldest version, so it goes HTTP to HTTPS, old domain to new, old path to new path. That's three hops, each added by someone doing their job properly.

When a chain runs too long or loops, Search Console lists the URL under Redirect error in the Page indexing report. Old URLs showing as Page with redirect are normal: Google describes them as non-canonical URLs that redirect elsewhere, so they aren't indexed themselves. It's the Redirect error rows that need work, and when new URLs won't index for other reasons, that's a separate crawl and indexing diagnosis.

To find chains before Google does, I run the old URLs through a crawler in list mode with redirects followed, then sort by hop count. The list comes from the same places as the URL list for a Wix to WordPress move. For a spot check, curl -sIL on one URL prints every hop and its status in order.

// 05 - the layer

Where should a redirect live: server, plugin or CDN?

Any of the three can send a proper 301. Google recommends server-side redirects because they've got the highest chance of being read correctly, and all three count: Googlebot gets a status code and a new location before any page content. So the real question is which layer the person running the site can see and keep tidy.

The three places a WordPress redirect can live, and what I watch for in each
WhereHow it's setWhat I watch for
Web serverApache's .htaccess with mod_alias or mod_rewrite, or NGINX return and rewrite rulesFast and independent of WordPress, but easy to lose on a host move
WordPress pluginA redirect manager in the dashboard, or code that calls wp_redirect()Easy to see and edit; the code route defaults to 302 unless a status is passed
CDNEdge rules such as Cloudflare's Single Redirects or Bulk RedirectsCloudflare defaults to 301, but nobody editing WordPress can see these rules

My rule is one layer per job. Site-wide rules, like HTTP to HTTPS and one hostname over the other, go in one place, usually the server or the CDN. Page moves go in one list, usually a plugin, so whoever runs the site can see them. A split setup is where chains breed: a CDN rule adds the www, the server adds the trailing slash, a plugin moves the page, and each layer's owner only sees their own hop.

// 06 - the method

How I flatten redirect chains after a migration

This is the order I work in once a move has settled, or when an audit turns up chains left from old moves. The aim: every old URL answers with one redirect, straight to a page that returns 200.

  1. Step 01

    Put every rule from every layer in one sheet

    I export the plugin's redirect list, read the server config and list the CDN rules. Until they sit side by side, nobody can see a URL's whole path.

  2. Step 02

    Add every old URL that still gets requests

    The Search Console export by page, the old sitemaps and a backlink export add the addresses that links and bookmarks still use, including ones no rule covers yet.

  3. Step 03

    Trace each URL to its final answer

    The crawler records every hop, each status and where the path ends. A final 404, a loop or a path through the homepage goes on the fix list.

  4. Step 04

    Point every rule at the final address

    If A goes to B and B goes to C, A's rule changes to go straight to C. B keeps its own rule to C, because B may have links of its own.

  5. Step 05

    Fix the ends that don't land

    A target that now 404s gets its closest live replacement. If nothing's close, the old URL returns a 404 or 410, not a redirect to something unrelated.

  6. Step 06

    Use the permanent code on every permanent move

    Any 302 left behind by a code default or a quick fix becomes a 301, unless the page is actually coming back.

  7. Step 07

    Stop linking to redirects

    Menus, internal links, canonical tags and the XML sitemap get the final URLs. Google's move guidance says to update internal links, and it treats every sitemap URL as a suggested canonical, so a redirecting URL doesn't belong there.

  8. Step 08

    Re-run the list, then leave the rules alone

    Every URL should now take one hop to a 200. Google's advice for a move is to keep redirects for as long as possible, generally at least a year, and I keep them longer when old addresses still have links.

// when to hand this over

If your site's been through two or three moves and nobody's sure which layer does what, that clean-up is part of the migration work I do, remotely and from the search side. The build stays with your developer.

Book a call on Upwork

Is this your site? Send me the URL.

Book a call on Upwork
// questions - migrations

What else do people ask about this?

Is a 302 redirect bad for SEO?

Not when the move really is temporary. Google still follows it; it just treats it as a weak signal that the new URL should be canonical. The trouble starts when a 302 sits on a permanent move and the old URL keeps showing in results.

What does a 307 or 308 redirect mean?

A 307 is the temporary one and a 308 the permanent one, and both keep the request method, so a form POST stays a POST. Google treats a 308 like a 301 and a 307 like a 302, so for ordinary pages either pair is fine.

How many redirects in a chain are too many?

Anything past one hop is more than you need. Google's crawlers follow up to 10 hops by default, but Google's move guidance still says to redirect straight to the final destination, so I flatten every chain I find.

Can I change a 302 to a 301 later?

Yes, and it's the fix I make most often. I change the status on the existing rule, keep the same destination, then run curl -I on the old URL to confirm a 301 actually goes out. Google reads the new code the next time it crawls that URL.

// sources - checked

Where do these rules come from?

Platform and Google documentation, opened and read on the day this was written. Everything else is how I work.

  1. Google Search Central: redirects and Google Search
  2. Google crawler documentation: how HTTP status codes affect Google's crawlers
  3. Google Search Central: site moves with URL changes
  4. Google Search Central: how to specify a canonical URL
  5. Google Search Central: minimize A/B testing impact in Google Search
  6. Search Console Help: Page indexing report
  7. WordPress developer reference: wp_redirect()
  8. Cloudflare docs: Single Redirects settings
  9. Cloudflare docs: URL forwarding and redirects
  10. RFC 9110 HTTP Semantics: status codes 301, 302, 307 and 308, and which are heuristically cacheable
  11. Chrome DevTools: Network features reference
Muhammad Younus, WordPress technical SEO consultant
// who wrote this

One consultant, writing down his own method

I'm Muhammad Younus, a WordPress technical SEO consultant with 8+ years of experience and 100+ client sites fixed. Top Rated Plus on Upwork with a 100% Job Success Score. Every post here is the way I actually do the job, written in the first person because it's one person doing it, remotely, with no team behind the name.

Nothing in these posts is a client I can't name or a number I can't show. Where a figure comes from a client's Search Console, it's from a published case study, and where a rule comes from Google or a platform, the source is linked at the bottom of the post.

// the service behind this post
Muhammad Younus with a friendly open smile, head tilted slightly
// next step

Want this done on your own site?

Book a call on Upwork, send the URL and read-only Search Console access, and you'll get a written scope for the search side before any work starts. One person does the whole job, remotely.

Book a call on Upwork