warning http

HTTP 301 Moved Permanently

Understanding HTTP 301 Moved Permanently - the requested resource has been permanently moved to a new URL and all future requests should use the new URL.

What It Means

HTTP 301 Moved Permanently indicates that the requested resource has been assigned a new permanent URI. Any future references to this resource should use the new URI returned in the Location header.

Search engines will transfer the SEO ranking from the old URL to the new URL, making this the preferred redirect for permanent URL changes.

Important caveat: Browsers may change POST requests to GET requests when following a 301 redirect. Use 308 if you need to preserve the HTTP method.

Common Causes

  • A website has moved to a new domain
  • URL structure has been permanently changed
  • Pages have been consolidated or reorganized
  • Enforcing HTTPS by redirecting from HTTP
  • Redirecting from www to non-www (or vice versa)
  • Old API versions redirecting to new endpoints

How to Fix

Nginx Configuration

# Redirect a single page
server {
    listen 80;
    server_name example.com;

    location /old-page {
        return 301 https://example.com/new-page;
    }

    # Redirect HTTP to HTTPS
    return 301 https://$host$request_uri;
}

Apache (.htaccess)

# Redirect a single page
Redirect 301 /old-page https://example.com/new-page

# Redirect entire domain
RewriteEngine On
RewriteCond %{HTTP_HOST} ^olddomain\.com$ [NC]
RewriteRule ^(.*)$ https://newdomain.com/$1 [R=301,L]

Express.js

app.get('/old-page', (req, res) => {
  res.redirect(301, '/new-page');
});

// Redirect all HTTP to HTTPS
app.use((req, res, next) => {
  if (!req.secure) {
    return res.redirect(301, `https://${req.headers.host}${req.url}`);
  }
  next();
});

Client-side handling

// fetch follows redirects automatically
const response = await fetch('https://example.com/old-page');
console.log(response.url);        // https://example.com/new-page
console.log(response.redirected);  // true

Best practices:

  • Use 301 only for permanent moves — use 302 or 307 for temporary redirects
  • Always set the Location header with the new URL
  • Avoid redirect chains (A -> B -> C); redirect directly to the final URL
  • HTTP 302 - Found: Temporary redirect that may change the request method.
  • HTTP 307 - Temporary Redirect: Temporary redirect that preserves the request method.
  • HTTP 308 - Permanent Redirect: Permanent redirect that preserves the request method.