You're migrating a site, changing domain names, or moving content around. You add a redirect rule—302, because it's temporary, right?—and three months later your old URL still ranks higher than the new one. Or you use a 301, browsers cache it forever, and now you can't test the destination without clearing cache on every device.
I've seen both scenarios dozens of times in support tickets. The redirect status code you pick matters more than most developers realize, and the mistakes fall into predictable patterns.
Mistake 1: Using 302 for permanent moves
This is the big one. You're restructuring your site, moving /blog/old-post to /articles/new-post, and you reach for a 302 because "it's just a redirect." Search engines see 302 as temporary. They keep indexing the old URL and pass little to no link equity to the new one.
The fix: Use 301 for any move you intend to keep longer than a few weeks. A 301 tells Google, Bing, and everyone else to forget the old URL and treat the new one as the canonical version. In Apache:
Redirect 301 /blog/old-post https://example.com/articles/new-post
In Nginx:
location = /blog/old-post {
return 301 https://example.com/articles/new-post;
}
If you're unsure whether a change is permanent, ask yourself: will this URL exist in six months? If no, it's temporary. Otherwise, it's permanent.
Mistake 2: Using 301 when you actually need temporary
The opposite problem bites you during A/B tests, maintenance windows, or staged rollouts. You redirect traffic to a test page with a 301. Browsers cache it aggressively—some for an entire year. Now your test is over, but half your users still see the old destination because their browser won't even ask your server.
The fix: Use 302 (or 307 if you care about preserving the HTTP method, more on that in a moment). A 302 is cacheable but typically isn't cached as long. For maximum control during testing:
Header set Cache-Control "no-cache, no-store, must-revalidate"
Redirect 302 /test-page https://example.com/experiment
That Cache-Control header ensures browsers re-check on every visit. Once your test concludes, remove the redirect or replace it with a 301 if the move became permanent.
Mistake 3: Ignoring HTTP methods when choosing between 302 and 307
A 302 allows the browser to change a POST request into a GET when following the redirect. This behavior is old, slightly broken, and baked into every browser for backward compatibility. Most of the time it doesn't matter because redirects happen on navigation, not form submissions.
But if you're redirecting an API endpoint or a form POST, 302 will quietly convert POST to GET. The client sends form data; your server redirects; the client hits the new URL with GET and no body. Data vanishes.
The fix: Use 307 for temporary redirects that must preserve the original method and body. In Nginx:
location = /api/legacy-endpoint {
return 307 https://example.com/api/v2/endpoint;
}
For permanent method-preserving redirects, use 308 instead. If your redirect doesn't involve POST, PUT, PATCH, or DELETE, 302 is fine.
Mistake 4: Forgetting that 301 responses get cached hard
You set up a 301 redirect in your .htaccess or Nginx config. You test it—works perfectly. Two hours later you realize you pointed it to the wrong destination, fix the config, reload… and your browser still goes to the wrong place.
301 redirects are cached by browsers with no explicit expiration. Chrome, Firefox, and Safari will remember that redirect indefinitely until you clear browsing data. If you pushed that redirect to production before catching the mistake, every visitor who hit the old URL once is now stuck.
The fix: Test with 302 first, especially if you're typing URLs from memory or copy-pasting. Once you confirm the destination is correct, change it to 301. If you already pushed a wrong 301 to production, you have two options:
- Leave the incorrect redirect in place and add a second redirect at the wrong destination pointing to the correct one (a redirect chain, not ideal but it works)
- Contact users via email or a banner asking them to clear their browser cache (not realistic for public sites)
For internal tools or known user bases, option two can work. For public sites, you're stuck with option one.
Mistake 5: Mixing up 301 and 308
You've heard that 308 is the "new 301" and decide to use it everywhere for permanent redirects. Older HTTP clients that don't recognize 308 will treat it as a generic 300-series response and might not follow it at all. Conversely, you use 301 for an API endpoint that accepts POST, and client libraries silently convert it to GET.
The fix: Match the code to your traffic. For standard website redirects where the vast majority of requests are GET—page navigation, image URLs, asset files—use 301. Search engines understand it, every browser handles it correctly, and it's been stable for decades.
For API endpoints, webhooks, or any service where HTTP methods other than GET matter, use 308. Modern HTTP clients respect it, and older ones that don't recognize 308 will typically fall back to treating it as a permanent redirect anyway.
Here's a quick decision tree:
- Redirecting a webpage? → 301
- Redirecting an API endpoint that receives POST/PUT/DELETE? → 308
- Temporary move for a webpage? → 302
- Temporary move for an API? → 307
So what if your CDN or proxy doesn't support 308?
Some older CDN configurations and reverse proxies don't recognize 308 as a valid status code. Cloudflare, Fastly, and modern Nginx versions handle it fine, but legacy setups or certain managed hosting platforms might strip it or return an error.
The fix: Check your CDN or proxy documentation. If 308 isn't supported and you need method-preserving permanent redirects, you have two workarounds:
- Handle the redirect at the application layer instead of the web server, so it never passes through the proxy
- Use 301 and document that clients must be prepared for GET conversion, then update your API to accept GET with query parameters as a fallback
Neither is perfect. The first adds latency because the request reaches your application server before redirecting. The second breaks REST semantics. If your API is internal or you control the clients, option one is cleaner.
Mistake 6: Chaining redirects
You migrate a site from oldsite.com to newsite.com, setting up a 301. A year later you restructure URLs on newsite.com, adding another 301 from /page to /new-page. Now a request to oldsite.com/page hits two redirects: first to newsite.com/page, then to newsite.com/new-page.
Each redirect adds latency. Browsers make an extra round trip, and search engines may stop following after two or three hops. Google has said they'll follow redirect chains but the PageRank passed through them diminishes.
The fix: Audit your redirects every time you add a new one. If a URL was already redirected, update the original rule to point directly to the final destination:
# Bad - chain
Redirect 301 /page https://newsite.com/page
Redirect 301 /page https://newsite.com/new-page
# Good - direct
Redirect 301 /page https://newsite.com/new-page
Use a tool like curl -I to test:
curl -I https://oldsite.com/page
If you see more than one 3xx status in the chain, consolidate.
Mistake 7: Not setting the Location header correctly
This one shows up when developers build redirects in application code instead of using web server config. You return a 301 or 302 status but forget to set the Location header, or set it to a relative path that breaks when the request came through a proxy.
# Python Flask - missing Location
return '', 301 # Browser has no idea where to go
The browser receives the status code, sees no Location header, and either shows an error or does nothing. If you do set Location but use a relative path like /new-page, it works in local testing but breaks in production when your app sits behind a load balancer or reverse proxy that rewrites paths.
The fix: Always set an absolute URL in the Location header:
from flask import redirect
return redirect('https://example.com/new-page', code=301)
In PHP:
header('Location: https://example.com/new-page', true, 301);
exit;
Absolute URLs survive proxies, CDNs, and subpath installations. Relative URLs are fragile.
What to check first
When a redirect breaks or behaves unexpectedly, walk through this:
- Test with
curl -ILto see the exact status code and headers without browser caching interference - Check if it's a chain—multiple hops slow everything and confuse search engines
- Confirm the status code matches your intent: 301/308 for permanent, 302/307 for temporary
- For APIs, verify the HTTP method is preserved if that matters (use 307/308)
- Look for caching headers—if you used 301 by mistake, you can't un-cache it client-side, but you can add a second redirect
- Check the
Locationheader is absolute and points where you intended
Most redirect problems come down to picking 302 when you meant 301, or the reverse. The rest are caching surprises or missing headers. Fix those and you'll handle ninety percent of redirect issues without breaking SEO or user experience.
Common questions
Q: Can I change a 302 to a 301 after the fact without breaking anything?
Yes, but browsers that cached the 302 will pick up the 301 on their next visit. Search engines will re-crawl and update their index. The transition is smooth.
Q: How long does Google take to recognize a 301?
Usually within a few crawls—days to a couple of weeks for active pages. Low-traffic pages can take longer. You'll see the old URL drop from the index as the new one rises.
Q: Do I need both 301 and 308 if I'm redirecting a site?
For a typical content site (WordPress, static pages, blogs), 301 covers everything. Use 308 only if you run APIs or services where POST/PUT/DELETE requests must preserve their method.
Q: What if I have hundreds of old URLs?
Use rewrite maps or regex patterns in your web server config instead of individual redirect lines. In Nginx, map blocks are efficient. In Apache, RewriteMap with a text file works well.
Test before you commit
You can undo almost anything in web hosting except a bad 301 cached by ten thousand browsers. Test your redirects with 302 first, check them with curl, verify the destination, and only then switch to 301. That five-minute caution has saved me from multi-hour firefighting more times than I can count.
![7 Common 301 vs 302 vs 308 Redirect Mistakes [Solved]](/images/blog/7-common-301-vs-302-vs-308-redirect-mistakes-solved.jpg)