HTTPError.net

The fastest way to diagnose, understand, and fix any HTTP status code

301 Moved Permanently

Fault: Neither
TL;DR

All future requests should use the new URL provided in the Location header.

The resource has been permanently moved to a new URL.

What HTTP 301 Moved Permanently Means

The resource has been permanently moved to a new URL.

All future requests should use the new URL provided in the Location header.

Common Causes

What Visitors Should Do

Notes for Developers

301 vs 302 vs 307 vs 308

CodePermanent?Method on redirectTypical use
301YesMay change POST to GETMoved pages, domain or HTTPS migrations
302NoMay change POST to GETShort-term moves, login redirects
303NoAlways GETRedirect after a form POST
307NoMust keep method and bodyTemporary moves of APIs or forms
308YesMust keep method and bodyPermanent moves of APIs or forms

RFC 9110 allows clients to switch a POST to GET on a 301 or 302 for historical reasons, which is why 307 and 308 exist.

How to Set Up a 301 Redirect

# Nginx: redirect one path permanently
location = /old-page { return 301 /new-page; }

# Nginx: redirect a whole domain, keeping the path
server {
    server_name old.example.com;
    return 301 https://example.com$request_uri;
}

# Apache (.htaccess)
Redirect 301 /old-page /new-page

Redirect each old URL to its closest equivalent, update internal links to point to the final URL, and avoid redirect chains (A to B to C). Browsers cache 301s aggressively, so test redirects in a private window.

Returning a 301 Moved Permanently (Code Examples)

If you build APIs or web apps, here is how to send an HTTP 301 response and how to test for it:

Node.js (Express)

app.get('/resource', (req, res) => {
  res.status(301).json({ error: 'Moved Permanently' });
});

Python (Flask)

@app.route('/resource')
def resource():
    return jsonify(error='Moved Permanently'), 301

PHP

<?php
http_response_code(301);
header('Content-Type: application/json');
echo json_encode(['error' => 'Moved Permanently']);

Check the status with curl

curl -I https://example.com/resource
# Look for: HTTP/1.1 301 Moved Permanently

Frequently Asked Questions

What does HTTP 301 Moved Permanently mean?

All future requests should use the new URL provided in the Location header. In short: The resource has been permanently moved to a new URL.

How should I handle an HTTP 301 Moved Permanently response?

Update internal links to new URL. Use for permanent URL changes. Set Location header.

Official Specification

The 301 Moved Permanently status code is defined in RFC 9110 Section 15.4.2.

View the IANA HTTP Status Code Registry →