HTTP Status Codes Reference
Browse and search all HTTP status codes with detailed descriptions. Filter by category (1xx-5xx) to quickly find the status code you need for web development and API debugging.
HTTP status codes are three-digit integer responses provided by a web server to indicate the outcome of a client's request. They serve as the foundational language of the internet, enabling browsers, applications, and search engines to understand whether a digital transaction succeeded, failed, or requires further action. By mastering these codes, developers and technical professionals will learn how to diagnose network issues, design robust Application Programming Interfaces (APIs), and ensure seamless digital experiences for users worldwide.
What It Is and Why It Matters
At its absolute core, the internet operates on a strict client-server model characterized by a continuous loop of requests and responses. When you open a web browser, mobile application, or any software that communicates over the network, that software acts as a "client." The client asks a remote computer, known as the "server," to perform a specific action, such as retrieving an image, saving a user profile, or deleting a message. An HTTP status code is the server's immediate, standardized summary of exactly what happened to that request. Instead of sending back a complex, human-readable paragraph explaining the outcome, the server transmits a simple three-digit number. For example, the number 200 universally means "everything went perfectly," while 404 universally means "the requested resource does not exist."
This concept exists to solve the fundamental problem of machine-to-machine communication at a massive, global scale. Without a standardized set of status codes, every single web application, browser, and server software would have to invent its own proprietary way of communicating success or failure. A Google Chrome browser would not inherently know how to handle an error from an Apache server, and search engine web crawlers would have no automated way to determine if a web page had been permanently moved or temporarily deleted. By utilizing a universal numeric system, HTTP status codes decouple the client's logic from the server's implementation. A 15-year-old building their first website and a senior engineer at Amazon Web Services both rely on the exact same numeric vocabulary.
Understanding these codes is not optional for anyone working in web development, network administration, or technical Search Engine Optimization (SEO). When an application fails, the HTTP status code is always the very first diagnostic clue. It immediately bifurcates the troubleshooting process: a code starting with a 4 tells the developer that the client sent a flawed request, while a code starting with a 5 indicates that the server itself crashed or encountered an internal fault. Furthermore, API developers rely on these codes to build intuitive, predictable interfaces for other programmers. If a developer submits a payment payload to Stripe's API, receiving a 201 status code provides absolute cryptographic certainty that the payment was created, triggering the next step in the checkout flow without requiring the developer to parse the actual text of the server's response.
History and Origin
The story of HTTP status codes is deeply intertwined with the invention of the World Wide Web itself. In 1989, Sir Tim Berners-Lee, a British computer scientist working at CERN (the European Organization for Nuclear Research) in Switzerland, proposed a system to help physicists share data across different computers. He invented the Hypertext Transfer Protocol (HTTP). However, the very first iteration of this protocol, retroactively named HTTP/0.9 and implemented in 1991, was incredibly primitive. It supported only a single command—GET—and had absolutely no concept of status codes or headers. The client would request a document, and the server would either stream the HTML text back or simply drop the connection if the document did not exist. There was no standardized way to communicate an error.
As the web rapidly expanded beyond academic circles, the need for a more robust communication protocol became glaringly obvious. In 1992, Berners-Lee, along with pioneers like Roy Fielding and Henrik Frystyk Nielsen, began drafting what would become HTTP/1.0. To solve the problem of communicating request outcomes, they looked to an older, battle-tested protocol: the File Transfer Protocol (FTP). Defined in RFC 959 back in October 1985, FTP already utilized a brilliant three-digit numeric system where the first digit indicated the broad category of the response (e.g., 2 for success, 4 for transient error, 5 for permanent error). The HTTP architects adopted this exact paradigm, adapting it for the stateless, hypermedia-driven nature of the web.
This standardized list of HTTP status codes was officially codified in May 1996 with the publication of RFC 1945. This seminal document defined the foundational codes that we still use today, including 200 OK, 301 Moved Permanently, 400 Bad Request, 404 Not Found, and 500 Internal Server Error. Three years later, in June 1999, the Internet Engineering Task Force (IETF) published RFC 2616, defining HTTP/1.1. This massive update expanded the status code vocabulary to accommodate complex caching mechanisms, range requests, and sophisticated proxy server interactions. Over the next two decades, the protocol continued to evolve. In June 2014, the IETF published RFC 7231 to clarify the semantics of these codes, and most recently, in June 2022, RFC 9110 consolidated the definitions of HTTP semantics for all versions of the protocol, including HTTP/2 and HTTP/3. Through 30 years of technological revolution, the three-digit status code system has remained remarkably unchanged, serving as a testament to the elegant foresight of the internet's early architects.
How It Works — Step by Step
To truly understand HTTP status codes, you must observe them in their natural habitat: the HTTP request-response cycle. This cycle is a meticulously choreographed sequence of network events. Let us assume a user types the URL https://api.example.com/users/123 into their browser and presses Enter. The process begins at the Network Layer. The browser first performs a Domain Name System (DNS) lookup to translate the human-readable domain api.example.com into an IP address, such as 192.0.2.45. Once the IP address is known, the client initiates a Transmission Control Protocol (TCP) handshake, sending a SYN packet, receiving a SYN-ACK, and sending a final ACK to establish a reliable connection. Because the URL uses https://, a Transport Layer Security (TLS) handshake follows to encrypt the connection. All of this happens in roughly 50 to 100 milliseconds before a single byte of HTTP data is exchanged.
With the secure connection established, the client formulates the actual HTTP request. This request consists of a method, a path, a protocol version, and a set of headers. In plain text, the raw request looks exactly like this:
GET /users/123 HTTP/1.1
Host: api.example.com
Accept: application/json
User-Agent: Mozilla/5.0
This text is transmitted across the internet to the server. The server software (such as Nginx, Apache, or a Node.js application) receives this text and begins processing. The server's routing logic identifies that the client wants the user data for ID 123. The application code queries the backend PostgreSQL database: SELECT * FROM users WHERE id = 123;.
Now, the server must formulate its response, and this is exactly where the HTTP status code is generated. If the database query successfully returns the user's data, the application logic instructs the web server to generate a success response. The server constructs the HTTP response, which always begins with the "Status Line." The Status Line consists of the protocol version, the three-digit status code, and a brief, human-readable reason phrase. The server then appends its own headers and the actual data (the body) requested by the client. The raw response sent back over the wire looks like this:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 85
Date: Mon, 15 May 2023 14:30:00 GMT
{"id": 123, "name": "Alice Smith", "email": "alice@example.com", "status": "active"}
The client receives this payload, reads the very first line, sees 200, and immediately knows the operation succeeded. If, however, the database had returned zero rows because user 123 had been deleted, the server application would have generated a different status line: HTTP/1.1 404 Not Found. The client parses this three-digit number and instantly knows to display an error screen to the user, without needing to parse the JSON body to figure out what went wrong.
Key Concepts and Terminology
To navigate the landscape of HTTP status codes, one must possess a fluent command of the surrounding network terminology. The first critical term is the Client. The client is the software application that initiates the communication. While most people associate clients with web browsers like Safari or Google Chrome, a client can also be a mobile app, a smart refrigerator, or a backend script written in Python making automated API calls. The counterpart to the client is the Server, a high-powered computer running specialized software designed to listen for incoming client requests, process them, and return the appropriate responses. The server is the authoritative entity that determines and issues the HTTP status code.
The communication itself is divided into two halves: the Request and the Response. The Request is the message sent from the client to the server, and it always includes an HTTP Method (also known as an HTTP Verb). The method tells the server what type of action the client wants to perform. The most common methods are GET (retrieve data), POST (create new data), PUT (replace existing data), PATCH (partially update data), and DELETE (remove data). The Response is the message sent back from the server, which always begins with the Status Line containing the three-digit status code.
Both requests and responses contain Headers and a Body (also known as a Payload). Headers are key-value pairs that provide metadata about the transaction. For example, the Content-Type: application/json header tells the receiving party that the body of the message is formatted as JSON. The User-Agent header tells the server exactly what kind of client (e.g., an iPhone running iOS 16) is making the request. The Body contains the actual data being transferred, such as the HTML code of a webpage, the binary data of a JPEG image, or the JSON string of a user profile. Finally, an Endpoint or URI (Uniform Resource Identifier) is the specific address the client is communicating with, such as https://api.example.com/v1/customers. The HTTP status code represents the final outcome of the interaction between the client, the specific method, and the specific endpoint.
Types, Variations, and Methods: The Five Classes
The architecture of HTTP status codes is brilliantly categorized by the very first digit of the three-digit number. This first digit defines the "class" or broad category of the response, while the remaining two digits provide specific granular details. There are exactly five official classes of HTTP status codes, ranging from 1xx to 5xx. This categorization ensures that even if a client encounters an obscure, unrecognized status code like 451, it can look at the first digit (4) and immediately understand the general nature of the situation (a client error).
1xx: Informational
Codes in the 100-199 range are purely informational. They indicate that the server has received the initial part of the request and is currently processing it, but the transaction is not yet complete. These are temporary, interim responses. The client should simply wait for the final response. The most common is 100 Continue, which a server sends when a client is about to upload a massive 5-gigabyte video file. The client first asks, "Are you willing to accept this massive file?" and the server replies 100 Continue, signaling the client to begin the heavy data transfer. Another is 101 Switching Protocols, used when a client asks to upgrade an HTTP connection to a continuous WebSocket connection.
2xx: Success
Codes in the 200-299 range indicate that the client's request was successfully received, understood, and accepted by the server. This is the desired outcome for any web transaction. 200 OK is the standard response for successful GET requests. 201 Created specifically indicates that a POST request successfully resulted in the creation of a new resource on the server, such as a new user account. 204 No Content is used when the request was successful, but there is absolutely no data to send back in the response body—commonly used after successfully executing a DELETE request.
3xx: Redirection
Codes in the 300-399 range inform the client that further action is required to complete the request. Usually, this means the requested resource has moved, and the server is telling the client where to find it. The server includes a Location header in the response containing the new URL. 301 Moved Permanently tells browsers and search engines that the old URL is dead and all traffic (and SEO ranking) should be forwarded to the new URL. 302 Found (or the more modern 307 Temporary Redirect) indicates the resource is temporarily located elsewhere, but the client should keep using the original URL for future requests. 304 Not Modified is a critical caching code; it tells the client, "The file hasn't changed since the last time you downloaded it, so just use your locally cached copy."
4xx: Client Error
Codes in the 400-499 range indicate that the client made a mistake. The request contains bad syntax, lacks proper authentication, or asks for something that does not exist. The server is essentially saying, "I understand what you want, but I cannot or will not process it because you did something wrong." 400 Bad Request means the client sent malformed data (e.g., passing text into a field that requires an integer). 401 Unauthorized means the client failed to provide valid authentication credentials (no API key). 403 Forbidden means the client is authenticated, but lacks the administrative permissions to access the resource. 404 Not Found is the most famous code on the internet, indicating the requested URL simply does not exist on the server. 429 Too Many Requests means the client has hit a rate limit and needs to slow down.
5xx: Server Error
Codes in the 500-599 range indicate that the client sent a perfectly valid request, but the server failed to fulfill it due to an internal fault. The server is admitting, "It's not you, it's me." 500 Internal Server Error is a generic catch-all indicating the server's backend code crashed or threw an unhandled exception. 502 Bad Gateway and 504 Gateway Timeout occur in modern microservice architectures; they indicate that an edge server (like a load balancer or reverse proxy) tried to communicate with a downstream backend server, but that backend server either returned an invalid response or took too long to reply. 503 Service Unavailable indicates the server is intentionally offline for maintenance or completely overwhelmed by traffic.
Real-World Examples and Applications
To bridge the gap between abstract protocol definitions and daily engineering tasks, let us examine how HTTP status codes dictate the flow of real-world applications. Consider a modern e-commerce checkout flow. A customer, Jane, adds a $1,200 laptop to her cart and clicks "Submit Order." Her browser sends an HTTP POST request to https://api.store.com/v1/orders containing her credit card token and shipping address in a JSON payload. The server receives this and begins processing. First, it checks the payload. If Jane's browser accidentally omitted her zip code, the server immediately halts and returns a 400 Bad Request. The frontend code reads the 400 status, parses the error message in the body, and highlights the zip code field in red on Jane's screen.
Assuming the payload is correct, the server attempts to charge the credit card via a third-party payment gateway like Stripe. If Jane's bank declines the card due to insufficient funds, the server returns a 402 Payment Required (a rarely used but semantically accurate code) or a 400 Bad Request with a specific error code in the body. If the payment succeeds, the server writes the new order to its database. Because a new resource (an order) has been successfully generated, the server responds with a 201 Created status code. It also includes a Location: /v1/orders/98765 header. Jane's browser sees the 201 and transitions her screen to the "Thank You for Your Purchase" page.
Another critical application of status codes is API Rate Limiting, a defensive mechanism used by companies to prevent abuse. Imagine a developer writing a Python script to scrape weather data from a public API. The API provider allows 60 requests per minute on their free tier. The developer's script loops too fast, sending 100 requests in 10 seconds. For the first 60 requests, the server returns 200 OK along with the weather data. On the 61st request, the server detects the threshold has been breached. Instead of processing the request, it immediately returns a 429 Too Many Requests status code. Crucially, the server also includes a Retry-After: 50 header. The developer's Python script is programmed to catch the 429 status code, read the Retry-After header, and automatically pause its execution for 50 seconds before attempting the 61st request again. This seamless, automated negotiation is entirely powered by standardized HTTP status codes.
Common Mistakes and Misconceptions
Despite the standardized nature of HTTP status codes, developers routinely make architectural mistakes that lead to brittle applications and debugging nightmares. The single most pervasive anti-pattern in modern web development is the "Always 200 OK" mistake. In this flawed design, a developer configures their API to return an HTTP 200 OK status code for every single request, even when a fatal error occurs. Instead of using the HTTP status code, they bury the error inside the JSON body, returning a payload like {"status": "error", "message": "User not found"}. This completely defeats the purpose of the HTTP protocol. Load balancers, caching layers, and monitoring tools like Datadog only look at the HTTP status code; they do not parse the JSON body. If an API returns 200 OK for database crashes, the monitoring systems will falsely report 100% uptime, and developers will be entirely blind to massive system failures.
Another frequent misconception revolves around the distinction between 401 Unauthorized and 403 Forbidden. Beginners often use them interchangeably, but they have strictly different semantic meanings. 401 Unauthorized actually means "Unauthenticated." It tells the client, "I do not know who you are. Please provide a valid API key or login token." The appropriate client reaction is to prompt the user to log in. Conversely, 403 Forbidden means "Unauthorized." It tells the client, "I know exactly who you are, but you do not have the administrative privileges required to view this file." If a client receives a 403, prompting the user to log in again will not help, because their identity is not the issue; their permission level is.
In the realm of SEO and marketing, a devastating mistake is the misuse of 301 and 302 redirects. When a company redesigns its website and changes its URL structure from example.com/about-us to example.com/company, they must redirect the old traffic. If a developer uses a 302 Found (Temporary Redirect), they are explicitly telling Google, "This page has moved for a few days, but keep the old URL in your search index." All the accumulated SEO authority (link equity) remains trapped at the old, dead URL. The new URL will start with zero authority and rank poorly. The developer must use a 301 Moved Permanently status code. The 301 explicitly commands Google to drop the old URL from its index and transfer 100% of the historical SEO ranking power directly to the new URL. Misunderstanding this single digit can cost a business millions of dollars in lost organic search traffic.
Best Practices and Expert Strategies
Professional software engineers treat HTTP status codes not as an afterthought, but as a critical component of their API contract. The gold standard for leveraging status codes is strict adherence to RESTful design principles. An expert developer maps CRUD (Create, Read, Update, Delete) operations to their mathematically correct status codes. A successful GET request must return 200 OK. A successful POST request that generates a database record must return 201 Created. A successful DELETE request should return 204 No Content, signaling the resource is gone and the server is saving bandwidth by sending an empty body. By adhering to this strict mapping, developers create predictable APIs. A frontend engineer integrating with a well-designed API doesn't need to read pages of documentation to know how to handle a deletion; the 204 status code tells them everything they need to know.
When returning 4xx or 5xx error codes, experts never return the status code in isolation. A status code tells the client that an error occurred, but it rarely provides enough context to explain why it occurred or how to fix it. Best practice dictates implementing RFC 7807, known as "Problem Details for HTTP APIs." This standard dictates that whenever an error status code is sent, the response body must contain a structured JSON object with specific fields: type (a URI identifying the error type), title (a short human-readable summary), status (mirroring the HTTP status code), and detail (a specific explanation of the exact occurrence). For example, instead of just sending a naked 400 Bad Request, an expert API sends the 400 status code alongside a payload detailing exactly which form field failed validation (e.g., {"title": "Validation Failed", "detail": "The 'age' parameter must be an integer greater than 18"}).
Furthermore, experts utilize status codes to optimize infrastructure costs and performance through aggressive caching strategies. By properly implementing 304 Not Modified, engineers can drastically reduce server load and bandwidth bills. When a client requests a 5-megabyte hero image, the server sends it with an ETag (Entity Tag) header—a unique cryptographic hash of the image file, such as ETag: "33a64df5". The next time the client asks for that image, it includes the header If-None-Match: "33a64df5". The server quickly hashes the image currently on its hard drive. If the hash is still "33a64df5", the server does not send the 5-megabyte file again. It simply sends a 0-byte response with the status code 304 Not Modified. This elegant use of status codes allows applications to load instantaneously for returning users while saving terabytes of outbound data transfer costs.
Edge Cases, Limitations, and Pitfalls
While the HTTP status code system is robust, it relies on the assumption that both the client and the server strictly adhere to the RFC specifications. When this assumption breaks down, severe limitations and edge cases arise. One major pitfall involves intermediary network layers—such as proxy servers, VPNs, and corporate firewalls—altering or swallowing status codes. For instance, some aggressive corporate firewalls intercept 403 Forbidden or 500 Internal Server Error responses from external servers and aggressively rewrite them into 200 OK responses containing a custom HTML error page ("This page has been blocked by IT"). To the client application, the network request appears completely successful (200 OK), causing the application to parse the IT department's HTML as if it were legitimate JSON data, resulting in catastrophic application crashes.
Another limitation is the lack of granularity in the official status code registry. There are only about 60 official status codes, which simply cannot cover every highly specific business logic error. For example, if a user tries to transfer money from a bank account that has been frozen due to suspected fraud, there is no official HTTP status code for "Account Frozen." Developers are forced to shoehorn this complex business state into a generic 403 Forbidden or 400 Bad Request, forcing the client to rely entirely on the custom JSON body to understand the nuance. This limitation has led major tech companies to invent unofficial, proprietary status codes. Cloudflare, a massive Content Delivery Network, invented the 52x range (e.g., 521 Web Server Is Down, 522 Connection Timed Out, 525 SSL Handshake Failed) to provide specific diagnostic information about failures between Cloudflare's edge nodes and the customer's origin server. Nginx, a popular web server, uses the unofficial 499 Client Closed Request to log when a user closes their browser tab before the server finishes processing.
Finally, one must acknowledge the internet's most famous edge case: 418 I'm a teapot. In April 1998, the IETF published RFC 2324, the "Hyper Text Coffee Pot Control Protocol" (HTCPCP), as an April Fools' Day joke. It stipulated that if a client attempts to brew coffee using a teapot, the teapot must respond with the 418 status code. Amusingly, this joke became deeply embedded in internet culture. Decades later, major backend frameworks like Node.js and Go officially implemented the 418 status code in their core HTTP libraries. While it is a harmless easter egg, it perfectly illustrates how the rigid standards of internet protocols occasionally intersect with human humor, creating permanent artifacts in the global network architecture.
Industry Standards and Benchmarks
The definitive authority on HTTP status codes is the Internet Assigned Numbers Authority (IANA), which maintains the official "Hypertext Transfer Protocol (HTTP) Status Code Registry." Any new status code must be proposed to the IETF, undergo rigorous peer review, and be officially published in a Request for Comments (RFC) document before it is added to the IANA registry. The current overarching standard governing the semantics of these codes is RFC 9110, published in June 2022. This document explicitly defines the mathematical boundaries of the five classes and outlines the exact conditions under which a server is legally allowed to issue a 206 Partial Content or a 415 Unsupported Media Type. Professional engineering teams treat RFC 9110 not as a suggestion, but as binding digital law.
In the realm of Site Reliability Engineering (SRE) and DevOps, HTTP status codes form the mathematical foundation for calculating Service Level Agreements (SLAs). Enterprise software companies publicly guarantee extreme levels of reliability, often promising "Four Nines" (99.99%) uptime. Uptime is not calculated by simply pinging a server to see if it is turned on; it is calculated by measuring the ratio of successful HTTP status codes to failed HTTP status codes. The industry standard formula for calculating API availability over a 30-day window is: (Total Requests - 5xx Responses) / Total Requests * 100.
For example, if an API processes exactly 10,000,000 requests in a month, and 1,500 of those requests result in a 500 Internal Server Error or a 503 Service Unavailable, the availability calculation is (10,000,000 - 1,500) / 10,000,000 * 100 = 99.985%. If the company's SLA guaranteed 99.99% uptime, they have breached their contract and must issue financial credits to their enterprise customers. Notice that 4xx client errors are entirely excluded from this benchmark. Industry standard dictates that if a client repeatedly sends malformed data and receives 400 Bad Request 50,000 times, that is the client's fault, not the server's fault. Therefore, monitoring systems like Prometheus and Grafana are configured to alert on-call engineers at 3:00 AM only when the rate of 5xx status codes breaches a specific threshold, completely ignoring spikes in 4xx codes.
Comparisons with Alternatives
While HTTP status codes are the undisputed standard for RESTful web architectures, they are not the only paradigm for communicating success and failure over a network. Comparing REST's use of HTTP status codes to alternative technologies like GraphQL and gRPC reveals fascinating architectural trade-offs. GraphQL, developed by Facebook, fundamentally rejects the granular use of HTTP status codes. In a standard GraphQL implementation, every single request—whether it succeeds flawlessly, fails validation, or encounters a catastrophic database crash—is sent as an HTTP POST and receives an HTTP 200 OK response. The actual success or failure state is entirely embedded within the JSON payload. A failed GraphQL request returns HTTP/1.1 200 OK with a body like {"data": null, "errors": [{"message": "Internal Server Error"}]}.
The advantage of the GraphQL approach is that clients only need to parse one thing: the JSON body. The massive disadvantage is that it completely breaks the internet's standard caching and monitoring infrastructure. A CDN like Cloudflare cannot cache a GraphQL error, because Cloudflare sees the 200 OK and assumes it is a successful payload. Network monitoring tools will show a 100% success rate even if the GraphQL API is internally failing every request. Developers using GraphQL must deploy specialized, application-layer monitoring tools (like Apollo Studio) to crack open the JSON payload of every request to calculate error rates, which requires significantly more computational overhead than simply reading a three-digit HTTP header.
Another major alternative is gRPC (gRPC Remote Procedure Calls), developed by Google for ultra-fast, internal microservice communication. gRPC operates over HTTP/2, but it intentionally bypasses standard HTTP status codes in favor of its own proprietary status model. gRPC defines exactly 17 integer status codes, numbered 0 through 16. For example, 0 means OK, 5 means NOT_FOUND, and 16 means UNAUTHENTICATED. These codes are transmitted in a specialized HTTP trailer header called grpc-status. The advantage of gRPC's system is that it is highly optimized for binary serialization (Protocol Buffers) and strictly limits the vocabulary to 17 highly specific states, eliminating the ambiguity developers face when choosing between the 60+ standard HTTP codes. However, gRPC is largely unsuitable for public-facing web applications; browsers cannot natively parse gRPC trailers, meaning an expensive proxy layer (like Envoy) is required to translate gRPC's 5 NOT_FOUND back into a standard HTTP 404 Not Found before the data reaches the user's web browser.
Frequently Asked Questions
What is the difference between a 401 Unauthorized and a 403 Forbidden?
A 401 Unauthorized status code indicates that the server does not know who the client is. The request lacks valid authentication credentials, such as a missing or expired JWT (JSON Web Token) or API key. The client should resolve this by logging in. A 403 Forbidden status code indicates that the server knows exactly who the client is, but the client does not have the proper authorization or administrative permissions to perform the requested action. Logging in again will not solve a 403; the user's account must be granted higher privileges by an administrator.
Does a 301 Redirect pass SEO link equity to the new page?
Yes, a 301 Moved Permanently status code is the industry standard method for preserving SEO rankings when changing URLs. When a search engine crawler like Googlebot encounters a 301, it understands that the old URL is permanently defunct. It will remove the old URL from the search index and transfer approximately 90% to 100% of the historical ranking power (link equity) to the new destination URL. Using a 302 Found (temporary redirect) instead will cause the search engine to keep the old URL indexed, failing to pass the ranking power to the new page.
Why am I seeing a 502 Bad Gateway error on my website?
A 502 Bad Gateway error occurs in environments where a proxy server (like Cloudflare, Nginx, or an AWS Application Load Balancer) sits in front of your actual backend application server (like a Node.js or Python process). The proxy server successfully received the client's request and forwarded it to your backend server. However, your backend server either crashed, was restarting, or returned a malformed response that the proxy could not understand. The proxy server therefore returns a 502 to the client. You must check the error logs of your backend application server to diagnose why it failed to respond properly to the proxy.
Can I invent my own custom HTTP status codes?
Technically, yes, but it is highly discouraged. The HTTP specification dictates that if a client receives an unrecognized status code, it must treat it according to its class (the first digit). If you invent a custom code 499, a browser will simply treat it as a generic 400 Bad Request. However, inventing custom codes violates standard protocol and will confuse third-party developers, monitoring tools, and caching layers that expect standard IANA-registered codes. If you need to communicate highly specific business logic errors, you should return a standard 400 or 422 status code and include a detailed, custom error code inside the JSON response body.
What is the difference between 503 Service Unavailable and 504 Gateway Timeout?
A 503 Service Unavailable means the server is actively rejecting requests. The server is alive and functioning enough to say, "I am too busy right now, or I am down for scheduled maintenance." It is an intentional, immediate rejection, often accompanied by a Retry-After header. A 504 Gateway Timeout, on the other hand, means a proxy server forwarded a request to a backend server, but the backend server took too long to respond. The proxy server waited for a predetermined amount of time (e.g., 30 seconds), gave up, and returned a 504 to the client. A 503 is an active refusal; a 504 is a failure due to latency.
Is it acceptable to return a 200 OK for a failed request?
No, returning a 200 OK for a failed request is a severe anti-pattern in RESTful API design. HTTP status codes exist specifically to leverage the infrastructure of the internet. If you return a 200 OK for a database error and put the error message in the JSON body, your CDN might cache that error page, your load balancer will think the server is perfectly healthy, and your automated alerting tools will fail to notify you of the outage. You must always use a 4xx code for client errors and a 5xx code for server errors to ensure network infrastructure functions correctly.