breakitdown

301, 302, 303, 307 and 308 redirects compared

Answer

Use 301 or 308 for permanent moves and 302 or 307 for temporary ones. 307 and 308 guarantee the client repeats the same method and body; with 301 and 302, browsers turn a POST into a GET. 303 always means "now GET this other URL".

301
Moved Permanently RFC 9110 §15.4.2

The resource has a new permanent URL, given in the Location header.

Used for domain moves, HTTP-to-HTTPS redirects and changed URL structures; search engines transfer ranking signals to the new URL. Browsers cache 301s aggressively, often with no expiry, so a mistaken 301 can stick in users' browsers long after you fix the server. For historical reasons clients may turn a POST into a GET when following it; use 308 if the method must be kept.

302
Found RFC 9110 §15.4.3

The resource is temporarily at a different URL, given in the Location header; keep using the original URL.

Called "Moved Temporarily" in HTTP/1.0. The classic use is redirecting to a login page or after a form post, though 303 states that intent more precisely. Browsers change a POST to a GET when following a 302 even though early specs said not to; use 307 if you need the method and body preserved.

303
See Other RFC 9110 §15.4.4

Go fetch the result from another URL with GET.

The standard way to implement Post/Redirect/Get: after a form POST succeeds, the server answers 303 pointing at a results page, and the browser loads it with GET, so a reload does not resubmit the form. Unlike 302, the switch to GET is required, not just tolerated. It does not mean the original resource moved.

307
Temporary Redirect RFC 9110 §15.4.8

The resource is temporarily at another URL; repeat the same request, same method and body, there.

It is a 302 with the method guaranteed: a POST stays a POST. Browsers also show an internal 307 when HSTS forces an http:// URL to https://; that redirect never left the browser, so you will not find it in server logs. Use it for temporary moves of API endpoints that accept non-GET methods.

308
Permanent Redirect RFC 9110 §15.4.9

The resource has a new permanent URL; repeat the same request, same method and body, there.

It is a 301 with the method guaranteed. First defined in RFC 7538 and now part of RFC 9110. Use it when permanently moving an endpoint that receives POST, PUT or DELETE. Very old clients that predate 308 may not follow it.

Explained

Two questions decide the code. Is the move permanent? Then clients and search engines should update their links: 301 or 308. Is it temporary? Then they should keep using the original URL: 302, 303 or 307.

Must the method be kept? Early browsers changed POST to GET when following 301 and 302, and the spec eventually allowed it. 307 (temporary) and 308 (permanent) were added so a redirected POST, PUT or DELETE is replayed exactly, body included. 303 goes the other way and always switches to GET, which is what you want after a form submission (the Post/Redirect/Get pattern).

In summary: 301 permanent, method may change to GET; 302 temporary, method may change to GET; 303 temporary, always GET; 307 temporary, method kept; 308 permanent, method kept.

Gotchas

Related explainers

← All HTTP status codes