HTTP 301
The HTTP 301 status code, also known as Moved Permanently, is a standard response in the Hypertext Transfer Protocol (HTTP) indicating that the target resource has been assigned a new permanent URI, and any future references to the original resource ought to use one of the new URIs provided by the server.[1] Servers responding with 301 typically include a Location header field containing the preferred new URI for automatic redirection by user agents, such as web browsers, while the response payload often features a short hypertext note with a hyperlink to the new location.[1] This code was first defined in HTTP/1.0 under RFC 1945 and later refined in HTTP/1.1 specifications, including RFC 2616 and the current RFC 9110, to ensure consistent semantics across implementations.[1]
In practice, the 301 response prompts clients to update their references to the resource, making it particularly useful for permanent URL changes, such as during website migrations or content reorganization. User agents may automatically follow the redirect, but for historical reasons, they are permitted to change the request method from POST to GET in the subsequent request, omitting the message body—a behavior that can alter the semantics of the original request and is discouraged in favor of more precise codes like 307 (Temporary Redirect) or 308 (Permanent Redirect) when method preservation is critical.[1][2][3]
Additionally, 301 responses are cacheable by default under HTTP caching rules, allowing intermediaries like proxies to store and reuse the redirect unless overridden by explicit cache controls or method-specific restrictions, which enhances performance for repeated accesses to the original URI.[1] Unlike temporary redirect codes such as 302 (Found), the permanence implied by 301 signals to clients and crawlers that the change is not expected to revert, influencing long-term link management and resource discovery across the web.[4] This status code plays a foundational role in maintaining the stability and usability of web resources amid evolving site architectures.
Definition and Purpose
Status Code Meaning
The HTTP 301 status code, known as "Moved Permanently," indicates that the target resource has been assigned a new permanent URI, and any future references to the original resource ought to use one of the URIs provided by the server.[5] This status signals a lasting change in the resource's location, prompting clients with link-editing capabilities to automatically update references to the effective request URI with the new permanent URI where possible.[5]
The server must include a Location header field in the response, containing a preferred URI reference for the new permanent location, which the client may use for redirection.[5] The response payload, if present, typically consists of a short hypertext note with a hyperlink to the new URI to assist user agents without automatic redirection support.[5]
For GET and HEAD requests, which are safe and idempotent methods, the user agent may automatically redirect by issuing a GET request to the URI specified in the Location header without user interaction.[5] However, for non-GET/HEAD methods, automatic redirection is prohibited unless the method can be safely converted to GET, though changing POST to GET is allowed for historical reasons but not recommended as it may discard request body data.[5] In contrast to temporary redirects like HTTP 302, the 301 status implies persistence, encouraging clients to cache and reuse the new URI indefinitely.[5]
A typical 301 response might appear as follows:
HTTP/1.1 301 Moved Permanently
Location: [https](/page/HTTPS)://example.com/new-resource
HTTP/1.1 301 Moved Permanently
Location: [https](/page/HTTPS)://example.com/new-resource
This example demonstrates the minimal structure required for the redirect.[5]
Common Use Cases
HTTP 301 redirects are commonly employed when a web resource undergoes a permanent relocation, ensuring that clients and automated systems update their references to the new URI without losing access to the content.[5] One primary use case is site restructuring, where URLs are updated to reflect changes in site architecture, such as migrating from HTTP to HTTPS protocols to enhance security.[6] In this scenario, servers issue a 301 response with a Location header pointing to the HTTPS equivalent, allowing browsers to seamlessly follow the redirect and future requests to use the secure protocol.[7]
Domain migrations represent another frequent application, particularly when an organization rebrands or consolidates under a new domain name, like shifting from oldcompany.com to newcompany.com.[8] Here, the 301 status code signals that all resources on the old domain have permanently moved, prompting clients to update bookmarks and links accordingly while preserving continuity for users.[9] Content consolidation also leverages 301 redirects effectively, such as when merging multiple pages into a single canonical URL to streamline user experience and reduce duplication.[8] For instance, outdated versions of a document might redirect to an updated master page, ensuring that incoming traffic is funneled to the most relevant resource.
In API development, HTTP 301 is used to handle deprecated endpoints where a resource is retired and permanently relocated to a new path, informing clients to adopt the updated endpoint for ongoing interactions.[10] This approach maintains backward compatibility during transitions, with the Location header providing the precise new URI.[5] To combat link rot—the degradation of hyperlinks over time due to resource relocation—administrators implement 301 redirects to guide users from obsolete URLs to their current equivalents, thereby sustaining the web's interconnected integrity.[11] A practical example is product rebranding, where an e-commerce site redirects /old-product to /new-product following a name change, ensuring that external links and search referrals continue to deliver value without interruption.[12]
Technical Specifications
The HTTP 301 response utilizes a specific set of headers to convey redirection information to the client, with the Location header serving as the primary mechanism for indicating the new resource URI. According to RFC 7231, the server should include a Location header field containing a preferred URI reference for the permanent new location, formatted as a URI-reference that may be absolute or relative; relative URIs are resolved against the effective request URI per RFC 3986.[5][13][14]
While the Location header is recommended rather than strictly mandatory, its absence would render the redirect ineffective, as clients rely on it for automatic redirection. An optional Content-Location header may also be included to specify the URI of the representation in the response payload, particularly useful in scenarios involving content negotiation where the payload corresponds to a specific variant of the resource.[5][15]
The response body is not required but, if present, should typically contain a short hypertext note with a hyperlink to the new URI to inform non-automated clients of the relocation. This aligns with recommendations in HTTP/1.1, though compatibility extends to HTTP/1.0, where 301 responses follow similar header semantics without the enhanced URI-reference flexibility introduced in HTTP/1.1.[5][16]
If the Location header contains an invalid URI-reference, such as a malformed or unresolvable path, the client may fail to redirect, potentially resulting in a navigation error or fallback to manual handling by the user agent.[13]
A representative example of an HTTP/1.1 301 response with minimal headers is as follows:
HTTP/1.1 301 Moved Permanently
Location: https://example.com/new-resource
Content-Type: text/html
<html>
<head><title>Moved Permanently</title></head>
<body>
<p>The document has moved <a href="https://example.com/new-resource">here</a>.</p>
</body>
</html>
HTTP/1.1 301 Moved Permanently
Location: https://example.com/new-resource
Content-Type: text/html
<html>
<head><title>Moved Permanently</title></head>
<body>
<p>The document has moved <a href="https://example.com/new-resource">here</a>.</p>
</body>
</html>
This structure ensures interoperability across HTTP versions while providing essential redirection details.[5]
Client-Side Handling
When a client receives an HTTP 301 Moved Permanently response to a GET or HEAD request, it may automatically follow the redirection by issuing a new request to the URI specified in the Location header, using the same method.[5] This behavior allows user agents to seamlessly update references to the resource's new permanent location without user intervention.[5]
For requests using methods intended to modify resources, such as POST, PUT, or DELETE, the 301 response indicates that the effective request URI has changed permanently, and clients may automatically redirect by issuing a subsequent request to the new URI, though user agents are permitted to change the method to GET for historical reasons.[5] Historically, user agents have sometimes converted POST requests to GET upon redirection for compatibility reasons, though this is not required and can lead to loss of request body data.[5] To prevent such conversions, servers may use status code 308 Permanent Redirect instead for non-GET methods.[17]
Clients must implement mechanisms to detect and avoid infinite redirection loops, such as tracking the number of redirects or the set of URIs encountered in a chain, and intervening if a cycle is identified.[16] This prevents denial-of-service scenarios from misconfigured or malicious redirect chains.
The Location header value is a URI-reference, which may be relative; clients resolve relative references against the effective request URI of the original request, as defined in URI resolution rules.[13][14]
Security considerations in client handling include the risk of protocol downgrades, where a 301 redirect from an HTTPS origin leads to an HTTP target URI, potentially exposing data to interception; modern browsers mitigate this through HTTP Strict Transport Security (HSTS), which forces upgrades of HTTP requests to HTTPS for participating domains, even in redirected contexts.
In a typical client flow, a browser sends a GET request to an original URI, receives a 301 response with a Location header pointing to the new URI, extracts and resolves the Location value, then issues a new GET request to that URI, updating its internal reference for future accesses.[5]
Historical Development
Origin in HTTP/1.1
The HTTP 301 status code, known as "Moved Permanently," was formally defined in the HTTP/1.1 specification through RFC 2616, published by the Internet Engineering Task Force (IETF) in June 1999.[18] This document established it as a member of the 3xx family of redirection status codes, which signal that further action is needed to complete the request by redirecting the client to a new resource location.[19]
The original purpose of HTTP 301 was to notify clients that a resource had undergone a permanent relocation, enabling seamless updates to links and references without rendering existing hyperlinks obsolete.[20] This mechanism supported the dynamic evolution of the World Wide Web by allowing server operators to migrate content to new uniform resource identifiers (URIs) while preserving accessibility.[20] The specification required servers to include a Location header field containing the new URI, and for non-HEAD requests, an optional entity body with a hypertext note and hyperlink to the target.[20] A key excerpt from RFC 2616 states: "The requested resource has been assigned a new permanent URI and any future references to this resource SHOULD use one of the returned URIs."[20]
Although HTTP/1.0, as described in RFC 1945 (May 1996), had introduced a basic 301 code for permanent moves with similar semantics, it lacked the comprehensive guidelines on caching, client relinking, and non-GET/HEAD handling that HTTP/1.1 provided.[21] HTTP/1.1 refined these aspects to ensure more reliable interoperability across diverse clients and servers, addressing ambiguities in the earlier version's informal treatment of redirects.[20]
HTTP 301 became a standard practice with the widespread adoption of HTTP/1.1 in web browsers and servers during the late 1990s. These developments were driven by the rapid expansion of the web during this period, with the number of hosted websites growing from thousands to millions, necessitating tools for maintaining URL stability amid frequent content reorganizations and domain migrations.[22]
Updates in Subsequent RFCs
The HTTP/1.1 specification was modularized and updated in the RFC 7230 series (2014), which obsoleted RFC 2616; specifically, RFC 7231 defined the semantics of HTTP messages, including status codes like 301.[23]
In RFC 7231, Section 6.4.2, the 301 status code's semantics were clarified to indicate a permanent URI assignment for the target resource, with the server required to include a Location header field containing the new URI; user agents may automatically redirect using this field, and for historical reasons, they may change the request method from POST to GET in the subsequent request, though 307 or 308 should be used to prevent this.[5] The response is cacheable by default for safe and idempotent methods unless otherwise indicated, and an optional hypertext payload may describe the relocation, as in the example:
HTTP/1.1 301 Moved Permanently
Location: http://www.example.org/
Content-Type: text/html
Content-Length: 174
<html>
<head><title>Moved Permanently</title></head>
<body>
<p>The document has moved <a href="http://www.example.org/">here</a>.</p>
</body>
</html>
```[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.2)
This update relaxed prior ambiguities in RFC 2616 regarding method preservation, explicitly allowing the POST-to-GET change while emphasizing non-automatic redirection for unsafe methods to avoid unintended side effects.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.2)[](https://datatracker.ietf.org/doc/html/rfc2616#section-10.3.2)
Further refinements appeared in RFC 9110 (2022), which consolidated HTTP semantics across versions and obsoleted RFC 7231; Section 15.4.2 clarified that automatic redirection is permitted without confirmation only for safe and idempotent methods, while non-idempotent methods like [POST](/page/Post) require user confirmation; the historical POST-to-GET method change remains allowed, though 308 is recommended to preserve the method.[](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.2) It also clarified that while the Location header typically holds one [URI](/page/Uri), payloads may contain multiple URIs in hypertext form, and recipients must not assume a single URI without scanning the payload.[](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.2) Handling of authority changes in the Location [URI](/page/Uri) was implicitly supported, as 301 permits redirects to different hosts or schemes for permanent moves.[](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.2)
The 301 status code remains unchanged in [HTTP/2](/page/HTTP/2) (RFC 9113) and [HTTP/3](/page/HTTP/3) (RFC 9114), retaining the same semantics while adapting to protocol-specific framing, such as using pseudo-headers for [Location](/page/Location) in HTTP/2 streams. As of 2025, no major semantic shifts have occurred, maintaining stability under IETF standards.[](https://datatracker.ietf.org/doc/html/rfc9110)
## Comparisons with Other Redirects
### Differences from [HTTP 302](/page/HTTP_302)
The HTTP 301 status code signifies a permanent redirection, indicating that the target resource has been assigned a new permanent [URI](/page/Uri), and clients ought to use this new [URI](/page/Uri) for all future requests to the resource.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.2) In contrast, the HTTP 302 status code denotes a temporary redirection, where the target resource resides temporarily under a different [URI](/page/Uri), and clients should continue to use the original effective request [URI](/page/Uri) for subsequent requests, as the redirection may change over time.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.3) This distinction in permanence guides client behavior: with a 301, user agents with link-editing capabilities are expected to automatically update references to the new [URI](/page/Uri), effectively treating it as the [canonical](/page/Canonical) location, whereas a 302 preserves the original [URI](/page/Uri)'s role without implying any long-term relocation.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.2)[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.3)
Regarding client caching, a 301 response is cacheable by default, allowing user agents to store the redirection indefinitely unless overridden by explicit freshness information in headers like Cache-Control or Expires, which supports efficient handling of permanent changes without repeated server queries.[](https://datatracker.ietf.org/doc/html/rfc7234#section-3) Conversely, a 302 response is not cacheable by default and requires explicit directives, such as Cache-Control: public, to be stored; without them, clients typically do not cache the redirection or do so only briefly, ensuring that temporary redirects are re-evaluated on each request to reflect potential alterations.[](https://datatracker.ietf.org/doc/html/rfc7234#section-3) This caching disparity minimizes unnecessary traffic for permanent moves while preventing stale handling of transient ones.
In terms of SEO implications, search engines like [Google](/page/Google) treat a 301 as a strong signal that the target [URL](/page/URL) is the [canonical](/page/Canonical) version, passing full link equity from the original to the new [URL](/page/URL), which helps consolidate [ranking](/page/Ranking) signals during permanent migrations.[](https://developers.google.com/search/docs/crawling-indexing/301-redirects) A 302, however, serves as a weaker signal, with link equity not fully transferred—Google may retain the original [URL](/page/URL) in search results longer and index the target more tentatively—making it unsuitable for preserving SEO value in ongoing scenarios.[](https://developers.google.com/search/docs/crawling-indexing/301-redirects)
Both 301 and 302 responses include a Location header specifying the new [URI](/page/Uri) and permit user agents to automatically redirect the request, but they handle HTTP methods differently in practice. For non-GET or non-HEAD requests, such as [POST](/page/Post), both status codes allow the [method](/page/Method) to be transparently changed to GET for the redirected request, omitting the original request body to avoid unintended side effects; however, the 301's permanence implies that future interactions should consistently use the new URI with the appropriate method, whereas the 302's temporariness does not alter the expectation to revert to the original URI and method afterward.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4) For method preservation in temporary cases, the 307 status code is now preferred over 302.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.7)
The 302 code is typically employed for short-term scenarios, such as site maintenance, [A/B testing](/page/A/B_testing), or seasonal promotions where the original resource will soon return to its primary [URI](/page/Uri), avoiding unnecessary updates to bookmarks or links.[](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/302) In distinction, the 301 is reserved for structural, long-term changes like domain migrations or URL consolidations, signaling to clients and crawlers that the original resource is obsolete.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.2)
Both status codes were first defined in HTTP/1.0 (RFC 1945) and refined in HTTP/1.1 specifications, including RFC 2616, but the 302's historical reason phrase "Found" has been noted as misleading since it implies discovery rather than temporariness; modern implementations and documentation favor "Temporary Redirect" to clarify its semantics, aligning with updates in RFC 7231 and later specifications like RFC 9110.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.3)[](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.3)
### Differences from HTTP 303 and 307
The HTTP status codes [303 (See Other)](/page/HTTP_303) and 307 (Temporary Redirect) were introduced in RFC 2616 to provide unambiguous guidance for client behavior in redirection scenarios, particularly those involving [POST](/page/Post-) requests, building on the existing 301 (Moved Permanently) code from earlier HTTP/1.1 specifications.[](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) While 301 signals a permanent relocation of the resource where future requests should use the new [URI](/page/Uri), 303 and 307 address specific needs for temporary or method-specific handling without implying permanence.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.2)
A key distinction lies in method handling: 303 forces the client to convert the redirected request to a GET method, regardless of the original method (e.g., even for unsafe methods like POST), making it ideal for the "POST/Redirect/GET" (PRG) pattern to prevent accidental resubmission of forms.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.4) In contrast, 301 allows the original method to be preserved for safe requests but permits user agents to change unsafe methods (such as POST) to GET, though modern implementations often prompt the user for confirmation in such cases to avoid unintended side effects.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.2) For example, after a user submits a form via POST, a server might respond with 303 to redirect to a results page using GET, ensuring the action is not repeated on refresh, whereas 301 would be used if the entire endpoint has permanently moved, potentially retaining the method if deemed safe.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.4)
The 307 code, meanwhile, emphasizes temporary relocation while strictly requiring the client to preserve the original request method and body, without any conversion to GET, which contrasts with 301's permanent nature and optional method flexibility.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.7) Clients receiving 307 must not automatically redirect unsafe methods without user confirmation, ensuring [idempotence](/page/Idempotence) is maintained for the temporary shift.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.7) This makes 307 suitable for scenarios like load balancing where the resource is briefly unavailable at its primary [URI](/page/Uri) but must be accessed with the same semantics.
In client processing rules, 301 provides leeway for method changes in unsafe cases (potentially prompting the user), 307 mandates preservation of the method to avoid altering request semantics, and 303 always enforces GET to treat the redirect as a new retrieval.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.2) For permanent redirects requiring method preservation, the later-defined 308 (Permanent Redirect) is now preferred over 301 in modern [HTTP/2](/page/HTTP/2) and [HTTP/3](/page/HTTP/3) contexts, as it explicitly prohibits method changes.[](https://datatracker.ietf.org/doc/html/rfc7238)
## Implementation Approaches
### Server Configuration Examples
Configuring HTTP 301 redirects declaratively through server configuration files allows administrators to implement permanent redirects without modifying application code. This approach is commonly used on popular web servers like [Apache](/page/Apache), [Nginx](/page/Nginx), and IIS, where rules are defined using built-in modules for URL rewriting or redirection. These configurations ensure that requests to deprecated or moved resources are automatically forwarded to new locations with the appropriate status code.[](https://httpd.apache.org/docs/2.4/rewrite/remapping.html)[](https://nginx.org/en/docs/http/ngx_http_rewrite_module.html)[](https://learn.microsoft.com/en-us/iis/extensions/url-rewrite-module/url-rewrite-module-configuration-reference)
On Apache HTTP Server, the mod_rewrite module enables 301 redirects via .htaccess files or the main configuration. For instance, to redirect a specific page from /old to https://example.com/new, the following rule can be added to the .htaccess file in the relevant directory:
HTTP/1.1 301 Moved Permanently
Location: http://www.example.org/
Content-Type: text/html
Content-Length: 174
<html>
<head><title>Moved Permanently</title></head>
<body>
<p>The document has moved <a href="http://www.example.org/">here</a>.</p>
</body>
</html>
```[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.2)
This update relaxed prior ambiguities in RFC 2616 regarding method preservation, explicitly allowing the POST-to-GET change while emphasizing non-automatic redirection for unsafe methods to avoid unintended side effects.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.2)[](https://datatracker.ietf.org/doc/html/rfc2616#section-10.3.2)
Further refinements appeared in RFC 9110 (2022), which consolidated HTTP semantics across versions and obsoleted RFC 7231; Section 15.4.2 clarified that automatic redirection is permitted without confirmation only for safe and idempotent methods, while non-idempotent methods like [POST](/page/Post) require user confirmation; the historical POST-to-GET method change remains allowed, though 308 is recommended to preserve the method.[](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.2) It also clarified that while the Location header typically holds one [URI](/page/Uri), payloads may contain multiple URIs in hypertext form, and recipients must not assume a single URI without scanning the payload.[](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.2) Handling of authority changes in the Location [URI](/page/Uri) was implicitly supported, as 301 permits redirects to different hosts or schemes for permanent moves.[](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.2)
The 301 status code remains unchanged in [HTTP/2](/page/HTTP/2) (RFC 9113) and [HTTP/3](/page/HTTP/3) (RFC 9114), retaining the same semantics while adapting to protocol-specific framing, such as using pseudo-headers for [Location](/page/Location) in HTTP/2 streams. As of 2025, no major semantic shifts have occurred, maintaining stability under IETF standards.[](https://datatracker.ietf.org/doc/html/rfc9110)
## Comparisons with Other Redirects
### Differences from [HTTP 302](/page/HTTP_302)
The HTTP 301 status code signifies a permanent redirection, indicating that the target resource has been assigned a new permanent [URI](/page/Uri), and clients ought to use this new [URI](/page/Uri) for all future requests to the resource.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.2) In contrast, the HTTP 302 status code denotes a temporary redirection, where the target resource resides temporarily under a different [URI](/page/Uri), and clients should continue to use the original effective request [URI](/page/Uri) for subsequent requests, as the redirection may change over time.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.3) This distinction in permanence guides client behavior: with a 301, user agents with link-editing capabilities are expected to automatically update references to the new [URI](/page/Uri), effectively treating it as the [canonical](/page/Canonical) location, whereas a 302 preserves the original [URI](/page/Uri)'s role without implying any long-term relocation.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.2)[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.3)
Regarding client caching, a 301 response is cacheable by default, allowing user agents to store the redirection indefinitely unless overridden by explicit freshness information in headers like Cache-Control or Expires, which supports efficient handling of permanent changes without repeated server queries.[](https://datatracker.ietf.org/doc/html/rfc7234#section-3) Conversely, a 302 response is not cacheable by default and requires explicit directives, such as Cache-Control: public, to be stored; without them, clients typically do not cache the redirection or do so only briefly, ensuring that temporary redirects are re-evaluated on each request to reflect potential alterations.[](https://datatracker.ietf.org/doc/html/rfc7234#section-3) This caching disparity minimizes unnecessary traffic for permanent moves while preventing stale handling of transient ones.
In terms of SEO implications, search engines like [Google](/page/Google) treat a 301 as a strong signal that the target [URL](/page/URL) is the [canonical](/page/Canonical) version, passing full link equity from the original to the new [URL](/page/URL), which helps consolidate [ranking](/page/Ranking) signals during permanent migrations.[](https://developers.google.com/search/docs/crawling-indexing/301-redirects) A 302, however, serves as a weaker signal, with link equity not fully transferred—Google may retain the original [URL](/page/URL) in search results longer and index the target more tentatively—making it unsuitable for preserving SEO value in ongoing scenarios.[](https://developers.google.com/search/docs/crawling-indexing/301-redirects)
Both 301 and 302 responses include a Location header specifying the new [URI](/page/Uri) and permit user agents to automatically redirect the request, but they handle HTTP methods differently in practice. For non-GET or non-HEAD requests, such as [POST](/page/Post), both status codes allow the [method](/page/Method) to be transparently changed to GET for the redirected request, omitting the original request body to avoid unintended side effects; however, the 301's permanence implies that future interactions should consistently use the new URI with the appropriate method, whereas the 302's temporariness does not alter the expectation to revert to the original URI and method afterward.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4) For method preservation in temporary cases, the 307 status code is now preferred over 302.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.7)
The 302 code is typically employed for short-term scenarios, such as site maintenance, [A/B testing](/page/A/B_testing), or seasonal promotions where the original resource will soon return to its primary [URI](/page/Uri), avoiding unnecessary updates to bookmarks or links.[](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/302) In distinction, the 301 is reserved for structural, long-term changes like domain migrations or URL consolidations, signaling to clients and crawlers that the original resource is obsolete.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.2)
Both status codes were first defined in HTTP/1.0 (RFC 1945) and refined in HTTP/1.1 specifications, including RFC 2616, but the 302's historical reason phrase "Found" has been noted as misleading since it implies discovery rather than temporariness; modern implementations and documentation favor "Temporary Redirect" to clarify its semantics, aligning with updates in RFC 7231 and later specifications like RFC 9110.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.3)[](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.3)
### Differences from HTTP 303 and 307
The HTTP status codes [303 (See Other)](/page/HTTP_303) and 307 (Temporary Redirect) were introduced in RFC 2616 to provide unambiguous guidance for client behavior in redirection scenarios, particularly those involving [POST](/page/Post-) requests, building on the existing 301 (Moved Permanently) code from earlier HTTP/1.1 specifications.[](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) While 301 signals a permanent relocation of the resource where future requests should use the new [URI](/page/Uri), 303 and 307 address specific needs for temporary or method-specific handling without implying permanence.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.2)
A key distinction lies in method handling: 303 forces the client to convert the redirected request to a GET method, regardless of the original method (e.g., even for unsafe methods like POST), making it ideal for the "POST/Redirect/GET" (PRG) pattern to prevent accidental resubmission of forms.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.4) In contrast, 301 allows the original method to be preserved for safe requests but permits user agents to change unsafe methods (such as POST) to GET, though modern implementations often prompt the user for confirmation in such cases to avoid unintended side effects.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.2) For example, after a user submits a form via POST, a server might respond with 303 to redirect to a results page using GET, ensuring the action is not repeated on refresh, whereas 301 would be used if the entire endpoint has permanently moved, potentially retaining the method if deemed safe.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.4)
The 307 code, meanwhile, emphasizes temporary relocation while strictly requiring the client to preserve the original request method and body, without any conversion to GET, which contrasts with 301's permanent nature and optional method flexibility.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.7) Clients receiving 307 must not automatically redirect unsafe methods without user confirmation, ensuring [idempotence](/page/Idempotence) is maintained for the temporary shift.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.7) This makes 307 suitable for scenarios like load balancing where the resource is briefly unavailable at its primary [URI](/page/Uri) but must be accessed with the same semantics.
In client processing rules, 301 provides leeway for method changes in unsafe cases (potentially prompting the user), 307 mandates preservation of the method to avoid altering request semantics, and 303 always enforces GET to treat the redirect as a new retrieval.[](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.2) For permanent redirects requiring method preservation, the later-defined 308 (Permanent Redirect) is now preferred over 301 in modern [HTTP/2](/page/HTTP/2) and [HTTP/3](/page/HTTP/3) contexts, as it explicitly prohibits method changes.[](https://datatracker.ietf.org/doc/html/rfc7238)
## Implementation Approaches
### Server Configuration Examples
Configuring HTTP 301 redirects declaratively through server configuration files allows administrators to implement permanent redirects without modifying application code. This approach is commonly used on popular web servers like [Apache](/page/Apache), [Nginx](/page/Nginx), and IIS, where rules are defined using built-in modules for URL rewriting or redirection. These configurations ensure that requests to deprecated or moved resources are automatically forwarded to new locations with the appropriate status code.[](https://httpd.apache.org/docs/2.4/rewrite/remapping.html)[](https://nginx.org/en/docs/http/ngx_http_rewrite_module.html)[](https://learn.microsoft.com/en-us/iis/extensions/url-rewrite-module/url-rewrite-module-configuration-reference)
On Apache HTTP Server, the mod_rewrite module enables 301 redirects via .htaccess files or the main configuration. For instance, to redirect a specific page from /old to https://example.com/new, the following rule can be added to the .htaccess file in the relevant directory:
RewriteEngine On
RewriteRule ^old$ https://example.com/new [R=301,L]
The [R=301] flag specifies a permanent redirect, while [L] stops further rule processing. This setup works for both HTTP and HTTPS requests and can be placed in server-wide configurations like httpd.conf as well.[](https://httpd.apache.org/docs/2.4/rewrite/remapping.html)
For wildcard redirects handling entire directories, [Apache](/page/Apache) supports regular expressions to capture and preserve path segments. An example redirecting all content under /old/ to /new/ while maintaining subpaths is:
The [R=301] flag specifies a permanent redirect, while [L] stops further rule processing. This setup works for both HTTP and HTTPS requests and can be placed in server-wide configurations like httpd.conf as well.[](https://httpd.apache.org/docs/2.4/rewrite/remapping.html)
For wildcard redirects handling entire directories, [Apache](/page/Apache) supports regular expressions to capture and preserve path segments. An example redirecting all content under /old/ to /new/ while maintaining subpaths is:
RewriteEngine On
RewriteRule ^old/(.*)$ /new/$1 [R=301,L]
This captures any trailing path in the first group ($1) and appends it to the target, ensuring /old/subpage redirects to /new/subpage. Such patterns are efficient for site migrations or [restructuring](/page/Restructuring).[](https://httpd.apache.org/docs/2.4/rewrite/remapping.html)
In [Nginx](/page/Nginx), the [return](/page/Return) directive in a [server](/page/Server) or [location](/page/Location) block issues a 301 redirect directly. To redirect /old to [https](/page/HTTPS)://[example.com](/page/Example.com)/new, add the following within the server block:
This captures any trailing path in the first group ($1) and appends it to the target, ensuring /old/subpage redirects to /new/subpage. Such patterns are efficient for site migrations or [restructuring](/page/Restructuring).[](https://httpd.apache.org/docs/2.4/rewrite/remapping.html)
In [Nginx](/page/Nginx), the [return](/page/Return) directive in a [server](/page/Server) or [location](/page/Location) block issues a 301 redirect directly. To redirect /old to [https](/page/HTTPS)://[example.com](/page/Example.com)/new, add the following within the server block:
server {
...
location = /old {
return 301 https://example.com/new;
}
}
This halts request processing and sends the redirect response immediately. For more complex scenarios, the [rewrite](/page/The_Rewrite) directive with the permanent flag can be used, equivalent to [return](/page/Return) 301.[](https://nginx.org/en/docs/http/ngx_http_rewrite_module.html)
Nginx also handles wildcard directory redirects using location blocks with regex or exact matches. For example, to redirect all requests under /old/ to /new/:
This halts request processing and sends the redirect response immediately. For more complex scenarios, the [rewrite](/page/The_Rewrite) directive with the permanent flag can be used, equivalent to [return](/page/Return) 301.[](https://nginx.org/en/docs/http/ngx_http_rewrite_module.html)
Nginx also handles wildcard directory redirects using location blocks with regex or exact matches. For example, to redirect all requests under /old/ to /new/:
location /old/ {
rewrite ^/old/(.*)$ /new/$1 permanent;
}
This captures any trailing path in the first group ($1) and appends it to the target, ensuring /old/subpage redirects to /new/subpage while preserving query strings. Such patterns are suitable for bulk redirects during domain changes.[](https://nginx.org/en/docs/http/ngx_http_rewrite_module.html)
For [Microsoft](/page/Microsoft) IIS, the URL Rewrite [Module](/page/Module) (version 2.0 or later) configures 301 redirects through web.config files using XML [rules](/page/Rule). A basic [rule](/page/Rule) to redirect /old to https://example.com/new involves adding the following under <system.webServer><rewrite><rules>:
This captures any trailing path in the first group ($1) and appends it to the target, ensuring /old/subpage redirects to /new/subpage while preserving query strings. Such patterns are suitable for bulk redirects during domain changes.[](https://nginx.org/en/docs/http/ngx_http_rewrite_module.html)
For [Microsoft](/page/Microsoft) IIS, the URL Rewrite [Module](/page/Module) (version 2.0 or later) configures 301 redirects through web.config files using XML [rules](/page/Rule). A basic [rule](/page/Rule) to redirect /old to https://example.com/new involves adding the following under <system.webServer><rewrite><rules>:
```
The redirectType="Permanent" sets the 301 status, and stopProcessing="true" prevents further rules from applying. This module integrates with IIS Manager for GUI-based rule creation as well.[24]
As a fallback for static sites without server-side scripting, an HTML meta refresh tag can simulate a redirect in the of the old page:
<meta http-equiv="Refresh" content="0; [URL](/page/URL)=https://example.com/new">
<meta http-equiv="Refresh" content="0; [URL](/page/URL)=https://example.com/new">
However, this is not a true HTTP 301 redirect; it is a client-side mechanism that instructs the browser to load the new URL after a delay (0 seconds for immediate effect), lacks a server-issued status code, and may not be followed reliably by search engines or non-HTML resources. It executes only after the page loads, potentially harming user experience and SEO compared to server-side 301s.[25]
To verify a 301 redirect configuration, use the curl command-line tool to inspect response headers. For example, run:
curl -I [https](/page/HTTPS)://example.com/old
curl -I [https](/page/HTTPS)://example.com/old
This fetches only the headers (-I flag), displaying output like "HTTP/1.1 301 Moved Permanently" and the "Location: https://example.com/new" header, confirming the redirect status and target URL. Adding -L follows the redirect for end-to-end testing, but -I alone suffices for status validation.[26]
Code-Based Implementations
Code-based implementations of HTTP 301 redirects involve programmatically setting the response status code to 301 (Moved Permanently) and the Location header within application logic, typically in server-side scripts or frameworks. This approach is useful for dynamic redirects based on conditions like user authentication or database queries, contrasting with static server configurations such as .htaccess rules. These methods require careful handling to comply with HTTP standards, ensuring the redirect is issued before any response body is output.
In PHP, the header() function sends raw HTTP headers, allowing a 301 redirect by specifying the status and Location. The following example redirects to a new URL and terminates execution to prevent further output:
php
<?php
header('HTTP/1.1 301 Moved Permanently');
header('Location: /new-url');
exit;
?>
<?php
header('HTTP/1.1 301 Moved Permanently');
header('Location: /new-url');
exit;
?>
This code sets the status code explicitly and provides the target URL in the Location header, as defined in HTTP/1.1 specifications. [27] [28]
In Python using the Flask web framework, the redirect() function from flask module handles the response object, supporting a code parameter for 301. An example route implementation is:
python
from flask import Flask, redirect
app = Flask(__name__)
@app.route('/old-url')
def old_route():
return redirect('/new-url', code=301)
from flask import Flask, redirect
app = Flask(__name__)
@app.route('/old-url')
def old_route():
return redirect('/new-url', code=301)
Flask's redirect generates the appropriate headers, with 301 indicating a permanent move. [29]
For Node.js with Express.js, the res.redirect() method on the response object simplifies issuing a 301 by passing the status code and path. A basic route example:
javascript
const express = require('express');
const app = express();
app.get('/old-url', (req, res) => {
res.redirect(301, '/new-url');
});
const express = require('express');
const app = express();
app.get('/old-url', (req, res) => {
res.redirect(301, '/new-url');
});
This method internally sets the status and Location headers, following Express's response API conventions. [30]
In Java servlets, the HttpServletResponse interface provides setStatus() and setHeader() methods to configure the 301 response. An example in a doGet() method:
java
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setStatus(301);
response.setHeader("Location", "/new-url");
}
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setStatus(301);
response.setHeader("Location", "/new-url");
}
These methods must be called before any output stream is written, per the Servlet API. [31]
A critical aspect of these implementations is error handling to avoid header emission issues; no content, including whitespace or errors, should be output before setting headers, as HTTP requires headers to precede the body. Failure to do so results in errors like "Headers already sent" in PHP or equivalent in other languages. [27]
In the context of JSON APIs, issuing a 301 for deprecated endpoints signals clients to update to the new permanent location, often combined with a body containing migration details if the API allows non-empty responses for redirects. This practice aids in graceful deprecation without breaking changes. [10]
SEO and Search Implications
Effects on Search Rankings
HTTP 301 redirects play a significant role in search engine optimization by facilitating the transfer of link equity from an old URL to a new one, ensuring that the ranking signals associated with the original page are largely preserved. According to Google's official documentation, 301 redirects do not result in any loss of PageRank, allowing the new URL to inherit the full link authority of the redirected page.[7] This mechanism helps maintain search visibility during site migrations or URL changes, preventing a drop in rankings that could otherwise occur if the redirect were not implemented.[32]
In terms of canonicalization, a 301 redirect serves as a strong signal to search engines that the old URL is permanently replaced, helping to consolidate duplicate or near-duplicate content under a single preferred version. This prevents dilution of ranking signals across multiple URLs and avoids penalties for perceived content duplication. Google's guidelines recommend using 301 redirects alongside or in place of canonical tags for handling cross-domain or structural duplicates, as they provide a definitive instruction to prioritize the target URL in indexing and ranking decisions.[33]
Following implementation, search engines like Google update their indexes by re-crawling the redirected URL, gradually replacing the old page with the new one in search results while deprecating the original. This process ensures that users and crawlers are directed to the current content, with the old URL eventually removed from the index to reflect the permanent move. The transition typically occurs over several weeks, depending on crawl frequency and site authority.[8][34]
Best practices for using 301 redirects emphasize their application exclusively for permanent URL changes to preserve rankings and avoid temporary disruptions. Implementing 301s for ongoing or reversible modifications can lead to ranking instability, as search engines may not fully credit the target if the redirect is later removed. Site owners should map redirects one-to-one, avoiding loops or mismatches, to maximize equity transfer and user experience.[35][36]
Tools such as Google Search Console provide metrics to track 301 redirect performance, including impressions, clicks, and index coverage changes for affected URLs. By monitoring the Index Coverage report and using the URL Inspection tool, users can verify that the new URL gains traffic and rankings equivalent to the old one, identifying any anomalies like delayed indexing. This data helps quantify the redirect's success in maintaining SEO value post-implementation.[8]
A key pitfall involves chained 301 redirects, where multiple sequential redirects occur before reaching the final URL, which can dilute link equity and slow crawling efficiency even if individual redirects pass full authority. Each hop introduces potential signal loss or processing delays, reducing the overall ranking boost for the destination page. To mitigate this, redirects should be direct and streamlined, with chains limited to one or two steps at most for optimal SEO outcomes.[37][38]
Search Engine Crawling Behavior
Search engine bots, such as Googlebot, detect HTTP 301 redirects by following the server response during crawling, treating them as a strong signal to update their index with the target URL as the canonical version.[8] Upon encountering a 301, Googlebot automatically redirects to the new URL and applies crawling rules, including respecting any robots.txt directives specified for the target location rather than the original URL.[39]
Major search engines like Bing handle 301 redirects by following them to the target and indexing the destination as the permanent location for permanent moves, which influences crawl budget allocation by deprioritizing the original URL over time.[40]
After processing a 301 redirect, search engine bots generally reduce the crawl frequency of the original URL, as the permanent status signals a low priority for revisits, allowing resources to focus on the new target.[8] This shift helps optimize overall crawl efficiency but may take weeks to months for full propagation depending on the site's crawl rate. As of 2025, there have been no significant changes to this behavior in major search engines.
To accelerate reindexing following a 301 implementation, site owners should update XML sitemaps to include only the new target URLs and submit them via webmaster tools, prompting bots to discover and prioritize the redirected content more quickly.
Verification of 301 redirect propagation can be performed using tools like Google Search Console's URL Inspection feature, which simulates Googlebot's crawl to confirm the redirect is followed and the target is indexed correctly, or Bing Webmaster Tools' URL submission to check status.
In edge cases involving international redirects, such as changes between country-code top-level domains (ccTLDs), search engines treat 301 redirects as permanent moves, transferring ranking signals to the new domain while maintaining hreflang annotations for proper geographic targeting.[33]
Browser Caching Rules
Web browsers implement caching for HTTP 301 responses to optimize performance by reusing permanent redirects without repeated server requests.[41] In the absence of explicit caching directives, browsers apply heuristic caching to 301 responses, storing them indefinitely or until cache space constraints force eviction.[42] This heuristic approach assumes the permanence indicated by the 301 status code, allowing browsers to treat the redirect as valid for future requests to the same URI.[41]
If the 301 response includes Cache-Control or Expires headers, browsers respect these for determining expiration. For instance, a Cache-Control: max-age directive specifies the maximum age in seconds before the cached redirect becomes stale, while Expires provides an absolute date and time.[41] Upon staleness, browsers may revalidate the response with the server using conditional requests, but for 301 redirects without such headers, the cache entry persists without automatic expiration.[42]
HTTP 301 responses are stored in the browser's HTTP cache, typically a combination of memory and disk storage, alongside other cacheable resources like images or scripts.[41] This storage enables quick resolution of subsequent requests to the original URI by directly applying the cached Location header.[42]
From a privacy perspective, cached 301 redirects are retained across browsing sessions within the same browser profile but are not shared across different profiles or incognito modes.[42] They can be cleared manually through the browser's cache management tools or automatically upon cache flush events, such as storage limits being reached.[41]
Major browsers like Google Chrome and Mozilla Firefox adhere to the heuristics outlined in RFC 7234 (now updated in RFC 9111) for persistent caching of 301 redirects, ensuring long-term storage unless overridden by explicit directives.[41] This implementation promotes efficiency but can lead to issues with stale redirects if the target resource is relocated again, requiring users to manually clear the cache to fetch updated behavior.[42]
Proxy and CDN Interactions
HTTP proxies and content delivery networks (CDNs) handle HTTP 301 (Moved Permanently) responses by caching them to optimize performance, following the guidelines in RFC 7234, which designates 301 responses as cacheable by default unless overridden by headers like Cache-Control: no-store.[43] This caching allows intermediaries to store and serve the redirect without querying the origin server repeatedly, provided the response includes freshness information via Cache-Control or Expires headers.[44]
In proxy configurations, caching behavior for 301 responses varies by implementation. Varnish Cache treats 301 redirects as standard HTTP responses and caches them by default if they match the VCL logic, enabling efficient serving of redirects without backend involvement.[45] HAProxy, primarily a load balancer, does not natively cache responses like full proxies but can forward and issue 301 redirects; advanced setups may integrate caching modules to store upstream 301s, though this requires explicit configuration.[46]
CDNs extend this caching to edge locations for global distribution. Cloudflare caches 301 responses from origins based on Cache-Control headers, with a default edge TTL of 120 minutes for such status codes unless overridden by page rules or custom TTLs, after which it forwards requests to the origin if stale.[47] Similarly, AWS CloudFront caches 3xx responses, including 301s, respecting origin freshness directives; it serves cached redirects directly to viewers, only querying the origin for validation on expiration.[48]
Reverse proxies like Nginx and Apache can both issue 301 redirects and cache upstream ones to reduce latency. Nginx supports caching 301s via the proxy_cache module, where directives like proxy_cache_valid set the storage duration, allowing the proxy to serve redirects from its cache.[49] Apache, using mod_proxy and mod_cache, caches eligible 301 responses in memory or disk, configurable through CacheEnable and related directives for shared proxy environments.[50]
Response headers significantly influence shared caching of 301s across proxies and CDNs. The Cache-Control: public directive explicitly permits storage in shared caches, enabling intermediaries like CDNs to distribute the redirect broadly without private restrictions.[51]
Caching 301 redirects at the proxy or CDN level yields performance gains by minimizing origin server hits for repeated requests, as edge nodes handle the redirect locally, reducing latency and load—particularly beneficial for high-traffic permanent migrations.[52]
A common pitfall arises from misconfigurations, such as conflicting redirect rules in CDNs, which can trigger infinite loops where a 301 points back to itself, leading to errors like ERR_TOO_MANY_REDIRECTS and requiring cache purges or rule adjustments to resolve.[53]