HTTP Status Codes - DEV Community
#Backend

HTTP Status Codes - DEV Community

Backend Reporter
14 min read

HTTP status codes are the silent language of the web, communicating the outcome of client-server interactions. This article explores the hierarchy, semantics, and practical applications of these numeric responses, helping developers design more robust, intuitive APIs that communicate effectively with clients.

HTTP Status Codes: The Silent Language of the Web

HTTP status codes form the backbone of client-server communication on the web. These three-digit numerical responses provide immediate feedback about the outcome of HTTP requests, guiding clients on how to proceed. While often taken for granted, proper implementation of status codes is crucial for building reliable, debuggable, and user-friendly applications.

The HTTP status code system was first defined in HTTP/1.1 (RFC 2616) and has evolved with subsequent HTTP versions. The codes are grouped into five categories based on their first digit, each representing a different class of response:

  • 1xx: Informational responses
  • 2xx: Successful responses
  • 3xx: Redirection messages
  • 4xx: Client error responses
  • 5xx: Server error responses

For a complete reference, you can consult the official HTTP Semantics specification (RFC 7231) or the MDN documentation on HTTP status codes.

Informational Responses (1xx)

The 1xx class of status codes represents provisional responses. These are rarely used in modern web development but can be valuable in specific scenarios.

100 Continue: This status code indicates that the client should continue with its request. The server has received the initial part of the request and is waiting for the remainder. This is particularly useful when the client needs to send a large request body, as it can verify that the server is willing to accept the request before transmitting the entire payload.

101 Switching Protocols: Used when the client requests a protocol change (e.g., switching from HTTP to WebSocket). The server acknowledges the request and will communicate using the new protocol for the remainder of the connection.

102 Processing: This WebDAV extension indicates that the server has received and is processing the request, but no response is available yet. This prevents the client from timing out while waiting for a long-running operation to complete.

Successful Responses (2xx)

The 2xx status codes indicate that the client's request was successfully received, understood, and accepted.

200 OK: The most common status code, indicating a successful request. When used with GET, it means the requested resource was found and returned in the response body. For other methods like POST, PUT, or DELETE, it typically indicates that the request was processed successfully.

201 Created: Sent in response to a POST or PUT request when a new resource has been created. The response should include a Location header containing the URI of the newly created resource.

202 Accepted: Indicates that the request has been accepted for processing, but the processing has not been completed. This is useful for long-running operations where the client doesn't need to wait for completion. The server should provide a way for the client to check the status of the request.

203 Non-Authoritative Information: Similar to 200 OK, but the response is from a cached or third-party source rather than the origin server. The client should treat the response as authoritative but be aware that it might not be the most up-to-date version.

204 No Content: Indicates that the request was successful but there is no content to return. Commonly used with DELETE operations when a resource is successfully removed but there's no need to return the deleted resource's representation.

205 Reset Content: Similar to 204 No Content, but also instructs the client to reset the view that sent the request. This is useful for form submissions where the form should be cleared after successful submission.

206 Partial Content: Used in response to a Range request header, indicating that only part of the requested resource is being returned. This is essential for implementing resumable downloads or streaming media.

207 Multi-Status: A WebDAV extension that provides status information for multiple independent operations. The response body contains XML describing the status of each sub-request.

Redirection Messages (3xx)

The 3xx status codes indicate that further action is needed to complete the request. These are commonly used for URL redirections.

300 Multiple Choices: Indicates that the requested resource corresponds to multiple representations, each with its own URI. The client can choose which representation to use.

301 Moved Permanently: Indicates that the requested resource has been permanently moved to a new URI. Clients should update their bookmarks and use the new URI for future requests. Search engines will also update their indexes to point to the new location.

302 Found: A temporary redirect, indicating that the requested resource has been temporarily moved to a different URI. Clients should continue to use the original URI for future requests. This is often misused in place of 303.

303 See Other: Instructs the client to use a different method (typically GET) to retrieve the resource. The response should include a Location header with the new URI. This is particularly useful after a POST request.

304 Not Modified: Used with conditional GET requests to indicate that the resource has not been modified since the version specified in the If-Modified-Since or If-None-Match headers. The client can use its cached version of the resource.

305 Use Proxy: Indicates that the requested resource must be accessed through a proxy. The Location header contains the proxy's URI. This status code is deprecated due to security concerns.

307 Temporary Redirect: Similar to 302, but preserves the original request method. This is important when redirecting POST requests, as 302 may cause some clients to change the method to GET.

308 Permanent Redirect: Similar to 301, but preserves the original request method. This is useful for permanently redirecting endpoints that need to maintain the request method.

Client Error Responses (4xx)

The 4xx status codes indicate that the client seems to have made an error. These are crucial for providing clear feedback to API consumers.

400 Bad Request: Indicates that the server cannot process the request due to something that is perceived to be a client error. This is a general-purpose error that can cover various issues, such as malformed request syntax, invalid request message framing, or deceptive request routing.

401 Unauthorized: Indicates that the request lacks valid authentication credentials for the target resource. This is often confused with 403 Forbidden, but 401 specifically relates to authentication rather than authorization. The response should include a WWW-Authenticate header indicating the authentication scheme.

402 Payment Required: A non-standard status code that was originally intended for digital payment systems. It's rarely used in practice but could be implemented for APIs requiring payment.

403 Forbidden: Indicates that the server understood the request but refuses to authorize it. Unlike 401, the client has provided valid credentials, but those credentials don't have permission to access the requested resource.

404 Not Found: Indicates that the server cannot find the requested resource. This is one of the most well-known status codes, but it should be used carefully. For APIs, it's often better to return a more specific error code when a resource is not found.

405 Method Not Allowed: Indicates that the request method is not supported for the requested resource. The response should include an Allow header listing the supported methods.

406 Not Acceptable: Indicates that the server cannot produce a response matching the list of acceptable values defined in the request's Accept headers.

407 Proxy Authentication Required: Similar to 401, but specifically for proxy authentication. The response should include a Proxy-Authenticate header.

408 Request Timeout: Indicates that the server did not receive a complete request within the time it was prepared to wait. This can occur when the client closes the connection prematurely.

409 Conflict: Indicates that the request could not be completed due to a conflict with the current state of the target resource. This is commonly used in APIs for operations that would violate data integrity, such as creating a resource with a duplicate identifier.

410 Gone: Similar to 404, but indicates that the resource is permanently gone and will not be available again. This is useful for distinguishing between resources that have been moved (301) and those that no longer exist.

411 Length Required: Indicates that the server requires a Content-Length header in the request. This is typically used for methods that require a request body.

412 Precondition Failed: Indicates that one or more conditions in the request's If-None-Match or If-Unmodified-Since headers are not met.

413 Payload Too Large: Indicates that the request body is larger than the server is willing or able to process. The response should include a Retry-After header indicating when the client can retry.

414 URI Too Long: Indicates that the request's URI is longer than the server is willing to interpret.

415 Unsupported Media Type: Indicates that the server does not support the media type in the request's Content-Type header.

416 Range Not Satisfiable: Indicates that the client requested a range of the resource that is not satisfiable. This can occur when the client requests bytes beyond the end of the resource.

417 Expectation Failed: Indicates that the server cannot meet the requirements of the Expect request header.

421 Misdirected Request: Indicates that the server cannot produce the response because the request was directed to a server that cannot produce it.

422 Unprocessable Entity: A WebDAV extension that indicates the server understands the content type of the request body, but was unable to process the contained instructions. This is commonly used in APIs for validation errors.

423 Locked: Indicates the resource is locked and cannot be modified.

424 Failed Dependency: Indicates that the method could not be performed on the resource because the requested action on another resource failed.

425 Too Early: Indicates that the server is unwilling to risk processing a replayed request.

426 Upgrade Required: Indicates that the server refuses to service the request using the current protocol but is willing to do so after the client upgrades to a different protocol.

428 Precondition Required: Indicates that the server requires the request to be conditional.

429 Too Many Requests: Indicates the client has sent too many requests in a given amount of time. The response should include a Retry-After header.

431 Request Header Fields Too Large: Indicates that the server is unwilling to process the request because its header fields are too large.

451 Unavailable For Legal Reasons: Indicates that the server is denying access to the resource for legal reasons, such as censorship or government takedowns.

Server Error Responses (5xx)

The 5xx status codes indicate that the server failed to fulfill a valid request.

500 Internal Server Error: A general-purpose error message when the server encounters an unexpected condition. This should be used for errors that are not specifically covered by other 5xx status codes.

501 Not Implemented: Indicates that the server does not support the functionality required to fulfill the request. This is appropriate when the server doesn't recognize the request method or cannot fulfill any of the options.

502 Bad Gateway: Indicates that the server, while acting as a gateway or proxy, received an invalid response from an upstream server.

503 Service Unavailable: Indicates that the server is currently unable to handle the request. This is often used for maintenance or when the server is overloaded. The response should include a Retry-After header.

504 Gateway Timeout: Similar to 502, but indicates that the server did not receive a timely response from an upstream server.

505 HTTP Version Not Supported: Indicates that the server does not support the HTTP protocol version used in the request.

506 Variant Also Negotiates: Indicates that the server has an internal configuration error.

507 Insufficient Storage: Indicates that the server cannot store the representation needed to complete the request.

508 Loop Detected: Indicates that the server terminated an operation because it encountered an infinite loop while processing a request with "Depth: infinity".

510 Not Extended: Indicates that further extensions to the request are required for the server to fulfill it.

511 Network Authentication Required: Indicates that the client needs to authenticate to gain network access.

Best Practices for Using HTTP Status Codes

  1. Use specific status codes: Instead of always using 500 for server errors, use more specific codes like 503 for service unavailable or 502 for bad gateway.

  2. Include error details: While status codes provide a high-level indication of the problem, include error details in the response body to help clients understand what went wrong.

  3. Be consistent: Use the same status codes for similar errors across your API to make it easier for clients to handle them.

  4. Use appropriate redirection codes: Use 301 for permanent redirects and 307 for temporary redirects to avoid caching issues.

  5. Handle conditional requests properly: Implement 304 Not Modified for conditional GET requests to improve performance.

  6. Provide retry information: For rate limiting (429) or service unavailable (503) errors, include a Retry-After header.

  7. Use 422 for validation errors: When a request body contains validation errors, 422 Unprocessable Entity is more descriptive than 400 Bad Request.

  8. Use 409 for conflicts: When a request would create a conflict with the current state of the resource, use 409 Conflict.

  9. Document your status codes: Provide clear documentation about the status codes your API uses and their meanings.

  10. Consider using custom error codes: For complex APIs, consider using custom error codes in the response body to provide more detailed error information.

Common Pitfalls and How to Avoid Them

  1. Using 404 when 410 is more appropriate: If a resource has been permanently removed, use 410 Gone instead of 404 Not Found.

  2. Using 200 OK for errors: Avoid wrapping error responses in a 200 OK status. Use appropriate error status codes and include error details in the response body.

  3. Not providing enough error information: Status codes alone are often not enough to help clients understand what went wrong. Include descriptive error messages and, when appropriate, error codes.

  4. Inconsistent use of status codes: Use the same status codes for similar errors across your API to make it easier for clients to handle them.

  5. Ignoring conditional requests: Implement 304 Not Modified for conditional GET requests to improve performance and reduce bandwidth usage.

  6. Misusing 302 redirects: Use 307 Temporary Redirect instead of 302 when you need to preserve the request method.

  7. Not handling authentication properly: Use 401 for authentication errors and 403 for authorization errors. Don't use 403 when the client hasn't provided valid credentials.

  8. Overusing 500 errors: Reserve 500 for truly unexpected server errors. For expected errors like database connection failures, use more specific status codes.

  9. Not providing retry information: For rate limiting or service unavailable errors, include a Retry-After header to help clients handle the error.

  10. Not documenting status codes: Provide clear documentation about the status codes your API uses and their meanings.

Evolution of HTTP Status Codes

HTTP status codes have evolved with each version of the protocol:

  • HTTP/1.1 (RFC 2616) defined the original set of status codes.
  • HTTP/2 (RFC 7540) maintained backward compatibility with HTTP/1.1 status codes.
  • HTTP/3 (RFC 9110) continued the same status code system while improving the underlying transport.

Some status codes have been deprecated or replaced over time:

  • 305 Use Proxy is deprecated due to security concerns.
  • 505 HTTP Version Not Supported is rarely used as most servers support multiple versions.

New status codes have been added to address emerging needs:

  • 425 Too Early was added to prevent replay attacks.
  • 451 Unavailable For Legal Reasons was added to address censorship concerns.

For a deeper dive into REST API design patterns, including status code usage, check out this comprehensive guide.

As web APIs continue to evolve, we can expect to see:

  1. More granular status codes: As APIs become more complex, there may be a need for more specific status codes to address nuanced error conditions.

  2. Better error handling standards: More standardized ways to include error details in response bodies, making it easier for clients to handle errors consistently.

  3. Machine-readable error descriptions: Structured error formats that can be easily parsed by automated systems.

  4. Improved handling of asynchronous operations: Better status codes and patterns for handling long-running operations.

  5. Enhanced support for conditional requests: More sophisticated use of status codes like 304 to improve performance.

Conclusion

HTTP status codes are a fundamental aspect of web communication, providing a standardized way to indicate the outcome of HTTP requests. By understanding the semantics of each status code and using them appropriately, developers can build more robust, debuggable, and user-friendly APIs.

Remember that status codes are just one part of error handling. Combine them with descriptive error messages, proper documentation, and consistent patterns to create APIs that are easy to work with. As web technologies continue to evolve, staying informed about new status codes and best practices will help you design APIs that stand the test of time.

Comments

Loading comments...