HTTP 303 See Other – Free, Online, Private
303 See Other tells the client to GET a different URI for the result of this request.
What HTTP 303 means
303 is the status for the post-redirect-get pattern. The original request, often a POST, has been processed, and the result is somewhere else. The follow-up must be GET. That split keeps a refresh from resubmitting the form. It is not a permanent move, and it is not a temporary copy of the same request.
303 See Other belongs to the 3xx redirection class. Clients that only look at the class will group it with its neighbors. Clients that care about the exact code should use the narrower rule on this page, because the class is only the first digit.
When you see HTTP 303
When you see HTTP 303 See Other, stop on that exact status line. 303 See Other tells the client to GET a different URI for the result of this request. The trace that usually produces it: A form POST created a record and the browser was sent to the record's page. The 3xx redirection class only tells you the first digit. A neighbor in that class is a different fault, and the fix on this page does not transfer to it.
Return 303 after a successful POST when the result has its own URL, such as the new object or a confirmation page. If the resource was created and you want the client to remember that URL as the object's address, 201 with Location is the more precise status. Use 303 when the next step is a page, not when you are naming the created resource.
How to fix HTTP 303
To fix HTTP 303, change the condition that made the server choose See Other. Follow Location with GET, regardless of the original method. Do not resend the POST body. If you do not follow redirects, read Location and GET it yourself. Do not retry the POST because you received 303. The work already succeeded. Retry the GET if that fetch fails. If the log line is a different code, leave this page. The mix-up people make with 303 is this one: 201 points at a resource this request created and does not force GET. 302 may or may not change the method. 303 always means GET the other URI.
- A client followed 303 with POST and the server rejected the second write.
- Location pointed at an error page and the user thought the POST failed even though it succeeded.
- A JSON client did not follow redirects and showed the empty 303 body as the result.
An access log that only stores 303 is not enough to tell these apart. Keep the method, the path, and a request id. Do not keep the Authorization header or a request body that might be a token. The status explains the outcome. It is not a place to echo secrets back to the client either.
Example response
HTTP 303 See OtherHTTP/1.1 303 See Other
Location: /orders/42
The client GETs /orders/42. That GET returns 200 and the order. The 303 itself has no interesting body. If the POST failed, do not send 303 to an error URL and hope the user notices. Send the error status on the POST.
What the client should do
Follow Location with GET, regardless of the original method. Do not resend the POST body. If you do not follow redirects, read Location and GET it yourself.
303 is not the representation. Do not cache it as the POST result. The subsequent GET is cached under its own rules.
Do not retry the POST because you received 303. The work already succeeded. Retry the GET if that fetch fails.
Codes people confuse with HTTP 303
201 points at a resource this request created and does not force GET. 302 may or may not change the method. 303 always means GET the other URI.
Frequently asked questions
Why not 302 after a form?
303 states that the next request is GET. 302 leaves that to the client's history.
Does 303 mean the POST failed?
No. It means the POST finished and the result is at Location.
Is the body of 303 the result?
No. The result is the response to the GET you do next.
How is 201 different?
201 names a resource that was created. 303 sends you to some other URI with GET.
What should I do first when I see HTTP 303?
Read the status as 303 See Other specifically. 303 See Other tells the client to GET a different URI for the result of this request. Then check the cause that matches the request you sent, starting with: A form POST created a record and the browser was sent to the record's page.