HTTP 301 Redirect: When and How to Use It
Beginner
The HTTP 301 permanent redirect is one of the most important status codes for SEO and web architecture. When a server returns a 301 response, it tells the client that the requested resource has moved permanently to a new URL. Browsers cache this redirect, and search engines update their indexes to reflect the new location. Understanding when and how to use 301 redirects correctly prevents SEO damage during site migrations, protocol upgrades, and URL restructuring.
Unlike temporary redirects (302 and 307), a 301 explicitly signals permanence. This distinction matters enormously for CDN caching behavior, search engine crawling, and long-term URL management. A misused 302 where a 301 belongs can prevent search engines from transferring link equity and leave outdated URLs in search results for months.
What Is HTTP 301 and How Does It Work?
When a client sends an HTTP request and the server responds with status code 301, the response includes a Location header containing the new URL. The client — whether a browser, search engine crawler, or CDN edge server — automatically follows the redirect to the new location. The 301 status code was defined in HTTP/1.0 (RFC 1945, 1996) and retained in HTTP/1.1 (RFC 7231, 2014) with the same semantics.
A typical 301 response looks like this:
HTTP/1.1 301 Moved Permanently
Location: https://www.example.com/new-page
Cache-Control: public, max-age=86400
Content-Length: 0
The Location header is mandatory — without it, the client cannot know where to redirect. The response body is typically empty or contains a short HTML page with a link to the new URL for clients that do not follow redirects automatically.
When Should You Use a 301 Redirect?
The 301 redirect is the correct choice in several critical scenarios. Each represents a permanent change where the original URL should never serve content again.
| Metric | Edge Processing | Origin Processing | Improvement |
|---|---|---|---|
| Latency (p50) | 8–15 ms | 120–300 ms | 15–20x faster |
| Cache Hit Ratio | 85–95% | N/A | Reduces origin load |
| TLS Handshake | 1–5 ms (nearby PoP) | 50–150 ms | 10–30x faster |
| Bandwidth Cost | $0.01–0.04/GB | $0.05–0.12/GB | 3–5x cheaper |
| Availability | 99.99% (multi-PoP) | 99.9% (single DC) | 10x fewer outages |
Domain migration is the most common use case. When moving from oldsite.com to newsite.com, every URL on the old domain should 301 to its equivalent on the new domain. This preserves search rankings, bookmarks, and external links. Google recommends maintaining 301 redirects for at least one year after migration, though keeping them indefinitely costs virtually nothing.
HTTP to HTTPS migration requires 301 redirects from every http:// URL to its https:// equivalent. This is now standard practice — Google has used HTTPS as a ranking signal since 2014, and modern browsers mark HTTP pages as "Not Secure." The redirect should happen at the server level, not through meta refresh or JavaScript.
URL restructuring occurs when a site changes its URL pattern. For example, changing from /blog/2024/01/post-title to /articles/post-title requires 301 redirects from every old URL to the new pattern. Without redirects, external links become dead ends, and search engines lose the ranking signals associated with those URLs.
Trailing slash normalization ensures consistency. If your site uses /page/ (with trailing slash), then /page should 301 to /page/, or vice versa. Inconsistency confuses search engines, which may treat the two URLs as separate pages and split ranking signals between them.
How Do 301, 302, 307, and 308 Redirects Compare?
The HTTP specification defines four redirect status codes, each with distinct semantics that affect browser behavior, CDN caching, and search engine indexing.
| Code | Name | Permanent? | Method Preserved? | CDN Cacheable? | SEO Equity? |
|---|---|---|---|---|---|
| 301 | Moved Permanently | Yes | May change POST→GET | Yes (default) | Yes (~95-99%) |
| 302 | Found | No | May change POST→GET | No (default) | No |
| 307 | Temporary Redirect | No | Yes (strict) | No (default) | No |
| 308 | Permanent Redirect | Yes | Yes (strict) | Yes (default) | Yes |
The critical difference between 301 and 308 is method preservation. A 301 allows browsers to change a POST request to GET when following the redirect — a behavior inherited from early browser implementations that technically violated the HTTP specification. The 308 code, introduced in RFC 7538 (2015), guarantees that the request method remains unchanged. For HTML pages and GET requests, 301 and 308 are functionally identical. For API endpoints that receive POST requests, 308 is the safer choice.
How Should You Implement 301 Redirects in Nginx?
Nginx provides several ways to implement 301 redirects, each suited to different scenarios.
Server-level redirect for domain migration or HTTP→HTTPS:
server {
listen 80;
server_name oldsite.com www.oldsite.com;
return 301 https://newsite.com$request_uri;
}
The return directive is the most efficient method — Nginx processes it immediately without evaluating location blocks or rewrite rules. Always prefer return over rewrite when the redirect pattern is simple.
Pattern-based redirect for URL restructuring:
location ~ ^/blog/(\d{4})/(\d{2})/(.+)$ {
return 301 /articles/$3;
}
Redirect map for managing hundreds of individual redirects:
map $request_uri $redirect_target {
/old-page-1 /new-page-1;
/old-page-2 /new-page-2;
/old-page-3 /new-page-3;
}
server {
if ($redirect_target) {
return 301 $redirect_target;
}
}
How Do You Implement 301 Redirects in Apache?
Apache offers two primary methods for 301 redirects: .htaccess files and virtual host configuration. While .htaccess is convenient, it carries a performance cost because Apache must check for and parse .htaccess files in every directory for every request. For high-traffic sites, configure redirects in the virtual host file and set AllowOverride None.
# .htaccess method
Redirect 301 /old-page https://example.com/new-page
# RewriteRule for pattern-based redirects
RewriteEngine On
RewriteRule ^blog/(.*)$ /articles/$1 [R=301,L]
# HTTP to HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
How Do CDNs Cache and Handle 301 Redirects?
CDNs cache 301 responses by default because RFC 7231 classifies them as cacheable. This behavior has important implications for cache management and redirect updates.
When a CDN edge server receives a 301 from the origin, it stores the redirect response in its cache. Subsequent requests for the same URL are served the cached 301 directly from the edge, without contacting the origin. This reduces origin load and improves redirect speed — a cached 301 at a nearby edge PoP adds only 1-5ms of latency, compared to 50-200ms for a round trip to the origin.
The cache TTL for 301 responses depends on the Cache-Control header. Without explicit cache headers, CDNs apply their default TTL, which varies by provider. Cloudflare defaults to a 2-hour TTL for 301s without cache headers. Fastly follows the s-maxage or max-age directives strictly. Always set explicit cache headers on 301 responses to control CDN behavior.
When you need to change a redirect destination, you must invalidate the CDN cache for the redirect URL. Otherwise, edge servers continue serving the old redirect until the TTL expires. This is a common source of confusion during site migrations — the origin redirect is updated, but users still reach the old destination because they are hitting cached 301s at CDN edge servers.
What Are Common 301 Redirect Mistakes to Avoid?
Redirect chains are the most frequent problem. A chain occurs when URL A redirects to URL B, which redirects to URL C. Each hop adds 50-100ms of latency and leaks a small amount of link equity. Google follows up to 10 redirect hops but recommends keeping chains to a single hop. Audit your redirects regularly to eliminate chains — redirect directly from the original URL to the final destination.
Redirect loops occur when URL A redirects to URL B, which redirects back to URL A. This creates an infinite loop that browsers eventually break with a "too many redirects" error. Common causes include conflicting redirect rules in Nginx and .htaccess, or CDN redirect rules that conflict with origin redirects. Always test redirects with curl -IL to trace the full redirect chain.
Losing query parameters happens when the redirect strips the query string. In Nginx, the return 301 directive preserves query strings by default when using $request_uri. In Apache, the [QSA] (Query String Append) flag preserves query parameters with RewriteRule. Without it, /search?q=term redirecting to /new-search loses the ?q=term parameter.
Not redirecting all URL variations means forgetting about HTTP vs HTTPS, www vs non-www, trailing slash vs no trailing slash, and uppercase vs lowercase. Each variation is a separate URL for search engines. A comprehensive redirect strategy covers all combinations.
How Do You Test and Monitor 301 Redirects?
Testing redirects before and after deployment prevents broken user experiences and SEO damage.
Command-line testing with curl is the most reliable method:
# Follow redirects and show each hop
curl -ILs https://example.com/old-page
# Show redirect chain with timing
curl -w "redirect_url: %{redirect_url}\ntime: %{time_total}s\n" -o /dev/null -sI https://example.com/old-page
Bulk redirect testing uses a CSV file of old→new URL mappings and a script to verify each one. This is essential during large migrations with hundreds or thousands of redirects.
After deployment, monitor redirects through server access logs to identify unexpected 301 responses, redirect chains, or high-volume redirects that indicate indexing issues. Google Search Console reports redirect-related crawl issues in the Coverage report.
For CDN environments, verify that the CDN is caching 301 responses as expected by checking the X-Cache or Cf-Cache-Status response header. A redirect that always shows MISS indicates a caching configuration problem that sends every redirect request back to the origin.