169

The differences between the various HTTP 3XX redirect codes are not clear to me. Yes, I've read the spec, but there seems to be some discrepancy between the standard and actual practice here.

The 301 redirect code seems clear enough: This means the resource was permanently moved to another URI, and future requests should use that URI.

And the 307 redirect code also seems clear: it means the redirect is temporary, and future requests should still use the original URI.

But I can't tell what the difference is between 302 and 303, or why either of them are really different from 301. It seems that 302 was originally intended to be a temporary redirect, (like 307), but in practice, most browsers treated it like a 303. But what's the difference between a 303 and a 301? Is 301 supposed to mean the redirect is more permanent?

hippietrail
  • 15,848
  • 18
  • 99
  • 158
Channel72
  • 24,139
  • 32
  • 108
  • 180

2 Answers2

160
  • 301: Permanent redirect. Clients making subsequent requests for this resource should use the new URI. Clients should not follow the redirect automatically for POST/PUT/DELETE requests.
  • 302: Redirect for undefined reason. Clients making subsequent requests for this resource should not use the new URI. Clients should not follow the redirect automatically for POST/PUT/DELETE requests.
  • 303: Redirect for undefined reason. Typically, 'Operation has completed, continue elsewhere.' Clients making subsequent requests for this resource should not use the new URI. Clients should follow the redirect for POST/PUT/DELETE requests, but use GET for the follow-up request.
  • 307: Temporary redirect. Resource may return to this location at a later point. Clients making subsequent requests for this resource should use the old URI. Clients should not follow the redirect automatically for POST/PUT/DELETE requests.

I personally recommend avoiding 302 if you have the choice. Many clients do not follow the spec when they encounter a 302. For temporary redirects, you should use either 303 or 307, depending on what type of behavior you want on non-GET requests. Prefer 307 to 303 unless you need the alternate behavior on POST/PUT/DELETE.

vog
  • 23,517
  • 11
  • 59
  • 75
Bob Aman
  • 32,839
  • 9
  • 71
  • 95
  • 28
    Nope. Following a 303 requires rewriting the method to GET. Following the others requires keeping the method, but to confirm with the UA if the method is unsafe (so methods other than OPTIONS, HEAD, GET, PROPFIND...) – Julian Reschke Jan 22 '11 at 09:58
  • Yes, that's correct. So to clarify, you would use a 303 when you have a POSTed form, and you finished the operation and want the user to go someplace else. It's particularly useful to avoid the case where the user refreshes the page after POSTing the form, getting either a warning they cancel out of or the potential that they resubmit the form data. – Bob Aman Jan 24 '11 at 19:42
  • 1
    @JulianReschke Could you please point places in the specs backing up your statement? – Piotr Dobrogost Nov 27 '11 at 18:07
  • 9
    @BobAman In your description you are doing the same mistakes made in the original HTTP spec ([RFC 1945](http://tools.ietf.org/html/rfc1945)). For instance saying that *Clients should follow the redirect for POST/PUT/DELETE requests.* after 303 redirect **without** specifying that the http verb to use in the following request must be GET is misleading... – Piotr Dobrogost Nov 27 '11 at 18:20
  • 4
    Correcting myself: "Following a 303 requires rewriting the method to GET unless the initial method was HEAD". – Julian Reschke Nov 28 '11 at 14:26
  • @JulianReschke *Note that <> is a statement about what URI to use, not what to do with it.* Sure, it seems like these are (should be) orthogonal subjects. Well, in that case instead of introducing new codes (303 and 307) just to be able to define what methods should be used in each case shouldn't the specs introduce a new header with information what method to use? – Piotr Dobrogost Nov 28 '11 at 23:16
  • 5
    Piotr: the default should be *not* to modify the method; the resource moved, that doesn't affect how to manipulate it. 303 is an exception; it doesn't mean "the resource has moved" but "the request was processed, and here is your result"; it's an entirely different type of redirect. See http://greenbytes.de/tech/webdav/draft-ietf-httpbis-p2-semantics-17.html#status.3xx – Julian Reschke Nov 29 '11 at 08:31
  • Can you please put more information about caching in each case. If expires header was sent with temporary redirect, will subsequent request consider old URL or new? – Akash Kava Aug 28 '13 at 07:15
  • @AkashKava See http://stackoverflow.com/questions/12212839/how-long-is-a-302-redirect-saved-in-browser for more details. A permanent redirect may be cached indefinitely, regardless of the presence or absence of caching headers as a way of satisfying the requirement that the client avoid making requests for the old resource. However, the exact implementation of this requirement depends on the type of client making the request. An RSS/Atom reader (as opposed to a browser), for example, should just update the feed record with the new URI in the case of 301 rather than caching the response. – Bob Aman Sep 03 '13 at 02:01
  • 6
    Since @BobAman refused to integrate JulianReschke's correction into his answer, I stepped in to integrate it. By the way, I still think that GolezTrol's answer is more accurate an to the point (https://stackoverflow.com/a/4764473/19163). Unfortunately, his answer never caught up to become the top answer, so I decided to fix the worse answer in addition to upvoting the better answer. – vog Jun 17 '17 at 06:48
  • @vog That's not fair at all. I didn't refuse to correct it, I answered the original comment and agreed that he was right. Six years ago! I did fail to update my answer, sure, and thank you for going ahead and making the edit, but at no point did I "refuse to correct" it. – Bob Aman Jul 05 '17 at 18:18
  • @BobAman Sorry, wrong wording on my side. I meant "... didn't care to integrate ..." – vog Jul 06 '17 at 08:11
  • 2
    It's unclear what "Clients should not follow the redirect automatically for POST/PUT/DELETE requests." does mean in description of 302/307. What clients should do instead then? Just ignore the response code? Ask user confirmation? Something else? It's also important to mention that 302 is actually implemented with behavior of 303 instead of 307 (as the spec and this answer states) in most http clients (saying "do not follow the spec" is not enough, imho) and that is why 2 new codes (303 and 307) were introduced instead of just one to complement 302. – Ruslan Stelmachenko Nov 05 '20 at 17:16
97

The difference between 303 and 307 is this:

303: See other. The request is received correctly, but the results should be retrieved using a GET on the redirect url.

307: Temporary redirect. The entire request should be redirected to the new url. Any post data should be re-posted.

Note that 302 was intended to have the behavior of 307, but most browsers implemented it as the behavior of 303 (both of which didn't exist back then). Therefore, those two new codes were introduced to replace 302.

The difference between 301 and 303:

301: The document is moved. Future requests should use the new url. This url is obsolete.

Note: Be careful with this code. Browsers and proxies tend to apply really agressive caching on it, so if you reply with a 301 it might take a long while for someone to revisit that url.

303: The request is received correctly. Any PUT requests are processed. The resulting document can be retrieved from the redirect url. Future request should still go to the original url.

GolezTrol
  • 114,394
  • 18
  • 182
  • 210
  • 1
    a good blog post that goes into the details of 3xx (and all the problems with it) is at: http://insanecoding.blogspot.no/2014/02/http-308-incompetence-expected.html – arcuri82 Oct 29 '16 at 11:57
  • 1
    @skeller88 You change made my answer incorrect so I reverted it (boo to the people who accepted the change)! You introduced the same mistake as the accepted answer has. 303 is a different kind of redirect and different rules apply, as confirmed by the comments by Julian Reschke on the accepted answer and the blog that was linked by arcuri82 – GolezTrol Feb 18 '17 at 09:00
  • I like this answer much more than accepted answer because it explicitly states **why** two new codes (303 and 307) were introduced instead of introducing just one (which seems more logical to me), that preserves HTTP method in addition to already existing 302, that doesn't. In reality 302 works exactly like 303 in most browsers. But that contradicts the spec, and that's why 303 was introduced. This means that 302 should not be used at all because while most software clients implement it like 303, some other can follow the spec that ironically will violate "expected" behavior. – Ruslan Stelmachenko Nov 05 '20 at 16:51
  • 1
    On the other hand, some older clients can ignore 303 and 307 and only do redirect when 301/302 is received, because they have no idea what 303/307 is (In 2k20 I think it's hard to find such http client). So the recommendation which code to use (302 or 303) to create a "GET" redirect depends mostly on expected http clients. – Ruslan Stelmachenko Nov 05 '20 at 16:59
  • @RuslanStelmachenko Thanks! While theoretically old clients can always be a concern, those status codes were introduced with HTTP 1.1 back in 1999, when Microsoft's Internet Explorer 5 was just gaining some market share over Netscape, years before the first Firefox and Chrome releases. Apparently [some bots _say_ they are on HTTP 1.0](https://stackoverflow.com/a/40076230/511529), but even that doesn't mean they won't respond to these status codes. But yeah, it's good to keep it in min in case you see weird behavior in response to these statuses. – GolezTrol Nov 06 '20 at 12:44