Skip to content

301 Moved Permanently

What is HTTP 301 Moved Permanently?

301 Moved Permanently
When you try to visit a webpage that moved to a new address forever, the website...
HTTP 301 Moved Permanently status code illustration

Explain Like I’m 3

The thing you want moved to a new place forever! Like when your toys used to be in one box, but now they live in a different box. When you look in the old box, there’s a note saying ‘The toys are in the new box now!’

Example: Your favorite book moved from the red shelf to the blue shelf. Now there’s a sign on the red shelf that says ‘Book is on blue shelf!’ so you know where to find it.

Explain Like I’m 5

When you try to visit a webpage that moved to a new address forever, the website says ‘301 Moved Permanently’ and tells your computer the new address. Your browser then automatically goes to the new page for you. It’s like when your friend moves to a new house - when you go to the old house, there’s a sign with the new address, and you go there instead.

Example: A website used to be at oldsite.com/page but the owner moved it to newsite.com/page forever. When you type the old address, the website automatically sends you to the new address. Next time, you can just use the new address!

Jr. Developer

HTTP 301 Moved Permanently tells browsers and search engines that a resource has permanently moved to a new URL specified in the Location header. Browsers automatically redirect users to the new location, and search engines transfer the old page’s SEO ranking to the new URL. This is crucial for maintaining SEO value when you restructure your site, change domains, or reorganize content. Unlike 302 (temporary redirect), 301 signals the move is permanent, so search engines update their indexes accordingly. Always use 301 for permanent moves to preserve search rankings.

Example: You’re restructuring your blog and moving /blog/old-post-name to /blog/2024/new-post-name. You configure your server to return 301 with Location: /blog/2024/new-post-name. Users and search engines will find the content at the new location, and Google will transfer the old URL’s ranking to the new one.

Code Example

// Express.js permanent redirect
app.get('/old-page', (req, res) => {
res.redirect(301, '/new-page');
});
// Redirect entire old path structure
app.get('/blog/:oldSlug', (req, res) => {
const newSlug = convertToNewFormat(req.params.oldSlug);
res.redirect(301, `/articles/${newSlug}`);
});

Crash Course

301 Moved Permanently indicates the requested resource has been permanently relocated to the URL specified in the Location header. Clients should use the new URL for all future requests, and user agents typically cache 301 responses indefinitely. This is the standard mechanism for preserving SEO value during site migrations, domain changes, or URL restructuring. The redirect transfers link equity and PageRank to the new URL. Unlike 302 (temporary) or 307 (temporary with method preservation), 301 signals permanence. Note that 301 may change the request method from POST to GET, so use 308 Permanent Redirect if you need to preserve the HTTP method. Avoid redirect chains (multiple 301s in sequence) as they slow page loads and dilute SEO value. Common use cases include HTTP to HTTPS upgrades, www to non-www canonicalization, and content reorganization.

Example: Your company rebrands from oldcompany.com to newcompany.com. You configure 301 redirects for all pages: oldcompany.com/products → newcompany.com/products, etc. Search engines crawl the old URLs, receive 301 responses, and within weeks transfer all rankings to newcompany.com. Users bookmarking old URLs are automatically taken to new ones.

Code Example

// Apache .htaccess permanent redirects
# Single page redirect
Redirect 301 /old-page.html /new-page.html
# Entire domain redirect
RewriteEngine On
RewriteCond %{HTTP_HOST} ^oldsite\.com$ [NC]
RewriteRule ^(.*)$ https://newsite.com/$1 [R=301,L]
# HTTP to HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

Deep Dive

The 301 Moved Permanently status code, defined in RFC 9110 Section 15.4.2, indicates that the target resource has been assigned a new permanent URI and any future references to this resource ought to use one of the enclosed URIs. The response must include a Location header containing the preferred URI for the requested resource. Clients with link-editing capabilities should automatically relink references to the effective request URI to one or more of the new references sent by the server. The 301 response is cacheable by default, and user agents may cache it indefinitely unless explicitly prohibited by Cache-Control directives.

Technical Details

Protocol-level semantics distinguish 301 from related redirect codes: 301 permits method change (POST→GET is common browser behavior, though not required by spec), while 308 explicitly forbids method changes. This distinction matters for API endpoints and form submissions. RFC 7231 notes that for historical reasons, user agents may change POST to GET when automatically following 301 redirects, whereas 308 maintains strict method preservation.

Caching implications are significant: 301 responses without explicit Cache-Control or Expires headers may be cached indefinitely by browsers and proxies. This permanence is both powerful and dangerous - incorrectly configured 301s can be extremely difficult to undo if browsers cache them. Chrome, Firefox, and Safari all implement aggressive caching of 301s. To make a 301 ‘less permanent’ during testing, include Cache-Control: max-age=3600 to limit caching duration.

SEO mechanics: Search engines treat 301s as signals to consolidate ranking signals from the old URL to the new one. Google typically processes 301s within days to weeks, transferring most (90-99%) of link equity. However, redirect chains dilute this transfer - each hop in a chain (A→B→C) loses some equity. Best practice is direct single-hop redirects. Redirect loops (A→B→A) cause infinite redirect errors and are treated as server misconfigurations.

HTTP method preservation issues arise in API contexts. A POST to an old API endpoint that 301s to a new endpoint may be automatically converted to GET by the client, losing the request body. RFC 7231 acknowledges this historical behavior but recommends against it. Modern clients should preserve method, but compatibility concerns persist. Use 308 for APIs requiring strict method preservation, though older clients may not support it.

Security considerations include open redirect vulnerabilities when Location headers are derived from user input without validation. Attackers can craft URLs that redirect users to malicious sites. Always validate redirect destinations against a whitelist or ensure they’re within the same origin. Additionally, redirecting from HTTPS to HTTP downgrades security and triggers browser warnings - always redirect toward HTTPS, never away.

Performance impact: Each redirect adds a round-trip, increasing page load time. Mobile networks with high latency suffer particularly. Minimize redirects in critical paths. Server-side redirects (301) are faster than client-side (meta refresh, JavaScript) but slower than direct responses. For high-traffic sites, redirect processing consumes server resources - consider CDN-level redirects for better performance.

Code Example

// Production-grade redirect handling with validation
const url = require('url');
const ALLOWED_REDIRECT_HOSTS = ['newsite.com', 'www.newsite.com'];
app.get('/redirect/*', (req, res) => {
const oldPath = req.params[0];
// Look up redirect mapping from database/config
const redirectMap = {
'old-product': 'https://newsite.com/products/new-product',
'old-blog': 'https://newsite.com/blog/updated-post'
};
const newUrl = redirectMap[oldPath];
if (!newUrl) {
return res.status(404).send('Not Found');
}
// Security: validate redirect destination
try {
const parsedUrl = new url.URL(newUrl);
if (!ALLOWED_REDIRECT_HOSTS.includes(parsedUrl.hostname)) {
// Prevent open redirect vulnerability
logger.warn('Blocked redirect to unauthorized host', {
attempted: parsedUrl.hostname,
from: req.path
});
return res.status(400).send('Invalid redirect destination');
}
} catch (error) {
return res.status(400).send('Invalid URL');
}
// Log redirect for analytics
logger.info('301 redirect', {
from: req.originalUrl,
to: newUrl,
userAgent: req.get('User-Agent'),
referer: req.get('Referer')
});
// Set cache headers - cache for 1 year
res.set({
'Location': newUrl,
'Cache-Control': 'public, max-age=31536000',
'Vary': 'Accept-Encoding'
});
res.status(301).end();
});

Frequently Asked Questions

What's the difference between 301 and 302 redirects?

301 means the move is permanent - search engines transfer SEO value to the new URL and browsers may cache the redirect indefinitely. 302 means temporary - search engines keep the old URL indexed and don't transfer SEO value. Use 301 for permanent changes (domain migrations, URL restructuring) and 302 for temporary situations (maintenance pages, A/B testing).

Should I use 301 or 308 for permanent redirects?

Use 301 for most cases, especially content pages and SEO-focused redirects. Use 308 when you need to preserve the HTTP method (like POST requests) - for example, API endpoints or form submissions. Note that 308 has less browser support than 301, so 301 is safer for general use.

Do 301 redirects hurt SEO?

No, when used correctly they preserve SEO value! Google transfers 90-99% of link equity through 301 redirects. They're essential for maintaining rankings during site migrations. However, redirect chains (multiple hops) and redirect loops do hurt SEO and performance, so use direct single-hop redirects whenever possible.

How long do browsers cache 301 redirects?

By default, browsers may cache 301s indefinitely, making them very difficult to undo. Chrome, Firefox, and Safari all implement aggressive permanent caching. To make redirects 'less permanent' during testing, include a Cache-Control header with a shorter max-age value (like 3600 for 1 hour).

Can I redirect from HTTPS to HTTP with a 301?

Technically yes, but you absolutely shouldn't! Redirecting from secure to insecure connections triggers browser security warnings and hurts user trust. Always redirect toward HTTPS (HTTP→HTTPS), never away from it. Most browsers will show 'Not Secure' warnings for HTTP pages.

Common Causes

  • Website migrating from old domain to new domain (oldsite.com → newsite.com)
  • URL structure reorganization (/old-path → /new-path)
  • HTTP to HTTPS upgrade (http:// → https://)
  • www to non-www canonicalization or vice versa
  • Content consolidation - merging multiple old pages into one new page
  • Removing file extensions from URLs (/page.html → /page)

Implementation Guidance

  • Configure 301 redirects at server level (.htaccess, Nginx config, etc.)
  • Ensure Location header points to the correct new URL (absolute URL preferred)
  • Avoid redirect chains - redirect directly to final destination
  • Test redirects with curl or browser DevTools to verify correct headers
  • Use tools like Screaming Frog or Redirect Checker to audit all redirects
  • Implement redirect monitoring to catch broken redirect destinations
  • For temporary testing, add Cache-Control: max-age=3600 to prevent permanent caching
  • Update internal links to point directly to new URLs (don’t rely on redirects)
  • Monitor Google Search Console for crawl errors after implementing redirects

Comments