301 Moved Permanently
Redirect
The requested resource has been assigned a new permanent URI and any future references should use the URI in the Location header. Search engines transfer ranking signals from the old URL to the new one, and browsers cache the redirect aggressively. Once a browser has seen a 301 for a URL, it may bypass the network entirely on subsequent visits. The HTTP spec historically allowed clients to change the method from POST to GET when following a 301, which is why 308 exists for cases where method preservation matters.
When does this happen?
Use 301 when a URL has permanently changed and you want crawlers, browsers, and bookmarks to switch to the new address. Domain migrations, HTTPS upgrades, www-canonicalization, trailing-slash normalization, and path restructuring after a CMS migration are all canonical 301 use cases. The response must include a Location header pointing at the new URL. Browsers cache 301s by default. Chrome and Firefox both honor 301s as cacheable indefinitely unless the response includes a Cache-Control header that says otherwise. This caching is the single biggest reason to be careful with 301: shipping the wrong destination and then fixing it does not undo the redirect in users' browsers. For SEO, Gary Illyes stated on Twitter in 2016 that 30x redirects no longer lose PageRank; Google Search Central docs describe 3xx redirects as consolidating ranking signals on the destination URL, but the absence of any decay has not been formally restated in Search Central documentation. Watch for chains of 301s. Each hop adds latency and crawlers eventually give up after roughly five hops. Older clients may rewrite POST as GET when following a 301, which is why API clients should prefer 308.
Common causes
- Domain migration from old-domain.com to new-domain.com after a rebrand or acquisition.
- Forcing HTTPS by 301-redirecting every HTTP URL to its HTTPS counterpart at the edge or load balancer.
- Canonicalizing the www subdomain. Either redirecting www.example.com to example.com or vice versa.
- Trailing-slash normalization to avoid duplicate-content penalties from /about and /about/ both being live.
- CMS migration where the URL structure changed from /node/123 to /blog/article-slug.
- Consolidating duplicate URLs created by tracking parameters or session IDs into a clean canonical.
- Removing a content section and redirecting its URLs to the most relevant remaining page rather than serving 404.
- Localized URL changes. For example shifting /products to /shop after a navigation redesign.
How to fix it
- Update every internal link to point at the final destination directly. Leaving 301s in your own navigation wastes crawl budget and adds round-trips.
- Audit the redirect chain to make sure you do not have 301 -> 301 -> 301 -> 200. Collapse them so every redirect lands on a 200 in one hop.
- Confirm the destination URL returns 200 and the same resource, not 404 or another redirect. Broken redirect targets are worse than no redirect.
- Set an explicit Cache-Control header on the 301 if you might need to undo it later. Without one, browsers may cache the redirect forever.
- Submit the new URLs in your XML sitemap and let Search Console process the moves so Google updates its index faster.
- For domain migrations, set the new domain as canonical in Search Console and keep the 301s in place for at least a year to let backlinks propagate.
- Avoid 301-redirecting based on dynamic conditions like cookies or query strings. The redirect must be deterministic per URL or it confuses crawlers.
- If a 301 was shipped to the wrong URL, fix the destination immediately and document that affected users may have the wrong URL cached in their browsers for months.
Real-world examples
- Site migrates from HTTP to HTTPS and the load balancer rewrites every http://example.com URL to https://example.com.
- Browser receives 301 with Location: https://example.com/path and immediately requests the HTTPS URL. Subsequent visits skip the HTTP request entirely because the redirect is cached.
- Old blog at example.com/blog/2019/why-redirects moves to example.com/articles/why-redirects after a CMS migration.
- Server returns 301 with Location: /articles/why-redirects. Crawlers update the index over the following weeks and link equity flows to the new URL.
- User visits the bare apex domain example.com and the site canonicalizes to www.example.com.
- Server returns 301 with Location: https://www.example.com/. Browser follows and caches the redirect so future visits go straight to www.
- Trailing-slash normalization: /about redirects to /about/.
- Server returns 301 with Location: /about/. The original URL is removed from search results within a crawl cycle and bookmarks update silently.
- Legacy product URLs like /p?id=123 are redirected to /products/blue-widget.
- Server returns 301 with the clean URL in Location. Search engines drop the parameterized URL from the index in favor of the canonical.
- API client issues POST /v1/old-endpoint with a JSON body to a deprecated endpoint.
- Server returns 301 with Location: /v2/new-endpoint. Older HTTP clients may follow the redirect with GET, dropping the body. This is why APIs should prefer 308 for permanent moves.
Debugging
- Run curl -I https://example.com/old-path and read the Status-Line and Location header to confirm the redirect target.
- Run curl -IL https://example.com/old-path to follow the chain and see every hop until you reach 200. Long chains are a red flag.
- Inspect Cache-Control on the 301 response. If it is absent, the browser may cache the redirect indefinitely.
- In DevTools Network tab, enable Preserve Log and watch the chain of requests; each redirect shows up as a separate row with status 301 and the next URL.
- Use curl -I -H 'Cache-Control: no-cache' to bypass intermediary caches and confirm the redirect is still coming from origin.
How it differs from related codes
HTTP 302
302 signals a temporary move. Browsers and search engines keep the original URL canonical. 301 transfers ranking signals and tells everyone the new URL is permanent.
HTTP 307
307 is a temporary redirect that strictly preserves the HTTP method and body. 301 is permanent and historically allowed clients to rewrite POST to GET, which can corrupt API behavior.
HTTP 308
308 is the strict-method version of 301. Same permanence semantics but the client is required to keep the original method and body. Use 308 for permanent API moves; use 301 for HTML page moves.
Related status codes
See HTTP 301 in your redirect chains?