HTTP Status Code Response Obligations
RFC 9110 puts the rule for what a 405 must carry in section 15.5.6, the 401 rule in 15.5.2, and the 201 Location rule in the POST method section. When I review an API response or write a contract test, I want those rules side by side. This table lists the per-status header and content rules from RFC 9110 section 15 and RFC 6585, with the exact keyword, who it applies to, when it applies, and the section to cite.
Each status code has a stable link, such as #405, and each rule has its own, such as #405-allow. The same rows are published as JSON for linters and test suites.
Quick answers
- 401 needs WWW-Authenticate. A server sending 401 MUST include at least one challenge (RFC 9110 §15.5.2).
- 405 needs Allow. The origin server MUST list the methods the resource supports now (RFC 9110 §15.5.6).
- 201 does not always need Location. The 201 definition has no keyword for it. After a POST creates a resource, the origin server SHOULD send Location (RFC 9110 §9.3.3). After a PUT creates one, the target URI already identifies it.
- 429 and 503 do not need Retry-After. Both say MAY. A temporary 413 SHOULD send it.
- Caches MUST NOT store 429 responses. RFC 6585 says the same for 428, 431, and 511.
How to read the table
- MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY are the BCP 14 keywords from RFC 2119 and RFC 8174. They only carry that meaning in uppercase.
- No keyword means the RFC defines the behavior or uses words like "ought to" or "can". Those rows are listed because reviewers ask about them, but they are not requirements.
- Who names the party the rule binds: sender, server, origin server, proxy, intercepting proxy, cache, client, or user agent. A proxy rule does not apply to your origin server.
- Client and user agent rows only cover reading the response itself. Client retry rules and rules for following Location are left out, except 307's method rule.
- Applies when is the condition from the RFC sentence. Always means the rule applies to every response with that status code.
- Open RFC text in a row to read the sentence the row is based on.
Rules by status code
| Code | Keyword | Who | Field or part | Applies when | Rule | Section |
|---|---|---|---|---|---|---|
1xx (all) | MUST NOT | server | response | The client uses HTTP/1.0. | Do not send any 1xx response to an HTTP/1.0 client. # RFC textSince HTTP/1.0 did not define any 1xx status codes, a server MUST NOT send a 1xx response to an HTTP/1.0 client. | |
1xx (all) | No keyword | sender | content | Always | A 1xx response ends at its header section. It has no content and no trailers. # RFC textA 1xx response is terminated by the end of the header section; it cannot contain content or trailers. | |
1xx (all) | MUST | client | response handling | Always | Parse one or more 1xx responses before the final response, even when none was expected. # RFC textA client MUST be able to parse one or more 1xx responses received prior to a final response, even if the client does not expect one. | |
1xx (all) | MUST | proxy | forwarding | Unless the proxy itself requested the 1xx. | Forward 1xx responses to the client. # RFC textA proxy MUST forward 1xx responses unless the proxy itself requested the generation of the 1xx response. | |
4xx (all) | SHOULD | server | content | Any request except HEAD. | Send a representation explaining the error and whether it is temporary or permanent. # RFC textExcept when responding to a HEAD request, the server SHOULD send a representation containing an explanation of the error situation, and whether it is a temporary or permanent condition. | |
5xx (all) | SHOULD | server | content | Any request except HEAD. | Send a representation explaining the error and whether it is temporary or permanent. # RFC textExcept when responding to a HEAD request, the server SHOULD send a representation containing an explanation of the error situation, and whether it is a temporary or permanent condition. | |
101 Switching Protocols | MUST | server | Upgrade | Always | Send Upgrade naming the protocol or protocols in effect after this response. # RFC textThe server MUST generate an Upgrade header field in the response that indicates which protocol(s) will be in effect after this response. | |
200 OK | SHOULD | origin server | ETag, Last-Modified | Responses to GET or HEAD. | Send any available validator fields. A strong ETag plus Last-Modified is preferred. # RFC textIn 200 responses to GET or HEAD, an origin server SHOULD send any available validator fields (Section 8.8) for the selected representation, with both a strong entity tag and a Last-Modified date being preferred. | |
201 Created | No keyword | sender | Location | Always | The 201 definition does not require Location. Location identifies the primary created resource; without it, the target URI does. # RFC textThe primary resource created by the request is identified by either a Location header field in the response or, if no Location header field is received, by the target URI. | |
201 Created | SHOULD | origin server | Location, content | A POST created one or more resources. | Answer with 201, a Location for the primary resource, and content that describes the request status and refers to the new resource. # RFC textIf one or more resources has been created on the origin server as a result of successfully processing a POST request, the origin server SHOULD send a 201 (Created) response containing a Location header field that provides an identifier for the primary resource created (Section 10.2.2) and a representation that describes the status of the request while referring to the new resource(s). | |
201 Created | MUST | origin server | status | A PUT created a representation where none existed. | Answer with 201. # RFC textIf the target resource does not have a current representation and the PUT successfully creates one, then the origin server MUST inform the user agent by sending a 201 (Created) response. | |
202 Accepted | No keyword | sender | content | Always | Describe the current status of the request and point to, or embed, a status monitor. RFC 9110 says "ought to", which is not a BCP 14 keyword. # RFC textThe representation sent with this response ought to describe the request's current status and point to (or embed) a status monitor that can provide the user with an estimate of when the request will be fulfilled. | |
204 No Content | No keyword | sender | content | Always | A 204 response ends at its header section. It has no content and no trailers. # RFC textA 204 response is terminated by the end of the header section; it cannot contain content or trailers. | |
205 Reset Content | MUST NOT | server | content | Always | Do not generate content. # RFC textSince the 205 status code implies that no additional content will be provided, a server MUST NOT generate content in a 205 response. | |
206 Partial Content | MUST | server | Date, Cache-Control, ETag, Expires, Content-Location, Vary | Each field that a 200 response to the same request would have sent. | Send those fields, in addition to the part-specific fields below. # RFC textA server that generates a 206 response MUST generate the following header fields, in addition to those required in the subsections below, if the field would have been sent in a 200 (OK) response to the same request: Date, Cache-Control, ETag, Expires, Content-Location, and Vary. | |
206 Partial Content | SHOULD NOT | sender | representation header fields | The request had If-Range. | Do not send representation header fields beyond the required ones; the client already has them. # RFC textA sender that generates a 206 response to a request with an If-Range header field SHOULD NOT generate other representation header fields beyond those required because the client already has a prior response containing those header fields. | |
206 Partial Content | MUST | sender | representation header fields | The request had no If-Range. | Send every representation header field that a 200 response would have sent. # RFC textOtherwise, a sender MUST generate all of the representation header fields that would have been sent in a 200 (OK) response to the same request. | |
206 Partial Content | MUST | server | Content-Range, content | One part is sent. | Send Content-Range for the enclosed range, with that range as the content. # RFC textIf a single part is being transferred, the server generating the 206 response MUST generate a Content-Range header field, describing what range of the selected representation is enclosed, and a content consisting of the range. | |
206 Partial Content | MUST | server | Content-Type, content | Multiple parts are sent. | Send multipart/byteranges content and a Content-Type of multipart/byteranges with its boundary parameter. # RFC textIf multiple parts are being transferred, the server generating the 206 response MUST generate "multipart/byteranges" content, as defined in Section 14.6, and a Content-Type header field containing the "multipart/byteranges" media type and its required boundary parameter. | |
206 Partial Content | MUST NOT | server | Content-Range | Multiple parts are sent. | Do not put Content-Range in the response header section. Each part carries its own. # RFC textTo avoid confusion with single-part responses, a server MUST NOT generate a Content-Range header field in the HTTP header section of a multiple part response (this field will be sent in each part instead). | |
206 Partial Content | MUST | server | Content-Range | Multiple parts are sent. | Send Content-Range in the header area of each body part. # RFC textWithin the header area of each body part in the multipart content, the server MUST generate a Content-Range header field corresponding to the range being enclosed in that body part. | |
206 Partial Content | SHOULD | server | Content-Type | Multiple parts are sent, and a 200 response would have had Content-Type. | Send that same Content-Type in the header area of each body part. # RFC textIf the selected representation would have had a Content-Type header field in a 200 (OK) response, the server SHOULD generate that same Content-Type header field in the header area of each body part. | |
206 Partial Content | SHOULD | server | content | Multiple parts are sent. | Send the parts in the order the ranges appeared in the Range header, leaving out unsatisfiable or coalesced ranges. # RFC textA server that generates a multipart response SHOULD send the parts in the same order that the corresponding range-spec appeared in the received Range header field, excluding those ranges that were deemed unsatisfiable or that were coalesced into other ranges. | |
206 Partial Content | MAY | server | content | Multiple ranges were requested. | Coalesce ranges that overlap or are separated by a gap smaller than the multipart overhead. # RFC textWhen multiple ranges are requested, a server MAY coalesce any of the ranges that overlap, or that are separated by a gap that is smaller than the overhead of sending multiple parts, regardless of the order in which the corresponding range-spec appeared in the received Range header field. | |
206 Partial Content | MUST NOT | server | content | The request asked for one range. | Do not send a multipart response. # RFC textA server MUST NOT generate a multipart response to a request for a single range, since a client that does not request multiple parts might not support multipart responses. | |
206 Partial Content | MAY | server | content | Multiple ranges were requested, but only one was satisfiable or one remained after coalescing. | Send a multipart/byteranges response with a single body part. # RFC textHowever, a server MAY generate a "multipart/byteranges" response with only a single body part if multiple ranges were requested and only one range was found to be satisfiable or only one range remained after coalescing. | |
206 Partial Content | MUST | client | Content-Type, Content-Range | Always | Read Content-Type and Content-Range to see which parts arrived and whether more requests are needed. # RFC textA client MUST inspect a 206 response's Content-Type and Content-Range field(s) to determine what parts are enclosed and whether additional requests are needed. | |
300 Multiple Choices | SHOULD | server | Location | The server has a preferred choice. | Send Location with the preferred choice's URI reference. # RFC textIf the server has a preferred choice, the server SHOULD generate a Location header field containing a preferred choice's URI reference. | |
300 Multiple Choices | SHOULD | server | content | Any request method except HEAD. | Send content listing the available representations and their URI references. # RFC textFor request methods other than HEAD, the server SHOULD generate content in the 300 response containing a list of representation metadata and URI reference(s) from which the user or user agent can choose the one most preferred. | |
301 Moved Permanently | SHOULD | server | Location | Always | Send Location with the new permanent URI. # RFC textThe server SHOULD generate a Location header field in the response containing a preferred URI reference for the new permanent URI. | |
302 Found | SHOULD | server | Location | Always | Send Location with the temporary URI. # RFC textThe server SHOULD generate a Location header field in the response containing a URI reference for the different URI. | |
303 See Other | No keyword | sender | Location | Always | 303 is defined by the URI in Location, which the client fetches as the indirect response. RFC 9110 states no separate keyword for it. # RFC textThe 303 (See Other) status code indicates that the server is redirecting the user agent to a different resource, as indicated by a URI in the Location header field, which is intended to provide an indirect response to the original request. | |
303 See Other | No keyword | sender | content | Any request except HEAD. | Include a short hypertext note linking to the Location URI. RFC 9110 says "ought to", which is not a BCP 14 keyword. # RFC textExcept for responses to a HEAD request, the representation of a 303 response ought to contain a short hypertext note with a hyperlink to the same URI reference provided in the Location header field. | |
304 Not Modified | MUST | server | Content-Location, Date, ETag, Vary, Cache-Control, Expires | Each field that a 200 response to the same request would have sent. | Send those fields. # RFC textThe server generating a 304 response MUST generate any of the following header fields that would have been sent in a 200 (OK) response to the same request: * Content-Location, Date, ETag, and Vary * Cache-Control and Expires (see [CACHING]) | |
304 Not Modified | SHOULD NOT | sender | representation metadata | Unless the metadata guides cache updates, such as Last-Modified when there is no ETag. | Do not send other representation metadata. # RFC textSince the goal of a 304 response is to minimize information transfer when the recipient already has one or more cached representations, a sender SHOULD NOT generate representation metadata other than the above listed fields unless said metadata exists for the purpose of guiding cache updates (e.g., Last-Modified might be useful if the response does not have an ETag field). | |
304 Not Modified | No keyword | sender | content | Always | A 304 response ends at its header section. It has no content and no trailers. # RFC textA 304 response is terminated by the end of the header section; it cannot contain content or trailers. | |
304 Not Modified | SHOULD | proxy | forwarding | The conditional request came from an outbound client, such as a user agent with its own cache. | Forward the 304 to that client. # RFC textIf the conditional request originated with an outbound client, such as a user agent with its own cache sending a conditional GET to a shared proxy, then the proxy SHOULD forward the 304 response to that client. | |
307 Temporary Redirect | SHOULD | server | Location | Always | Send Location with the temporary URI. # RFC textThe server SHOULD generate a Location header field in the response containing a URI reference for the different URI. | |
307 Temporary Redirect | MUST NOT | user agent | request method | The user agent follows the 307 automatically. | Keep the original request method. # RFC textThe 307 (Temporary Redirect) status code indicates that the target resource resides temporarily under a different URI and the user agent MUST NOT change the request method if it performs an automatic redirection to that URI. | |
308 Permanent Redirect | SHOULD | server | Location | Always | Send Location with the new permanent URI. # RFC textThe server SHOULD generate a Location header field in the response containing a preferred URI reference for the new permanent URI. | |
401 Unauthorized | MUST | server | WWW-Authenticate | Always | Send WWW-Authenticate with at least one challenge for the target resource. # RFC textThe server generating a 401 response MUST send a WWW-Authenticate header field (Section 11.6.1) containing at least one challenge applicable to the target resource. | |
405 Method Not Allowed | MUST | origin server | Allow | Always | Send Allow listing the methods the target resource supports now. # RFC textThe origin server MUST generate an Allow header field in a 405 response containing a list of the target resource's currently supported methods. | |
406 Not Acceptable | SHOULD | server | content | Always | Send content listing the available representations and their resource identifiers. # RFC textThe server SHOULD generate content containing a list of available representation characteristics and corresponding resource identifiers from which the user or user agent can choose the one most appropriate. | |
407 Proxy Authentication Required | MUST | proxy | Proxy-Authenticate | Always | Send Proxy-Authenticate with a challenge for that proxy. # RFC textThe proxy MUST send a Proxy-Authenticate header field (Section 11.7.1) containing a challenge applicable to that proxy for the request. | |
409 Conflict | SHOULD | server | content | Always | Send content that lets the user recognize the source of the conflict. # RFC textThe server SHOULD generate content that includes enough information for a user to recognize the source of the conflict. | |
413 Content Too Large | SHOULD | server | Retry-After | The condition is temporary. | Send Retry-After to say the limit is temporary and when the client can try again. # RFC textIf the condition is temporary, the server SHOULD generate a Retry-After header field to indicate that it is temporary and after what time the client MAY try again. | |
415 Unsupported Media Type | No keyword | server | Accept-Encoding | An unsupported content coding caused the 415. | Use Accept-Encoding to list the codings that would have worked. RFC 9110 says "ought to", which is not a BCP 14 keyword. # RFC textIf the problem was caused by an unsupported content coding, the Accept-Encoding response header field (Section 12.5.3) ought to be used to indicate which (if any) content codings would have been accepted in the request. | |
415 Unsupported Media Type | No keyword | server | Accept | An unsupported media type caused the 415. | Accept can list the media types that would have worked. Optional. # RFC textOn the other hand, if the cause was an unsupported media type, the Accept response header field (Section 12.5.1) can be used to indicate which media types would have been accepted in the request. | |
416 Range Not Satisfiable | SHOULD | server | Content-Range | The request was a byte-range request. | Send Content-Range with the current length, for example bytes */47022. # RFC textA server that generates a 416 response to a byte-range request SHOULD generate a Content-Range header field specifying the current length of the selected representation (Section 14.4). | |
421 Misdirected Request | MUST NOT | proxy | response | Always | Do not generate a 421. # RFC textA proxy MUST NOT generate a 421 response. | |
426 Upgrade Required | MUST | server | Upgrade | Always | Send Upgrade naming the required protocol or protocols. # RFC textThe server MUST send an Upgrade header field in a 426 response to indicate the required protocol(s) (Section 7.8). | |
428 Precondition Required | SHOULD | server | content | Always | Explain how to resubmit the request successfully. # RFC textResponses using this status code SHOULD explain how to resubmit the request successfully. | |
428 Precondition Required | MUST NOT | cache | storage | Always | Do not store the response. # RFC textResponses with the 428 status code MUST NOT be stored by a cache. | |
429 Too Many Requests | SHOULD | server | content | Always | Explain the rate limit in the response content. # RFC textThe response representations SHOULD include details explaining the condition, and MAY include a Retry-After header indicating how long to wait before making a new request. | |
429 Too Many Requests | MAY | server | Retry-After | Always | Send Retry-After with how long to wait. Optional. # RFC textThe response representations SHOULD include details explaining the condition, and MAY include a Retry-After header indicating how long to wait before making a new request. | |
429 Too Many Requests | MUST NOT | cache | storage | Always | Do not store the response. # RFC textResponses with the 429 status code MUST NOT be stored by a cache. | |
431 Request Header Fields Too Large | SHOULD | server | content | A single header field is too large. | Name the header field that was too large. # RFC textIn the latter case, the response representation SHOULD specify which header field was too large. | |
431 Request Header Fields Too Large | MUST NOT | cache | storage | Always | Do not store the response. # RFC textResponses with the 431 status code MUST NOT be stored by a cache. | |
503 Service Unavailable | MAY | server | Retry-After | Always | Send Retry-After with a suggested wait. Optional. # RFC textThe server MAY send a Retry-After header field (Section 10.2.3) to suggest an appropriate amount of time for the client to wait before retrying the request. | |
505 HTTP Version Not Supported | SHOULD | server | content | Always | Explain why the HTTP version is not supported and which protocols are. # RFC textThe server SHOULD generate a representation for the 505 response that describes why that version is not supported and what other protocols are supported by that server. | |
511 Network Authentication Required | SHOULD | intercepting proxy | content | Always | Link to a resource where the user can submit credentials. # RFC textThe response representation SHOULD contain a link to a resource that allows the user to submit credentials (e.g., with an HTML form). | |
511 Network Authentication Required | SHOULD NOT | intercepting proxy | content | Always | Do not include a challenge or the login interface itself. # RFC textNote that the 511 response SHOULD NOT contain a challenge or the login interface itself, because browsers would show the login interface as being associated with the originally requested URL, which may cause confusion. | |
511 Network Authentication Required | SHOULD NOT | origin server | response | Always | Do not generate 511. It is for intercepting proxies that control network access. # RFC textThe 511 status SHOULD NOT be generated by origin servers; it is intended for use by intercepting proxies that are interposed as a means of controlling access to the network. | |
511 Network Authentication Required | MUST NOT | cache | storage | Always | Do not store the response. # RFC textResponses with the 511 status code MUST NOT be stored by a cache. |
Codes with no status-specific rule
Not every status code needs a particular header. RFC 9110 defines these codes without adding a header or content rule of their own: 100 Continue, 203 Non-Authoritative Information, 305 Use Proxy, 306 (Unused), 400 Bad Request, 402 Payment Required, 403 Forbidden, 404 Not Found, 408 Request Timeout, 410 Gone, 411 Length Required, 412 Precondition Failed, 414 URI Too Long, 417 Expectation Failed, 418 (Unused), 422 Unprocessable Content, 500 Internal Server Error, 501 Not Implemented, 502 Bad Gateway, 504 Gateway Timeout. The 1xx class rules above still apply to 100, and the 4xx and 5xx class rules apply to the error codes in this list. 305 is deprecated, and 306 and 418 are reserved.
Heuristically cacheable status codes
A cache can reuse responses with these status codes using heuristic expiration, unless the method definition or explicit cache controls say otherwise: 200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414, 501. RFC 9110 section 15.1 says all other status codes are not heuristically cacheable.
Check a response
Send the request with the method the client used and read the headers. A 405 that follows RFC 9110 looks like this:
$ curl -si -X DELETE https://api.example.com/reports/42
HTTP/1.1 405 Method Not Allowed
Allow: GET, HEAD
The cURL command generator builds this kind of command for other methods and headers.
JSON data
https://httpstatuses.net/guides/status-code-response-obligations.json is generated from the same rows as this table. It has the 1xx, 4xx, and 5xx class rules, one entry for each covered status code with its rules and heuristic cacheability, the list of covered codes, and the codes that are not covered. Each rule looks like this:
{
"id": "405-allow",
"keyword": "MUST",
"role": "origin server",
"subject": "Allow",
"condition": null,
"rule": "Send Allow listing the methods the target resource supports now.",
"quote": "The origin server MUST generate an Allow header field in a 405 response containing a list of the target resource's currently supported methods.",
"source": "RFC 9110",
"section": "15.5.6",
"sourceURL": "https://www.rfc-editor.org/rfc/rfc9110.html#section-15.5.6",
"anchorURL": "https://httpstatuses.net/guides/status-code-response-obligations/#405-allow"
}
Rule IDs stay the same when wording changes, so a lint rule or test can point at 405-allow. condition is null when the rule always applies.
Coverage and sources
- Covered: the 50 status codes defined in RFC 9110 section 15 and RFC 6585, plus the POST and PUT rules in RFC 9110 that decide when a 201 is sent.
- Not covered: registered codes defined in other RFCs, which have their own rules: 102 (RFC 2518), 103 (RFC 8297), 207 (RFC 4918), 208 (RFC 5842), 226 (RFC 3229), 423 (RFC 4918), 424 (RFC 4918), 425 (RFC 8470), 451 (RFC 7725), 506 (RFC 2295), 507 (RFC 4918), 508 (RFC 5842), 510 (RFC 2774).
- Not covered: codes outside the IANA HTTP Status Code Registry, which have no standard rules: 509, 529, 530, 598, 599.
- Not covered: rules that apply to every response whatever the status, such as HEAD responses never including content (RFC 9110 §6.4.1), and the syntax of fields such as Retry-After.
- Each row quotes the RFC sentence it comes from, and the generator checks that each row's quote contains its keyword.
For the error body that goes with these headers, see the RFC 9457 Problem Details guide. To pick the status code first, use the REST API status code chooser.