A redirect sends visitors and crawlers from one URL to another. The status code tells them whether the move is permanent, and that decides which URL search engines keep in their index. Picking the wrong one is a common cause of lost rankings after a redesign or migration.
The redirect codes
| Code | Meaning | Method on redirect | Search engines |
|---|---|---|---|
| 301 Moved Permanently | Permanent | Browsers may change POST to GET | Index the target; pass signals |
| 302 Found | Temporary | May change POST to GET | Keep the original indexed (at first) |
| 307 Temporary Redirect | Temporary | Method and body preserved | Like 302 |
| 308 Permanent Redirect | Permanent | Method and body preserved | Like 301 |
For normal page moves, 301 and 302 are what you need. Use 307/308 when redirecting API endpoints or form submissions, where the request method must stay POST.
When to use 301 (or 308)
- Changing a page’s URL (new slug, new folder structure).
- Moving to HTTPS, or between www and non-www. See redirect HTTP to HTTPS in Nginx.
- Merging duplicate or thin pages into one stronger page.
- Moving to a new domain. See website migration SEO.
Google treats a 301 as a strong signal that the target is canonical. Ranking signals pass to the new URL, and the old one drops out of the index.
When to use 302 (or 307)
- A product is temporarily out of stock and you send users to a category.
- A/B tests sending some users to a variant.
- Geo or language suggestions (better: show a banner, and don’t force a redirect).
- Maintenance pages (better: a 503).
If a “temporary” redirect stays in place for months, Google eventually treats it as permanent anyway. Don’t rely on 302 to keep an old URL indexed forever.
When not to redirect: 404 and 410
If content is gone and has no reasonable replacement, don’t redirect everything to the home page. Google treats that as a soft 404. Return:
- 404 Not Found: the page doesn’t exist.
- 410 Gone: removed deliberately and permanently. Crawlers drop it a little faster.
Redirect only when a genuinely equivalent page exists. See HTTP status codes.
Nginx examples
# single page, permanent
location = /old-page/ { return 301 /new-page/; }
# temporary
location = /promo/ { return 302 /black-friday/; }
# whole folder, keeping the rest of the path
location ^~ /docs/v1/ {
rewrite ^/docs/v1/(.*)$ /docs/v2/$1 permanent;
}
# removed content
location = /discontinued-product/ { return 410; }
# whole domain
server {
server_name old-example.com www.old-example.com;
return 301 https://example.com$request_uri;
}
For hundreds of URLs, one exact location = per URL (or a map) is faster and easier to maintain than long regexes. See Nginx rewrite rules.
Apache (.htaccess)
Redirect 301 /old-page/ https://example.com/new-page/
Redirect 302 /promo/ https://example.com/black-friday/
Redirect 410 /discontinued-product/
RedirectMatch 301 ^/docs/v1/(.*)$ https://example.com/docs/v2/$1
WordPress
Use a redirect plugin (Redirection, or the one in your SEO plugin), which also logs 404s so you can spot broken URLs. See WordPress redirects.
Avoid chains and loops
A chain is A → B → C. Each hop adds latency, and crawlers stop following after several hops. After every migration, update old redirects to point straight at the final URL, and update internal links so they don’t hit redirects at all.
A loop (A → B → A) makes the page unreachable (“too many redirects”). Typical causes: conflicting HTTPS rules in the app and the proxy, or www rules that fight each other. See fixing “too many redirects” in WordPress.
Caching
Browsers cache 301s aggressively, sometimes indefinitely. Test new permanent redirects with 302 first if you’re unsure, then switch to 301. To undo a cached 301, users must clear their cache. This is one more reason to get it right.
Testing
curl -sI https://example.com/old-page/ | grep -iE '^(HTTP|location)'
curl -sIL https://example.com/old-page/ | grep -iE '^(HTTP|location)' # follow the whole chain
Crawlers (Screaming Frog, Sitebulb) list every redirect, chain and loop on a site. Search Console’s Pages report shows “Page with redirect” for URLs Google has processed.
Quick reference
| Situation | Code |
|---|---|
| URL changed for good | 301 (308 for APIs) |
| Short-term detour | 302 (307 for APIs) |
| Content removed, no replacement | 410 or 404 |
| Maintenance | 503 + Retry-After |
| Domain move | 301 for every URL to its equivalent |
Related: technical SEO on your own server and canonical URLs.