HTTP 301 Moved Permanently — SEO Redirects & Best Practices
The resource has been permanently moved to the URL given in the Location header. Search engines update their index to the new URL. Browsers cache the redirect and skip the original URL on future visits. The request method may change from POST to GET (unlike 308).
When to Return 301
Use for permanent URL changes: domain migrations, URL restructuring, HTTP → HTTPS upgrades (though your web server usually handles that). The Location header must be an absolute URL.
Common Causes
- Domain migration (old.com → new.com)
- URL path restructuring (/blog/post → /articles/post)
- Adding or removing www subdomain
HTTP Response Example
HTTP/1.1 301 Moved Permanently
Location: https://www.example.com/new-path
Cache-Control: max-age=31536000Code Examples
Express.js
// Redirect old URL to new URL permanently
app.get('/old-path', (req, res) => {
res.redirect(301, '/new-path')
})
// Redirect HTTP to HTTPS (usually handled by nginx/Cloudflare)
app.use((req, res, next) => {
if (!req.secure) return res.redirect(301, `https://${req.hostname}${req.url}`)
next()
})Next.js App Router
// next.config.ts
export default {
redirects: async () => [
{
source: '/old-path',
destination: '/new-path',
permanent: true, // sets 308 (Next.js default for permanent)
},
],
}
// Or in middleware.ts for dynamic redirects:
export function middleware(request: NextRequest) {
return NextResponse.redirect(new URL('/new-path', request.url), 301)
}Related Status Codes
Frequently Asked Questions
What does HTTP 301 Moved Permanently mean?
The resource has been permanently moved to the URL given in the Location header. Search engines update their index to the new URL. Browsers cache the redirect and skip the original URL on future visits. The request method may change from POST to GET (unlike 308).
When should an API return 301?
Use for permanent URL changes: domain migrations, URL restructuring, HTTP → HTTPS upgrades (though your web server usually handles that). The Location header must be an absolute URL.
What causes an HTTP 301 error?
Common causes: Domain migration (old.com → new.com); URL path restructuring (/blog/post → /articles/post); Adding or removing www subdomain.
