What Is a 301 Redirect? (And When to Use 302, 307, 308)
Two redirects can look identical to a user and still send completely different signals to Google. Here's the practical difference between 301, 302, 307, and 308, and which one to actually use in each situation.
- 301. Permanent. Default for every URL change you make on purpose.
- 302. Temporary. Use it when the original URL will come back.
- 307. Temporary, but the HTTP method is preserved (POST stays POST).
- 308. Permanent, method preserved. Next.js uses this by default.
For 99% of website redirects, the answer is 301. The other three exist for specific edge cases described below.
A 301 and a 302 look identical to a person clicking a link. Both quietly forward you to a different URL. To Google they're completely different signals. One says this page moved, transfer the rankings. The other says keep the old URL indexed, this is temporary. Pick the wrong one and you can quietly bleed link equity for months before anyone notices.
The HTTP spec (RFC 9110 §15.4) defines five permanent and temporary redirect codes. Four of them get used in practice. This post is the working reference for picking the right one.
The comparison, up front
| Code | Permanent? | Method preserved? | Passes ranking signal? | Default in |
|---|---|---|---|---|
| 301 | Yes | Browser may convert POST → GET | Yes (full) | Apache, Nginx, most CMS |
| 302 | No | Browser may convert POST → GET | No (Google keeps old URL indexed) | Many CMS defaults (problem) |
| 307 | No | Strictly preserved | No | Next.js (temp redirects) |
| 308 | Yes | Strictly preserved | Yes (full) | Next.js (perm redirects) |
The two columns that decide the right code: is the move permanent? and do you need to preserve the HTTP method (POST, PUT, etc.)? For ordinary GET requests on web pages, the method question doesn't apply and you're choosing between 301 (permanent) or 302 (temporary).
301: the default answer
A 301 says: this URL is gone, the new URL is the canonical one, transfer everything. Google processes the move by collapsing the old URL out of its index over the following days to weeks and moving the ranking signals onto the destination URL. Google's own docs describe this as the recommended code for URL changes on public-web content.
Use 301 for, at minimum:
- Renaming a slug (
/old-page→/new-page) - Moving to a new domain
- HTTP → HTTPS upgrades
- www → apex (or vice-versa) consolidation
- Merging two pages into one (pick the canonical destination)
- Restructuring URL hierarchies
If the old URL will never come back, the answer is 301. When in doubt between 301 and 302, the answer is still 301.
How long until Google processes a 301
From real recrawl data: the destination URL usually appears in the index within 3–10 days for crawled-regularly pages; long-tail or low-traffic URLs can take 4–8 weeks. The old URL drops out of the index on a similar timeline. Don't panic at temporary rank fluctuation during this window. It almost always resolves.
302: the most-misused code
A 302 says: this URL will come back, just send users somewhere else for now. Google reads this and intentionally keeps the original URL in its index. No ranking signal transfers to the destination because, as far as Google is concerned, the destination is just a temporary detour.
That's the right behavior for genuinely temporary moves:
- A/B test variants where traffic is being split temporarily
- Maintenance pages (“back in 10 minutes”)
- Geolocation redirects to a country-specific page
- Login gates that bounce back after authentication
- Seasonal landing pages that replace the canonical URL for a few weeks
Many CMS platforms (older WordPress installs, certain hosted-store platforms, default redirect plugins) emit 302 redirects when the move is genuinely permanent. The user gets to the right page, you ship the migration, you assume it's done. Six months later your organic traffic is lower than it should be and nobody knows why. The fix is to verify the redirect type after every implementation. Google has said it will eventually treat long-running 302s as 301s, but “eventually” is a vague promise. Don't rely on it.
307: when method matters
The 307 status code exists because the HTTP spec wasn't clear enough about what browsers should do with the request method when following a 302. Historically, browsers would happily convert a POST to a GET when they saw a 302, which is technically a spec violation but became the de-facto behavior. The 307 (RFC 9110 §15.4.8) closed the ambiguity: the method must not change.
Use 307 instead of 302 when:
- You're temporarily redirecting an API endpoint and clients are POSTing or PUTting
- A form submission needs to be re-routed mid-flight without dropping the request body
- You're writing low-level browser/proxy behavior (HSTS uses 307 internally for the HTTP → HTTPS upgrade before HSTS itself takes over)
For an ordinary blog post or marketing page (GET requests), 307 and 302 behave identically. The distinction only matters when you have non-GET traffic. SEO-wise, Google treats 307 exactly like 302. Temporary, original URL stays indexed.
308: permanent + method preserved
308 is to 307 what 301 is to 302: the permanent counterpart that also locks in the HTTP method. Defined in RFC 7538 to clean up the same method-change ambiguity 308 closed for temporary redirects.
For ordinary website redirects, 301 and 308 are interchangeable. Both are permanent, both pass full ranking signal, both get the destination URL into Google's index. The difference only shows up when you have non-GET traffic in the mix.
Next.js uses 308 (permanent) and 307 (temporary) as its defaults in next.config.js redirect rules, not 301/302. For SEO this is fine. They're functionally equivalent. If you need an actual 301 (e.g., to match a contract or analytics tool that expects it), set statusCode: 301 instead of permanent: true.
How to actually implement each
Apache (.htaccess)
# Permanent (301), the common case
Redirect 301 /old-page https://example.com/new-page
# Temporary (302)
Redirect 302 /sale /summer-promo
# Pattern-based with RewriteRule
RewriteEngine On
RewriteRule ^old-section/(.*)$ /new-section/$1 [R=301,L]Nginx
server {
# 301: single URL
location /old-page {
return 301 https://example.com/new-page;
}
# 301: entire domain rewrite
server_name old-domain.com;
return 301 $scheme://new-domain.com$request_uri;
}Next.js (next.config.js)
module.exports = {
async redirects() {
return [
// 308 (permanent: true is the Next.js default)
{ source: '/old-page', destination: '/new-page', permanent: true },
// 307 (permanent: false)
{ source: '/promo', destination: '/summer', permanent: false },
// Force 301 specifically (e.g. when 308 isn't an option)
{ source: '/legacy', destination: '/new', statusCode: 301 },
];
},
};Express / Node
app.get('/old-page', (req, res) => {
// res.redirect() defaults to 302; explicit is better
res.redirect(301, '/new-page');
});Five mistakes that cost rankings
1. Defaulting to 302 when the move is permanent
Already covered in the warning above, but it's worth restating because it's the most common cause of post-migration ranking loss we see. Always verify the actual status code with curl -I or our redirect checker.
2. Letting redirect chains grow
You ship a redirect from /v1 to /v2. A year later you rename to /v3 and add a second redirect from /v2 to /v3. Now /v1 requires two hops. Every additional hop adds latency, costs crawl budget, and risks one of the intermediate redirects breaking. Best practice: when you add a new redirect, rewrite any existing redirects that pointed to its source to point directly at the new destination instead. See our guide on finding and fixing redirect chains.
3. Redirect loops
One rule redirects HTTP to HTTPS. Another redirects www to apex. They're both fine individually. Combined wrong, you get HTTP → HTTPS → HTTP → HTTPS forever. Loops are almost always caused by interaction between separate rules. The reliable detection method: hit the URL and follow until you get a 200. If you get more than 5 hops, something's wrong.
4. Missing URL variations
When a URL is on the public web for any length of time, search engines pick up every variation that's ever been linked: with/without trailing slash, with/without www, HTTP and HTTPS, with various query strings. Each variation needs a redirect. Missing one means backlinks pointing at that variation lose their equity. After a migration: dump every URL that appears in Google Search Console's “Indexed” report and verify each one resolves.
5. Removing 301s after “everything looks fine”
A common cleanup instinct: it's been a year, the old URLs aren't in the index anymore, time to remove the redirect rules. Don't. External backlinks still exist on third-party sites and will continue to send traffic for years. Removing the redirect breaks those inbound links and drops the equity they were passing. Cost of keeping a 301 in place: essentially zero. Keep them indefinitely.
How to check your redirects
For a single URL:
# Show every hop and the final status
curl -ILs https://example.com/old-page | grep -i "location\|HTTP/"For checking a large list (after a migration, during a backlink audit, or whenever you suspect chains), paste the URLs into our redirect checker and you'll get the full chain for each one with status codes, hop count, and final destination. The bulk version handles tens of thousands of URLs in a single run, useful if you're post-migration and need to verify the whole sitemap. For the broader workflow, see our website migration checklist.
So which one should you actually use?
The decision compresses to two questions:
- Is the move permanent? Yes → 301 or 308. No → 302 or 307.
- Does the HTTP method need to be preserved? Yes → 307 (temp) or 308 (perm). No → 302 (temp) or 301 (perm).
For ordinary GET-only website redirects, the answer is almost always 301. If you're on Next.js, that becomes 308 by default. Same outcome. Save 302 for the rare genuinely-temporary case, and reach for 307 only when method preservation actually matters.
And whichever code you pick, verify it with curl -I or a redirect checker. The single highest-leverage habit in redirect work is “trust the spec, verify the response”.
Related Articles
How to Check for 404 Errors on Your Website →
Find and fix 404 errors hurting your SEO with Google Search Console, crawlers, and bulk checkers.
Free vs Paid Broken Link Checkers →
When free tools are enough and when you need a paid broken link checker.
How to Find Broken Links on Any Website (2026 Guide) →
Free methods, browser tools, and bulk checking to find and fix broken links on any website.