301
Moved Permanently
3xx Redirection
What Does HTTP 301 Moved Permanently Mean?
HTTP 301 tells the client that the requested resource has been permanently moved to a new URL. The server includes the new URL in the Location response header. Browsers automatically follow the redirect, and search engines update their index to use the new URL.
This is the most important redirect code for SEO. It signals that all link equity, bookmarks, and references should be transferred to the new URL. Browsers cache 301 redirects aggressively, which means once a user encounters a 301, future requests go directly to the new URL without hitting the old one again.
Common Causes
- Domain migration: Moving from
oldsite.comtonewsite.com. Every page on the old domain should 301 redirect to its counterpart on the new domain. - HTTP to HTTPS migration: Upgrading to HTTPS requires 301 redirecting all HTTP URLs to their HTTPS equivalents to preserve SEO and ensure security.
- URL structure changes: Changing from
/blog/2024/my-postto/articles/my-postrequires 301 redirects so old links and bookmarks still work. - www to non-www (or vice versa): Canonicalizing your domain to use either
www.example.comorexample.comconsistently uses 301 redirects. - Trailing slash normalization: Deciding whether URLs end with
/or not and redirecting the non-canonical form to the canonical one.
How to Set Up 301 Redirects
Apache (.htaccess)
# Single page redirect
Redirect 301 /old-page.html https://example.com/new-page.html
# Redirect entire domain (HTTP to HTTPS)
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Redirect www to non-www
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
Nginx
# Single page redirect
location = /old-page.html {
return 301 https://example.com/new-page.html;
}
# HTTP to HTTPS
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
# www to non-www
server {
listen 443 ssl;
server_name www.example.com;
return 301 https://example.com$request_uri;
}
Express.js (Node.js)
// Single route redirect
app.get('/old-page', (req, res) => {
res.redirect(301, '/new-page');
});
// Force HTTPS middleware
app.use((req, res, next) => {
if (req.header('x-forwarded-proto') !== 'https') {
return res.redirect(301, `https://${req.header('host')}${req.url}`);
}
next();
});
Verifying a 301 with curl
$ curl -I http://example.com/old-page
HTTP/1.1 301 Moved Permanently
Location: https://example.com/new-page
Content-Length: 0
$ curl -L -I http://example.com/old-page # Follow redirects
HTTP/1.1 301 Moved Permanently
Location: https://example.com/new-page
HTTP/1.1 200 OK
Content-Type: text/html
Common Mistakes to Avoid
- Redirect chains: A redirects to B which redirects to C. Each hop adds latency and may lose SEO value. Always redirect directly to the final destination.
- Redirect loops: A redirects to B, B redirects back to A. Browsers will stop after a few hops and show an error. Test all redirects thoroughly.
- Using 301 for temporary moves: If the URL will change back (seasonal pages, A/B tests), use 302 instead. 301 tells search engines and browsers the move is final.
- Not preserving query parameters: When redirecting, make sure to pass along query strings if they are relevant to the new URL.
- Forgetting to update internal links: Even with 301s in place, update links within your site to point directly to the new URLs. Redirects add a round trip of latency.
Frequently Asked Questions
What is the difference between 301 and 302 redirects?
A 301 is permanent — search engines transfer link equity to the new URL and drop the old URL from their index. A 302 is temporary — search engines keep the old URL indexed. Use 301 for domain changes, URL restructuring, or HTTPS migration. Use 302 for A/B tests, maintenance pages, or geo-based redirects.
How does a 301 redirect affect SEO?
A 301 passes approximately 90-99% of link equity to the destination URL. Google has confirmed that 301 redirects consolidate ranking signals. It is the recommended method for preserving search rankings during URL changes, domain migrations, and protocol upgrades (HTTP to HTTPS).
How do I fix a 301 redirect loop?
First, trace the full redirect chain with
curl -L -I <url> to see where it loops. Common causes: conflicting rules in .htaccess (both www and non-www rules active), CDN redirect settings fighting with server-side rules, or a CMS like WordPress forcing a redirect that conflicts with server config. Remove conflicting rules and ensure each URL has exactly one redirect target.