Reference
HTTP 3xx redirect status codes
RFC 9110 defines nine codes in the 3xx class, and only five of them redirect in practice: 301 and 308 are permanent, 302 and 307 are temporary, and 303 sends the client to a different resource with a GET. The split that matters is the method: 307 and 308 forbid changing it, while a POST answered with 301 or 302 is re-sent as a GET by browsers. 304 answers a conditional request and is not a redirect, 305 is deprecated and 306 is reserved.
| Code | Reason phrase | Meaning | Request method on the next hop | In a scan |
|---|---|---|---|---|
| 300 | Multiple Choices | The resource has several representations and the client is asked to choose one; the server may name a preferred choice in Location. | No automatic redirection is required. | Not one of the codes the page crawler follows; recorded with its status. |
| 301 | Moved Permanently | The resource has a new permanent URI and future references ought to use it. Heuristically cacheable. | A POST may be re-sent as GET, for historical reasons, and browsers do. | Followed; recorded as one hop of the chain. |
| 302 | Found | The resource is temporarily under a different URI; the client keeps using the original one. | A POST may be re-sent as GET, for historical reasons, and browsers do. | Followed; recorded as one hop of the chain. |
| 303 | See Other | The answer to the request is a different resource, typically the result page after a form submission. | The next request is a GET (or HEAD). | Followed; recorded as one hop of the chain. |
| 304 | Not Modified | Answers a conditional request: the stored copy the client already holds is still valid. Carries no new content. | Not a redirect. | Not expected: the crawler sends no conditional request. |
| 305 | Use Proxy | Defined by an earlier HTTP specification and now deprecated. | Not applicable. | Not followed. |
| 306 | (Unused) | Defined by an earlier specification, no longer used; the code is reserved. | Not applicable. | Not followed. |
| 307 | Temporary Redirect | The resource is temporarily under a different URI; the client keeps using the original one. | The method and body must not change. | Followed; recorded as one hop of the chain. |
| 308 | Permanent Redirect | The resource has a new permanent URI and future references ought to use it. Heuristically cacheable. | The method and body must not change. | Followed; recorded as one hop of the chain. |
Two questions sort the five real redirects
The first question is duration. 301 and 308 say the move is permanent and that references ought to be updated; 302 and 307 say it is temporary and that the original address stays the one to use.
The second question is the request method. The Fetch standard, which browsers implement, re-sends a POST as a GET after a 301 or a 302, and turns anything other than GET or HEAD into a GET after a 303. After a 307 or a 308 the method and the body are kept exactly as they were.
That second question is why 307 and 308 exist. They were added so a form or an API call could be redirected without silently losing its body, which is what happens to a POST answered with a 301 or a 302.
303 is the deliberate case of the rule: it is the code for sending a browser from a form submission to the page that shows its result, so that reloading that page does not submit the form again.
The four codes of the class that do not redirect
304 is the one met most often. A client that holds a stored copy asks whether it is still valid, with `If-None-Match` or `If-Modified-Since`, and a 304 answers that it is. A 304 on a request that asked no such question is a server or a cache misbehaving.
300 asks the client to choose between several representations. The Fetch standard's redirect statuses are 301, 302, 303, 307 and 308 only, so a browser does not follow a 300 automatically, and it is rarely served on purpose.
305 is deprecated and 306 is reserved. Neither should appear on a live site; seeing one is a sign of a very old or misconfigured component in the path.
What a scan records for each hop
The entry URL's redirects are followed one hop at a time, without letting the HTTP client follow them automatically, so the status code of every hop is kept. At most five hops are followed, and a redirect pointing at a private network address is not followed at all.
`transport.redirect_chain` reports up to two hops as normal and warns from three. `availability.redirect_loop` fails when the same URL is visited twice in the chain and warns when a chain without a loop is longer than three hops. `transport.http_redirect` reports which code sent the plain `http://` address to HTTPS.
The page crawler follows 301, 302, 303, 307 and 308 and records every hop. A redirect is never counted as a broken link: a link is judged on the status of the page it finally reaches.
The scan records the code; it does not decide for you whether a move should have been a 301 or a 302. That depends on whether the old address is meant to come back, which no response header says.
Why a permanent redirect is hard to take back
RFC 9110 lists 301 and 308 among the heuristically cacheable status codes. Without explicit cache headers, a browser or an intermediary may store the redirect and apply it again without asking the server.
A permanent redirect published by mistake can therefore keep sending returning visitors to the wrong place after the server rule has been removed. During a migration that is still being tested, a temporary code is the reversible choice; the permanent one comes once the destination is final.
Frequently asked questions
- How many redirects will a browser follow?
- The Fetch standard stops at twenty redirects and returns a network error on the twenty-first. Long before that limit, every hop adds a round trip to the page load, which is why a chain of three or more hops is worth shortening.
- Why does a form submission arrive as a GET after a redirect?
- Because the form was answered with a 301, 302 or 303, and browsers re-send the request as a GET after those codes. To redirect a POST and keep its method and body, the server has to answer with 307 or 308.
- Is a 304 Not Modified a problem?
- Not when the client asked for it with a conditional request: it is the cheap answer that says the stored copy is still valid. It is only a problem when a server or cache sends it to a client that asked no conditional question.
Sources
Related
VeriFixScan crawls a site and applies its checks to every page it reaches, keeping the evidence behind each finding. Scanning one website is free.
Scan a website