301 vs 302 Redirects: What's the Difference and Which to Use

301 vs 302 Redirects: What's the Difference and Which to Use

· Updated

A 301 redirect says a URL has moved permanently, so browsers and search engines should use the new address from now on. A 302 redirect says the move is temporary: the original URL is still the real address and should keep being used.

For SEO, the practical difference is which URL Google keeps. Google treats a 301 as a signal that the destination should become the canonical URL, meaning the version shown in search results. It does not treat a 302 that way, so the old URL usually stays indexed. Neither code loses PageRank in itself. Use a 301 (or 308) for any change you don't plan to undo, and a 302 (or 307) only when the original URL is coming back.

301 vs 302 at a Glance

301 Moved Permanently302 Found
Meaning in HTTP (RFC 9110)The resource has a new permanent URL; future references should use itThe resource is temporarily at another URL; keep using the original
Browser cachingCacheable by default, even without Cache-ControlCached only if the response explicitly allows it
Which URL Google keepsThe destination: the redirect is a signal that it should become canonicalThe original (source) URL: not used as a canonical signal for the target
PageRankNo loss from the redirect itselfNo loss from the redirect itself; signals tend to stay with the source URL while it remains canonical
POST requestsMay be changed to GETMay be changed to GET
Method-preserving version308 Permanent Redirect307 Temporary Redirect
Typical usesChanged slug, merged pages, HTTPS, domain moveRotating campaign URL, A/B test, login redirect

Google's redirects documentation groups the codes the same way: 301 and 308 are permanent; 302, 303, and 307 are temporary.

What the Status Codes Actually Say

Both responses carry a Location header with the destination URL, and every browser follows both the same way. A visitor can't tell them apart. The difference is the instruction to whoever remembers URLs: browsers, caches, crawlers, and feed readers.

301 Moved Permanently. RFC 9110 defines it as a new permanent URI for the resource, and future references should use the new URL. A 301 is also heuristically cacheable: a browser may store it and skip the request to your server next time.

302 Found. The resource "resides temporarily under a different URI," and the client should continue to use the original URL for future requests. A 302 is not cached unless you add explicit caching headers.

Both codes carry the same historical quirk: a browser may turn a POST into a GET when following the redirect. That rarely matters for ordinary pages, but it breaks forms and APIs. 307 and 308 exist to prevent it.

How Google Treats 301 and 302 Redirects

Canonical URL: The Real SEO Difference

Google's documentation describes the behavior directly. With a permanent redirect, Googlebot follows the redirect and the indexing pipeline uses it as a signal that the target should be canonical. With a temporary redirect, Googlebot still follows it, but the indexing pipeline doesn't use it as that signal.

In practice:

  • 301: Google generally replaces the old URL with the new one in search results, and signals such as links consolidate on the destination.
  • 302: Google generally keeps the original URL in results, even though visitors land on the destination.

It is a signal, not a command. Google weighs redirects together with rel="canonical", internal links, and sitemaps. Its canonicalization guide calls redirects a strong signal and sitemaps a weak one. Keep all of them pointing at the same preferred URL.

Does a 302 Redirect Pass PageRank?

Short answer: according to Google, the redirect itself doesn't cost PageRank, whether it's a 301 or a 302.

The old "302s leak link equity" advice is outdated. What still matters is which URL receives the credit. Google groups the redirecting URLs and picks one canonical, and the canonical is the URL that ranks. A 302 tells Google to prefer the source, so the link signals you wanted on the new page may stay with the old one. MDN's 302 reference describes the same outcome: search engines won't attribute links to the new URL. For a permanent move, use a permanent redirect.

When Google Treats a Long-Lived 302 Like a 301

Google's documentation doesn't set a deadline after which a 302 counts as permanent. The clearest statement comes from Google's John Mueller in April 2021: a temporary redirect suggests the source URL is preferred and a permanent one the destination, but if all internal and external links point to the destination, Google will probably pick it anyway. That's why a long-lived 302 can end up treated like a 301.

The takeaway is to fix the status code yourself rather than wait. Canonicalization can eventually override a wrong 302, but you control the redirect, and a correct 301 removes the ambiguity immediately.

Browser Caching: Why a Mistaken 301 Is Hard to Undo

Because a 301 is cacheable by default, a browser that has seen it may redirect on its own next time without asking your server. If you publish a wrong 301 and fix the rule an hour later, returning visitors can still be sent to the old destination until their cache expires or is cleared.

Three habits avoid this:

  1. Test new rules with a private window or DevTools Disable cache turned on.
  2. When you want to limit how long browsers keep a 301, add explicit freshness to the redirect response, such as Cache-Control: max-age=3600. Explicit headers override heuristic caching.
  3. Use a 302 (or 307) only when the move really is temporary. Don't use it as a permanent substitute just to avoid caching. That trades a browser problem for an SEO one.

When to Use 301 vs 302

SituationUseWhy
URL slug or folder structure changed301The old URL won't come back
Two pages merged into one301 to the merged pageThe merged page replaces both
HTTP to HTTPS, non-www to www (or reverse)301 or 308A permanent preference for one host and protocol
Domain migration301, page to equivalent pageSignals move to each new URL; see the domain migration guide
/sale always points to the current campaign page302/sale is the lasting address; the target changes each season
A/B test that redirects to a variant URL302Google's testing guidance says so explicitly
Signed-out visitor opens /account and is sent to /login?next=/account302, 303, or 307/account remains the real URL
Product briefly out of stockUsually no redirectKeep the page live (200) with an availability note
Site down for a day or twoNo redirect; return 503Google's downtime guidance uses 503, not a redirect
Page deleted with no real replacement404 or 410A redirect to something unrelated helps no one; see soft 404 errors
Form handler or API endpoint moved308 (permanent) or 307 (temporary)Keeps POST as POST

If you can't decide, ask whether you'll ever want the old URL to show in search results again. If not, it's a 301.

307 and 308: The Method-Preserving Versions

CodePermanent?Can POST become GET?Google treats it as
301 Moved PermanentlyYesYes (historically allowed)Permanent
308 Permanent RedirectYesNoPermanent
302 FoundNoYes (historically allowed)Temporary
307 Temporary RedirectNoNoTemporary
303 See OtherNoYes, by designTemporary

For normal page links, which are GET requests, 301 and 308 behave the same, and so do 302 and 307. The newer codes matter when a form submission or API call is redirected. 303 is the "go look at this other page" response, used after a POST so that a reload doesn't resubmit the form.

Google treats 308 like 301 and 307 like 302, so frameworks that default to the newer codes, such as Next.js, are fine for SEO.

How to Set Up a 301 or 302 Redirect

Several common tools produce a 302 unless you ask for 301: Apache's Redirect without a status, RewriteRule with plain [R], nginx return with a URL but no code, PHP's Location header, and WordPress wp_redirect(). Always state the code explicitly, then check the live response.

Apache: Redirect 301 vs RewriteRule

Apache has two ways to send a redirect. They produce the same HTTP response when configured correctly.

Redirect / RedirectMatch (mod_alias) is for simple URL-to-URL moves:

# Permanent: /old-page → /new-page
Redirect 301 /old-page https://example.com/new-page

# Temporary: /sale → the current campaign page
Redirect 302 /sale https://example.com/collections/autumn-sale

# Exact match only (Redirect is a prefix match)
RedirectMatch 301 ^/old-page$ https://example.com/new-page

RewriteRule with the R flag (mod_rewrite) is for redirects that depend on conditions such as hostname, HTTPS, or query string:

RewriteEngine On

# Whole domain move, path preserved
RewriteCond %{HTTP_HOST} ^old-domain\.com$ [NC]
RewriteRule ^(.*)$ https://new-domain.com/$1 [R=301,L]

# Single path (.htaccess syntax, no leading slash); [R] alone would send a 302
RewriteRule ^old-page$ /new-page [R=301,L]
Redirect 301RewriteRule ... [R=301,L]
Modulemod_aliasmod_rewrite
Default status if omitted302302
MatchingPath prefix; the rest of the path is appendedRegular expression; conditions via RewriteCond
Best forPage moves, folder movesHost/HTTPS rules, query strings, complex logic

Apache's own guidance, When not to use mod_rewrite, recommends Redirect and RedirectMatch for simple redirection. Two details cause most surprises:

  • Redirect 301 /blog https://example.com/articles also redirects /blog/any-post to /articles/any-post, because the remaining path is appended. Use RedirectMatch with ^...$ for a single exact URL.
  • Don't mix both modules for the same URLs. In .htaccess, mod_alias runs first; in server or virtual host configuration, mod_rewrite runs first. A rule can win or lose depending on where it lives.

Add L to R. Without it, Apache keeps processing later rewrite rules after building the redirect.

Nginx

# Exact path, permanent
location = /old-page {
    return 301 https://example.com/new-page;
}

# Exact path, temporary
location = /sale {
    return 302 https://example.com/collections/autumn-sale;
}

# Pattern-based: "permanent" = 301, "redirect" = 302
rewrite ^/guides/(.*)$ /learn/$1 permanent;

# Separate server block for an old hostname
server {
    listen 80;
    server_name old-domain.com;
    return 301 https://new-domain.com$request_uri;
}

return is the clearer choice for a fixed destination. return with a URL and no code produces a 302. An old HTTPS hostname also needs a valid certificate and its own listen 443 ssl block before it can redirect. See the nginx rewrite module docs.

Next.js

// next.config.js
module.exports = {
  async redirects() {
    return [
      { source: '/old-page', destination: '/new-page', permanent: true },  // 308
      { source: '/sale', destination: '/collections/autumn-sale', permanent: false }, // 307
    ]
  },
}

permanent: true sends 308, not 301, and permanent: false sends 307, not 302. The Next.js docs explain that this keeps the request method intact. Google treats 308 as permanent, so there's no SEO reason to force a 301. If an old client really needs one, the config accepts statusCode: 301 in place of permanent. In the App Router, permanentRedirect() also uses 308, and redirect() uses 307 in most contexts.

WordPress

Redirect plugins (Redirection, Rank Math's redirection module, Yoast SEO Premium) let you choose the type for each rule. Check the type after saving; don't assume the default is the one you want.

In code, wp_redirect() defaults to 302 (wp_safe_redirect() has the same default and also limits redirects to allowed hosts). Pass the code and stop execution:

add_action('template_redirect', function () {
    if (is_page('old-page')) {
        wp_safe_redirect(home_url('/new-page/'), 301);
        exit;
    }
});

For hosted platforms, follow the redirect settings for Shopify, Webflow, Wix, or Squarespace, plus the WordPress guide.

PHP

header('Location: https://example.com/new-page', true, 301);
exit;

The PHP manual notes that a Location header sends a 302 unless a 3xx status is already set. A bare header('Location: ...') is temporary.

Cloudflare

Cloudflare Single Redirects run at the edge, before a request reaches your server. In the dashboard, open Rules > Overview, choose Create rule > Redirect Rule, set the match, target URL, and status code, then deploy. The available codes are 301 (the default), 302, 307, and 308. Preserve query string is off by default. For large lists of individual URLs, use Bulk Redirects instead of hundreds of single rules. Details are in Cloudflare's settings reference.

If Cloudflare and your origin both redirect, the same request can take two hops. Decide which layer owns each rule.

Meta Refresh and JavaScript Are Not Equivalents

A <meta http-equiv="refresh"> tag or window.location change happens after the page loads with a 200 status. Google says it interprets an instant meta refresh as permanent and a delayed one as temporary. It recommends JavaScript redirects only when neither server-side nor meta refresh redirects are possible, because rendering can fail. Other clients (link checkers, feed readers, many bots) see only the 200 page. Use these only on hosts that give you no server-side option.

How to Check Whether a Redirect Is 301 or 302

Dashboards show what you configured. Check what the server actually returns.

curl

# One request: status code and destination
curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' https://example.com/old-page
301 https://example.com/new-page

Add -L with a header dump to see every hop in a chain:

curl -sS -L -D - -o /dev/null --max-redirs 10 https://example.com/old-page \
  | grep -Ei '^(HTTP/|location:)'

curl -I is a quick shortcut, but it sends a HEAD request, and some servers answer HEAD differently from GET. If -I disagrees with the browser, trust the GET commands above.

Chrome DevTools

  1. Open DevTools and select Network.
  2. Turn on Preserve log so the redirect stays in the list after the page changes, and Disable cache so a stored 301 doesn't hide the real response.
  3. Load the old URL and select the first document request.
  4. Under Headers, read Status Code in the General section and location in Response Headers.

Chrome DevTools Network panel with Preserve log and Disable cache turned on and the first request selected, showing Status Code 301 Moved Permanently and a location response header pointing to the new URL

If the status line says "from disk cache," the browser reused a stored redirect without contacting your server. Reload with the cache disabled before drawing conclusions. A 307 Internal Redirect on an http:// URL is usually Chrome upgrading to HTTPS on its own because of HSTS, not a response from your server; test the HTTP redirect with curl instead.

curl and DevTools check one URL at a time. To see which links across your pages go through a 301, 302, 307, or 308, run a scan with Broken Link Checker and click the Redirect card.

Broken Link Checker site scan filtered to redirects, listing links with 301, 302, and 308 statuses, their final URLs, the pages they were found on, and a tooltip with the full redirect chain

Each redirected link shows:

  • The status of the first hop and the final status, such as 302 → 200
  • The final URL under the link, so you can see where the redirect actually lands
  • The full chain when you hover the status, such as 301 → 301 → 200 for a two-hop chain
  • Found on: the page containing the link, with a locator that opens it and highlights the link

The CSV export includes Status Code, Redirect Chain, and Final URL columns for each source page. Sort by status code to review every 302 and ask whether the move is really temporary. Then update internal links so they point straight to the final URL. Links whose chain ends in a 404, a server error, or a loop are listed under Broken, not Redirect.

Use a page scan for the page you're editing, or the whole-site scan for up to 10,000 pages of a public site. The first three checks are free. The scan finds redirects on links that appear on your pages. Old URLs that nothing links to anymore, such as a list of pre-migration addresses, won't show up. Test those from a list with curl or a crawler in list mode.

Common 301/302 Mistakes

1. Getting a 302 by Default

The most common problem isn't a wrong decision but a missing one: the defaults listed under How to Set Up all send 302. The page works, so nobody notices until the old URL stays in search results for months.

2. Chains and Loops

/a → 301 → /b → 302 → /c still loads, but every hop adds a request and another point of failure. Googlebot follows up to 10 hops, then gives up. A loop never loads at all. Point every old URL directly at its final destination. The full procedure is in how to find and fix redirect chains.

3. Redirecting Deleted Pages to the Homepage

Sending dozens of removed pages to / looks tidy, but Google may treat irrelevant redirects as soft 404s. Redirect to a genuinely equivalent page, or return 404 or 410.

4. Mixing 301 and 302 in a Migration

Migrations often combine rules from several places: a CDN rule sends 301, a CMS plugin sends 302, and a leftover .htaccess line adds another hop. The result is mixed signals for URLs that all moved permanently. Before launch, export the redirect map, test every old URL, and confirm each returns a single 301 or 308 to the right page. The domain migration guide covers URL mapping and post-launch checks.

A redirect protects old bookmarks and backlinks. It isn't a reason to keep linking to the old address. Update navigation, content, canonicals, and sitemaps to the final URL so the redirect handles only outside traffic.

6. Removing Redirects Too Soon

Old URLs keep receiving visits from backlinks, emails, and bookmarks for years. Google recommends keeping redirects for generally at least a year; for URLs with valuable backlinks, keep them indefinitely. See reclaiming broken backlinks for what happens when they disappear.

Frequently asked questions

Is a 301 or 302 redirect better for SEO?
Neither is better in general; they mean different things. Use a 301 (or 308) when the move is permanent, because Google treats it as a signal that the new URL should be canonical and shown in search. Use a 302 (or 307) only when the original URL will return, because Google keeps treating the original as the preferred URL.
What is the difference between 301 and 308?
Both are permanent redirects, and Google treats them the same. A 301 allows a client to change a POST request to GET when following it; a 308 requires the same method. For ordinary page links there is no practical difference.
How do I change a 302 redirect to a 301?
Change the status in the rule that creates it: Redirect 302 to Redirect 301 in Apache, [R] to [R=301,L] in mod_rewrite, return 302 to return 301 in nginx, permanent: false to true in Next.js, or the redirect type in your CMS or CDN. Then verify the live response with curl or DevTools. Google needs to recrawl the URL before search results change.
Should HTTP to HTTPS use a 301 or 302 redirect?
Use a permanent redirect, 301 or 308. HTTPS is a lasting choice of preferred URL, just like choosing www or non-www. Redirect each HTTP URL to the same path on HTTPS in one hop, and keep internal links, canonicals, and sitemaps on the HTTPS version.
Can I use a 302 for a URL I might change later?
If the old URL is not coming back, use a 301 even if the destination might change later. You can update a 301 rule to point to a newer page at any time. A 302 is for cases where the original URL itself should stay the preferred one, such as a rotating campaign URL or an A/B test.
Pavel Molyanov

Pavel Molyanov

Creator of Broken Link Checker

Content marketer with 10+ years of experience. Founder of a content marketing agency. Writing about SEO, content workflows, and website maintenance.

Broken Link Checker

Check Your Links in One Click

Broken Link Checker finds broken links and redirects on any page or across your whole website, and works in Google Docs and Sheets. Try 3 checks free, with no signup or card required.

More on broken links, SEO, and web maintenance.