The difference between a 301 and a 302 redirect is one promise: a 301 says the page has moved for good, so browsers may remember it and Google moves the old URL's rankings to the new one; a 302 says the move is temporary, so Google keeps the old URL in its index. Use a 301 (or 308) whenever the old address is not coming back, and a 302 (or 307) only when it is. This guide explains what each of the four codes does, when a temporary redirect really is the right call, which code your server or framework sends when you do not say, and how to check. For what a 301 does to SEO in general, start with the 301 redirects guide.
Quick answer
- 301 Moved Permanently: the page has a new home for good. Renamed pages, new URL structures, http → https, www ↔ non-www, domain moves.
- 302 Found: the page is away for a while and will come back. A/B tests, a temporary campaign page, a login wall, a language or country redirect.
- 308 and 307 are the permanent and temporary versions that forbid the browser from turning a form
POSTinto aGET. For ordinary pages, 308 behaves like 301 and 307 like 302, in browsers and in Google. - The costly mistake is a 302 for a permanent move. Many tools send 302 unless told otherwise: Apache's
Redirect, mod_rewrite's[R], Caddy'sredir, PHP'sheader('Location: …'), WordPress'swp_redirect(). - Whatever the code, aim for one hop to the final URL.
- Check which code you really send with the redirect checker or
curl -sI, not a browser that has cached an old 301.
What is a 302 redirect?
A 302 redirect is the server's answer "the page you asked for is temporarily somewhere else". The response has status 302 Found and a Location header with the other address, and the browser follows it straight away. Unlike a 301, it carries no promise: the next request for the old URL should go to the old URL again.
HTTP/1.1 302 Found
Location: https://www.example.com/summer-sale/
Cache-Control: no-storeTwo consequences follow from "temporary":
- Browsers do not cache it by default. A 301 or 308 may be cached without an expiry date (RFC 9111 lets clients cache them heuristically). A 302 or 307 is only cached when the response says so with
Cache-ControlorExpires. This is why you can switch a 302 off and every visitor sees the change at once, while a 301 you regret may keep sending some browsers to the new URL for months. - Google keeps the old URL. Google's documentation on redirects and Google Search describes permanent redirects (301, 308) as a strong signal that the target should be the canonical URL, and temporary ones (302, 307) as a weak signal. With a 302, the old URL usually stays in search results, showing the content of the page it points to.
301 vs 302: what changes
| 301 / 308 | 302 / 307 | |
|---|---|---|
| Meaning | Moved for good | Away for now |
| Browser cache | Cached by default, often for a long time | Not cached unless headers say so |
| URL Google shows in results | Usually the new one | Usually the old one |
| Ranking signals | Consolidated on the new URL | Stay with the old URL |
| Easy to undo | No: cached copies linger | Yes |
For search, that is the whole difference. Google has said that 30x redirects do not lose PageRank, so neither code "leaks" ranking; what differs is which URL gets it. Google's John Mueller has also said that a 302 left in place for a long time is eventually treated as permanent, but "eventually" means weeks or months in which the old URL keeps its place and the new one waits. If the move is permanent, say so on day one.
302 vs 301: which one for your case
Whichever way round you search it, the decision comes down to one question: will the old URL be used again?
- No, the page has moved for good: 301. The 301 redirects guide covers what it does to rankings, and the setup guide for Apache, nginx, Cloudflare and WordPress has the rules.
- No, the whole domain has moved: 301, path by path, as in how to redirect a domain to another domain.
- Yes, the page is coming back: 302, for the cases listed under when to use a 302 redirect below.
- The page is gone and has no replacement: neither. A 404 or 410 is the honest answer; see 404 vs 410 vs redirect.
307 vs 308: when the request method matters
301 and 302 are old codes, and for historical reasons browsers may change the request method when following them: a form that POSTs to a 301 or 302 address can arrive at the new address as a GET, with the form data dropped. RFC 9110 permits this. Two newer codes close the gap:
| Code | Permanent? | Keeps method and body | Use it for |
|---|---|---|---|
| 307 Temporary Redirect | No | Yes | Temporary moves of form handlers and API endpoints |
| 308 Permanent Redirect | Yes | Yes | Permanent moves of form handlers and APIs; the default on some platforms |
| 303 See Other | No | No, always GET | After a form submission, to show a result page; never for moved pages |
For a normal page, requested with GET, 301 and 308 behave the same and Google treats them the same, and so do 302 and 307. You do not need to switch existing 301s to 308. Just do not "fix" a 308 your platform sends: Vercel and Next.js use 308 for permanent: true and 307 for temporary redirects, and both are correct.
You may also see 307 Internal Redirect in Chrome's developer tools when you open an http:// link. That is not your server: the browser upgraded the request itself because of your HSTS header, before anything went over the network. It costs no round trip and is a good sign.
When to use a 302 redirect
A 302 or 307 is right when the old URL must stay the one people and search engines remember:
- A/B and split tests that send some visitors to a variant URL. Google's guidance on website testing asks for a 302, not a 301, so the original stays indexed, plus a canonical on the variant pointing to the original.
- A temporary campaign or seasonal page, such as
/offers/pointing to/summer-sale/for six weeks. - A product that is briefly unavailable, sent to its category or a replacement, when it will be back in stock soon.
- Login walls and carts:
/account/redirecting a logged-out visitor to/login/. - Language or country redirects from a neutral URL, such as
/to/en/. Keep the neutral URL reachable and use hreflang, because Googlebot mostly crawls from the US and would only ever see one version.
When a 302 is not right:
- Maintenance. Redirecting every page to a "back soon" page for a few hours looks like the whole site moved to one URL. Answer
503 Service Unavailablewith aRetry-Afterheader instead; Google treats 503 as temporary and comes back later. - "We are not sure yet." A 302 "until we are sure" keeps the old URL ranking and delays the move. If you are unsure, test the rule with a 302 for an hour, then switch to 301 before launch.
- A page that is gone. If there is no equivalent, a 404 or 410 is more honest than a redirect to something unrelated, which Google treats like a missing page anyway.
Which redirect does your server send by default?
Most 302s on permanent moves are accidents: a tool's default that nobody overrode.
| Where | Default | Permanent version |
|---|---|---|
Apache Redirect /old /new | 302 | Redirect 301 /old /new |
Apache mod_rewrite [R] | 302 | [R=301,L] |
nginx return https://… (no code) | 302 | return 301 https://…; |
nginx rewrite … redirect | 302 | rewrite … permanent |
Caddy redir /new | 302 | redir /new permanent (301) |
| Cloudflare Redirect Rules | 301 | 301 or 308 in the rule |
Netlify _redirects | 301 | /old /new 301 |
Vercel vercel.json, Next.js redirects() | 307 (permanent: false) | permanent: true (308) or statusCode: 301 |
PHP header('Location: …') | 302 | header('Location: …', true, 301) |
WordPress wp_redirect() | 302 | wp_redirect( $url, 301 ) |
Express res.redirect(url) | 302 | res.redirect(301, url) |
Redirect plugins such as Redirection, Rank Math and Yoast SEO Premium create 301s unless you pick another type. The 301 redirect setup guide has the full rules for each server, and the redirect rule generator writes exact-match 301 rules from a list of old and new URLs.
One hop, whatever the code
The right code on every hop still costs visitors a round trip per hop, and chains are where codes get mixed. A typical one: http://example.com/shop → https://example.com/shop → https://www.example.com/shop → https://www.example.com/shop/. Each rule was added by a different person for a good reason, one of them is often a 302 from a default, and together they are three hops.
The cure is to decide the one final form of every URL (scheme, host, trailing slash) and send any wrong variant straight to it in a single 301 at the first layer that answers, the CDN or else the web server. Trailing slashes, www and https: pick one has the one-rule configs for nginx, Apache, Caddy and Cloudflare, and redirect chains after a migration shows how to find and flatten every hop across a list of old URLs.
How to check which redirect you have
The checker requests the address you enter and follows every redirect, recording each hop's status code and Location. It then requests the http:// and the other www variant of the final URL to see whether they redirect permanently, and asks Lighthouse how much time the redirects cost during the page load.

One redirect passes; two or more are a warning. The technical detail lists every hop as status from → to, so a 302 in the middle of a chain stands out.
The www question appears twice on purpose: in SEO, because two hosts split rankings, and in Best practices, because two hosts split cookies, caches and analytics.
From a terminal, the status of each hop:
curl -sIL http://example.com/shop | grep -iE "^(HTTP|location)"You want one 301 (or 308) line, one Location, then 200. A 302 or 307 on a move you meant to be permanent is the line to fix.
Common mistakes
- 302 for a permanent move. Symptom: the old URL stays in Google for months, showing the new page's content. Set 301 explicitly; the table above shows where.
- 301 for a test. A permanent redirect set up to "try something" gets cached by every browser that follows it. Experiment with 302, switch to 301 once the rule is right.
- Changing a 302 to a 301 and testing in the same browser. Browsers cache 301s, not 302s, so after the switch you see the new behaviour, but after switching back you may not. Test with curl or a private window.
- Redirecting to maintenance pages. Use 503 with
Retry-After, not a redirect. - Mixing codes in a chain. A 301 then a 302 sends Google mixed signals about which URL to keep. One hop, one permanent code.
Questions people ask
What is a 302 redirect?
A 302 redirect is a temporary redirect: the server answers the old URL with status 302 Found and a Location header, and the browser loads the other address. Because the move is temporary, browsers do not cache it by default and Google usually keeps the old URL in its results. Use it only when the original address will be used again.
When should I use a 302 redirect?
Use a 302 when the original URL will come back or must stay indexed: A/B tests that send visitors to a variant, a short campaign page, a briefly out-of-stock product, a login wall, or a language redirect from a neutral URL. For anything permanent, such as a renamed page or a new domain, use a 301 so rankings move to the new URL.
Is a 302 redirect bad for SEO?
No, not when the move really is temporary. A 302 tells Google to keep the old URL indexed, which is what you want for a test or a short campaign. It becomes a problem on a permanent move: the new URL waits in the wings while the old one keeps ranking. Google may eventually treat a long-standing 302 as permanent, but a 301 gets there at once.
What is the difference between 307 and 308 redirects?
A 307 is temporary and a 308 is permanent; both require the browser to repeat the request with the same method and body, so a form POST stays a POST. They are the method-safe versions of 302 and 301. For ordinary pages Google treats 308 like 301 and 307 like 302, so the choice only matters for forms and APIs.
Why does Chrome show a 307 Internal Redirect?
Chrome shows 307 Internal Redirect when it upgrades an http link to https by itself because the site sent an HSTS header, or is on the browser's HSTS preload list. No request reaches your server and no round trip is spent, so it is not a redirect you configured and not a problem. It means HSTS is working.