HTTP Status Codes
What the server is really telling you. All 64 registered codes plus the 10 vendor codes you meet in production, each with the causes behind it and what you do next.
| Code | Name | Meaning | Defined by |
|---|---|---|---|
| 100 | Continue | Keep going. The server has read the request headers and wants the body. | RFC9110 |
| 101 | Switching Protocols | The server is switching to another protocol, such as WebSocket, as the client asked. | RFC9110 |
| 102 | Processing | The server is still working on a long running request and has not finished. | RFC2518 |
| 103 | Early Hints | Early hints, sent before the real response so the browser can start preloading. | RFC8297 |
| 104 | Upload Resumption Supported | Provisional. Signals that the server supports resumable uploads. | draft-ietf-httpbis-resumable-upload-05provisional |
| Code | Name | Meaning | Defined by |
|---|---|---|---|
| 200 | OK | It worked. What that means depends on the method: a body for GET, a result for POST. | RFC9110 |
| 201 | Created | It worked and something new exists. The Location header points at it. | RFC9110 |
| 202 | Accepted | Accepted for processing, but not done yet. Nothing is guaranteed about the outcome. | RFC9110 |
| 203 | Non-Authoritative Information | It worked, but a proxy changed the response on the way, so treat it with care. | RFC9110 |
| 204 | No Content | It worked and there is deliberately no body to send back. | RFC9110 |
| 205 | Reset Content | It worked, and the client should clear the form or view that sent the request. | RFC9110 |
| 206 | Partial Content | Part of the resource, because the request asked for a byte range. | RFC9110 |
| 207 | Multi-Status | A body containing several separate status codes, one per sub operation. WebDAV. | RFC4918 |
| 208 | Already Reported | A member of a collection was already reported earlier in this response. WebDAV. | RFC5842 |
| 226 | IM Used | The response is the result of applying instance manipulations to the resource. | RFC3229 |
| Code | Name | Meaning | Defined by |
|---|---|---|---|
| 300 | Multiple Choices | Several representations exist and the client has to pick one. | RFC9110 |
| 301 | Moved Permanently | This URL has moved for good. Update your links. | RFC9110 |
| 302 | Found | This URL is temporarily somewhere else. Keep using the original. | RFC9110 |
| 303 | See Other | Look at a different URL with GET, typically after a form post. | RFC9110 |
| 304 | Not Modified | Nothing changed. Use the copy you already have in cache. | RFC9110 |
| 305 | Use Proxy | Deprecated. Told the client to use a proxy, and is no longer used. | RFC9110obsoleted |
| 306 | (Unused) | Reserved. Was defined in an earlier specification and is no longer used. | RFC9110unused |
| 307 | Temporary Redirect | Temporarily elsewhere, and the method must not change. The strict form of 302. | RFC9110 |
| 308 | Permanent Redirect | Permanently elsewhere, and the method must not change. The strict form of 301. | RFC9110 |
| Code | Name | Meaning | Defined by |
|---|---|---|---|
| 400 | Bad Request | The request itself is malformed and the server will not try to interpret it. | RFC9110 |
| 401 | Unauthorized | The server does not know who you are. Authenticate and try again. | RFC9110 |
| 402 | Payment Required | Reserved for payment. Rarely implemented, and never in a standard way. | RFC9110 |
| 403 | Forbidden | The server knows who you are and is refusing anyway. | RFC9110 |
| 404 | Not Found | The server has no resource at that URL and will not say whether it ever did. | RFC9110 |
| 405 | Method Not Allowed | The URL exists but not with that method. Check the Allow header. | RFC9110 |
| 406 | Not Acceptable | The server cannot produce anything the request's Accept headers will take. | RFC9110 |
| 407 | Proxy Authentication Required | Like 401, but the proxy in between is the one demanding credentials. | RFC9110 |
| 408 | Request Timeout | The client took too long to send the request and the server gave up waiting. | RFC9110 |
| 409 | Conflict | The request clashes with the current state, such as an edit against a stale version. | RFC9110 |
| 410 | Gone | Gone on purpose and not coming back. Stronger and rarer than 404. | RFC9110 |
| 411 | Length Required | The server refuses the request without a Content-Length header. | RFC9110 |
| 412 | Precondition Failed | A precondition in the request headers, such as If-Match, evaluated to false. | RFC9110 |
| 413 | Content Too Large | The request body is larger than the server is willing to process. | RFC9110 |
| 414 | URI Too Long | The URI is longer than the server is willing to interpret. | RFC9110 |
| 415 | Unsupported Media Type | The body's media type is not one this endpoint accepts. | RFC9110 |
| 416 | Range Not Satisfiable | The requested byte range lies outside the size of the resource. | RFC9110 |
| 417 | Expectation Failed | The Expect header asked for something the server cannot meet. | RFC9110 |
| 418 | I'm a teapot (unused) | Reserved and never to be implemented, because of the 1998 teapot joke. | RFC9110unused |
| 421 | Misdirected Request | This connection cannot serve that authority, so open a new one. | RFC9110 |
| 422 | Unprocessable Content | The syntax is fine but the content is semantically wrong, such as a failed validation. | RFC9110 |
| 423 | Locked | The resource is locked. WebDAV. | RFC4918 |
| 424 | Failed Dependency | The request failed because an earlier request it depended on failed. WebDAV. | RFC4918 |
| 425 | Too Early | The server will not risk replaying an early data request. | RFC8470 |
| 426 | Upgrade Required | The client must switch protocols, for example from HTTP to TLS. | RFC9110 |
| 428 | Precondition Required | The server requires a conditional request, to stop a blind overwrite. | RFC6585 |
| 429 | Too Many Requests | You are being rate limited. Slow down and honour Retry-After. | RFC6585 |
| 431 | Request Header Fields Too Large | The request headers are collectively or individually too large. | RFC6585 |
| 444 | No Response | nginx closes the connection without sending any response at all. | nginx |
| 451 | Unavailable For Legal Reasons | Access is denied for legal reasons, such as a court order. | RFC7725 |
| 499 | Client Closed Request | The client hung up before nginx could send a response. Logged, never sent. | nginx |
| Code | Name | Meaning | Defined by |
|---|---|---|---|
| 500 | Internal Server Error | The server hit an unexpected condition. This is the catch all failure. | RFC9110 |
| 501 | Not Implemented | The server does not support the functionality needed to fulfil the request. | RFC9110 |
| 502 | Bad Gateway | The server acted as a gateway and got an invalid response from upstream. | RFC9110 |
| 503 | Service Unavailable | The server cannot handle the request right now: overload or maintenance. | RFC9110 |
| 504 | Gateway Timeout | The server acted as a gateway and upstream did not answer in time. | RFC9110 |
| 505 | HTTP Version Not Supported | The HTTP version used in the request is not supported. | RFC9110 |
| 506 | Variant Also Negotiates | A content negotiation configuration error on the server. | RFC2295 |
| 507 | Insufficient Storage | The server has no room to store what the request needs. WebDAV. | RFC4918 |
| 508 | Loop Detected | The server detected an infinite loop while processing. WebDAV. | RFC5842 |
| 510 | Not Extended | Obsoleted. The request needed extensions the server does not support. | RFC2774Status change of HTTP experiments to Historicobsoleted |
| 511 | Network Authentication Required | You must authenticate with the network itself, typically a captive portal. | RFC6585 |
| 520 | Web Server Returns an Unknown Error | Cloudflare reached the origin but the answer made no sense to it. | Cloudflare |
| 521 | Web Server Is Down | Cloudflare could not open a connection to the origin at all. | Cloudflare |
| 522 | Connection Timed Out | Cloudflare's TCP connection attempt to the origin never completed. | Cloudflare |
| 523 | Origin Is Unreachable | Cloudflare cannot route to the origin at all. | Cloudflare |
| 524 | A Timeout Occurred | Cloudflare connected to the origin, but no response arrived in time. | Cloudflare |
| 525 | SSL Handshake Failed | The TLS handshake between Cloudflare and the origin did not complete. | Cloudflare |
| 526 | Invalid SSL Certificate | Cloudflare could not validate the origin's certificate. | Cloudflare |
| 530 | Cloudflare Error 1xxx | Always paired with a Cloudflare 1xxx error that carries the real detail. | Cloudflare |
Source: IANA HTTP Status Code Registry. Checked against that source on . Also drawn on: RFC 9110, HTTP Semantics. 74 codes, of which 64 are registered and 10 are vendor codes, dataset version 2.0.0. Changelog and JSON.
How to read HTTP status codes
Every HTTP response carries a three digit status code that summarizes the outcome of the request. The registered codes are maintained by the Internet Assigned Numbers Authority and defined mostly in RFC 9110, so their meanings are stable across every server and client on the web. The first digit is the most important part, because it groups codes into five classes that answer one question: did it work, and if not, whose fault is it.
A 2xx response means the request succeeded. A 3xx response asks the client to look somewhere else, usually a new URL. A 4xx response says the request itself was wrong, whether the syntax was malformed, the resource was missing, or the caller lacked permission. A 5xx response admits the server failed to handle a request that may have been perfectly valid. When you debug an API, reading the class first tells you which side of the connection to investigate.
Registered, unused, and vendor codes
Three of the codes in the table are listed by IANA but should never be returned. 306 was defined in an earlier specification and reserved, 305 is deprecated, and 418 is reserved precisely so that the teapot joke from RFC 2324 can never be given a serious meaning. The table labels each of them rather than quietly leaving them out, because people look them up. The vendor codes are the opposite case: they are not registered at all, but nginx and Cloudflare return them to real users every day, so leaving them out would make the table wrong in practice while being right on paper.
The pairs people mix up
Compare401 vs 403: authentication versus authorization
401 means the server does not know who you are, so authenticating will help. 403 means it knows exactly who you are and is refusing anyway, so authenticating again will not.
| 401 Unauthorized | 403 Forbidden | |
|---|---|---|
| Question it answers | Who are you? | Are you allowed? |
| Retry with credentials | Yes, that is the point | No, it will fail the same way |
| Required response header | WWW-Authenticate | None |
| Typical cause | Missing or expired token | Missing role, scope, or tenant |
301 vs 302 vs 307 vs 308: which redirect to return
Permanence runs down one axis and method preservation down the other. 301 and 308 are permanent, 302 and 307 are temporary. 307 and 308 guarantee the method survives the redirect, while 301 and 302 historically allowed clients to turn a POST into a GET.
| 301 | 302 | 307 | 308 | |
|---|---|---|---|---|
| Permanent | Yes | No | No | Yes |
| Method preserved | Not guaranteed | Not guaranteed | Yes | Yes |
| Cached by clients | Yes | No | No | Yes |
| Use it for | A move for good | A short detour | A short detour on POST | A move for good on POST |
Causes and fixes for the codes you actually hit
28 codesThe registry tells you what a code is called. It does not tell you why you are looking at one. These are the codes worth writing that down for, each with the situations that produce it, what to do, and the code it gets confused with.
This URL has moved for good. Update your links.
Common causes
- A page was moved and a permanent redirect was configured for the old URL.
- A site enforces a canonical host, such as apex to www, or http to https.
- A trailing slash convention rewrites one URL form to the other.
What to do Nothing, if the redirect is intended. If you are the one linking, update the link to the target so the hop disappears: clients and crawlers both cache a 301, and a chain of them costs latency on every request.
Confused with 302 Found, 308 Permanent Redirect
This URL is temporarily somewhere else. Keep using the original.
Common causes
- A framework default redirect after a login or a form submission.
- A temporary maintenance page or A/B split.
- A legacy handler that was meant to be permanent but was never changed to 301.
What to do Decide whether the move is temporary. If it is permanent, return 301 or 308 instead, because a 302 tells search engines to keep indexing the original URL. If the method must survive the redirect, use 307.
Confused with 301 Moved Permanently, 307 Temporary Redirect
Nothing changed. Use the copy you already have in cache.
Common causes
- The client sent If-None-Match and the ETag still matches.
- The client sent If-Modified-Since and the resource has not changed.
What to do This is the success case for caching, not an error. If you are seeing stale content, the cause is the caching headers on the original response, not the 304 itself.
Confused with 200 OK, 412 Precondition Failed
The request itself is malformed and the server will not try to interpret it.
Common causes
- Malformed JSON, or a body that does not match the declared Content-Type.
- A query parameter of the wrong type, such as a word where a number is required.
- A header the server cannot parse, sometimes from a stray newline in a generated value.
What to do Log and inspect the raw request, not your intent for it. Most 400s come from a serialiser producing something slightly different from what you assumed. If the syntax is valid and only the content is wrong, the correct code is 422.
Confused with 422 Unprocessable Content
The server does not know who you are. Authenticate and try again.
Common causes
- No Authorization header was sent at all.
- A token has expired, or was signed with a key the server no longer accepts.
- The credentials are for a different environment than the one you are calling.
What to do Authenticate and retry. A correct 401 carries a WWW-Authenticate header telling you which scheme to use. If retrying with valid credentials still fails, the server means 403 and is using the wrong code.
Confused with 403 Forbidden
The server knows who you are and is refusing anyway.
Common causes
- The authenticated user lacks the role or scope the endpoint requires.
- A firewall, WAF, or bot rule rejected the request before it reached the application.
- The resource exists but belongs to another tenant or account.
What to do Logging in again will not help, so check permissions rather than credentials. If the server would rather not reveal that the resource exists, 404 is the deliberate alternative.
Confused with 401 Unauthorized, 404 Not Found
The server has no resource at that URL and will not say whether it ever did.
Common causes
- The path is wrong, often a typo or a stale link.
- The resource was deleted and nothing was left in its place.
- A route exists in development but was not deployed, or a rewrite rule is missing.
What to do Check the exact path, including case and trailing slash. If the resource genuinely used to exist and is gone for good, 410 is more informative to clients and crawlers. If it moved, 301 to the new URL.
Confused with 410 Gone, 403 Forbidden
The URL exists but not with that method. Check the Allow header.
Common causes
- A POST sent to an endpoint that only defines GET.
- A preflight or a proxy rewrote the method.
- A route matches the path but registers a different method.
What to do Read the Allow header in the response: a correct 405 must list the methods the URL does support.
Confused with 404 Not Found, 501 Not Implemented
The request clashes with the current state, such as an edit against a stale version.
Common causes
- Two writes to the same record raced and the second was based on stale data.
- A uniqueness constraint would be violated, such as an email that already exists.
- A state machine was asked for a transition that is not legal from its current state.
What to do Re-read the current state and decide whether to merge or abandon the write. Preventing the race is better than handling it: use conditional requests with ETags, which lets the server answer 412 before anything is written.
Confused with 412 Precondition Failed, 422 Unprocessable Content
Gone on purpose and not coming back. Stronger and rarer than 404.
Common causes
- Content was intentionally removed and the operator wants that stated.
- A time limited resource, such as an expired export or share link.
What to do Nothing to fix on the client. As an operator, prefer 410 over 404 when you know the resource is permanently gone: search engines drop a 410 faster than a 404.
Confused with 404 Not Found
Reserved and never to be implemented, because of the 1998 teapot joke.
Common causes
- A joke endpoint, or a server deliberately signalling that a route is a decoy.
- A framework that implemented the 1998 April Fools specification for fun.
What to do Nothing. IANA lists 418 as reserved precisely so no one can assign it a real meaning. Do not build behaviour on it.
The syntax is fine but the content is semantically wrong, such as a failed validation.
Common causes
- A field failed validation, such as a date in the past where a future date is required.
- The payload parses but references something that does not exist.
- A business rule rejected an otherwise well formed request.
What to do Return and read the per field errors: a 422 without a body explaining which field failed is a wasted response. Use 400 only when the request could not be parsed at all.
Confused with 400 Bad Request, 409 Conflict
You are being rate limited. Slow down and honour Retry-After.
Common causes
- A client loop firing requests without any backoff.
- A shared API key used by several services at once.
- A burst limit that is much lower than the advertised hourly limit.
What to do Honour the Retry-After header if it is present, and back off exponentially with jitter if it is not. Retrying immediately is the one response that reliably makes it worse.
Confused with 503 Service Unavailable
nginx closes the connection without sending any response at all.
Common causes
- A return 444 rule used to drop malicious or unwanted traffic silently.
What to do Nothing arrives at the client, so this shows up as a dropped connection rather than a status code. Check the nginx configuration for an explicit return 444.
Access is denied for legal reasons, such as a court order.
Common causes
- A takedown order or court injunction covering the content.
- A geographic block imposed to comply with local law.
What to do Nothing technical. The specification asks the server to explain the legal demand in the response body.
Confused with 403 Forbidden
The client hung up before nginx could send a response. Logged, never sent.
Common causes
- A user navigated away or refreshed while the request was still running.
- A client side timeout that is shorter than the server's own processing time.
- A load balancer in front of nginx cancelling the request first.
What to do A rise in 499s usually means responses got slower, not that clients got impatient. Compare the 499 rate against your response time percentiles before changing any timeouts.
Confused with 408 Request Timeout
The server hit an unexpected condition. This is the catch all failure.
Common causes
- An unhandled exception in application code.
- A failed database connection or a query that timed out.
- A missing environment variable or configuration value in a fresh deployment.
What to do This is the code that tells you least, so go to the server logs and the request ID. If the failure is a dependency rather than your own code, 502, 503, or 504 describe it far better to the caller.
Confused with 502 Bad Gateway, 503 Service Unavailable
The server acted as a gateway and got an invalid response from upstream.
Common causes
- The upstream process crashed or is not listening on the expected port.
- The upstream returned a response the proxy could not parse.
- A protocol mismatch, such as a proxy speaking HTTP to a TLS only backend.
What to do Check whether the upstream is running and reachable from the proxy, not from your laptop. A 502 always means the proxy reached a conclusion about the backend, so its logs name the backend.
Confused with 503 Service Unavailable, 504 Gateway Timeout
The server cannot handle the request right now: overload or maintenance.
Common causes
- A deliberate maintenance window.
- Autoscaling has not caught up with a traffic spike.
- A health check is failing and the load balancer has no healthy targets.
What to do Look at capacity and health checks rather than application code. A well behaved 503 carries Retry-After, which is what lets clients back off instead of hammering.
Confused with 500 Internal Server Error, 504 Gateway Timeout
The server acted as a gateway and upstream did not answer in time.
Common causes
- An upstream request that takes longer than the gateway timeout.
- A slow query or a lock in the database behind the service.
- A chain of services where each hop has its own, shorter, timeout.
What to do Compare the timeouts along the whole chain: the smallest one wins, and it is usually not the one you tuned. Then attack the slow work itself, because raising a timeout only moves the failure later.
Confused with 502 Bad Gateway, 408 Request Timeout
Cloudflare reached the origin but the answer made no sense to it.
Common causes
- The origin returned an empty response or an oversized header.
- The origin connection was reset mid response.
What to do Reproduce the request straight against the origin, bypassing Cloudflare, and compare the raw response. A 520 means the origin answered, so the origin logs have the request.
Cloudflare could not open a connection to the origin at all.
Common causes
- The origin service is stopped.
- A firewall at the origin is blocking Cloudflare's IP ranges.
What to do Check that the origin is listening, and that its firewall allows the Cloudflare address ranges.
Cloudflare's TCP connection attempt to the origin never completed.
Common causes
- The origin is overloaded and not accepting new connections.
- Packets are being dropped between Cloudflare and the origin.
What to do Look at connection level metrics at the origin rather than application logs: in a 522 the request never became an HTTP request.
Confused with 524 A Timeout Occurred
Cloudflare cannot route to the origin at all.
Common causes
- A DNS record points at an address that no longer exists.
- A routing or network configuration change at the origin.
What to do Verify that the origin DNS records resolve to an address that is actually live.
Cloudflare connected to the origin, but no response arrived in time.
Common causes
- A long running request that exceeds the proxy timeout.
- A slow database query or an external call inside the request.
What to do Move the slow work to a background job and answer immediately with a job identifier. Raising the timeout only delays the same failure.
Confused with 504 Gateway Timeout, 522 Connection Timed Out
The TLS handshake between Cloudflare and the origin did not complete.
Common causes
- The origin has no certificate for the requested hostname.
- No cipher suite is shared between the two ends.
What to do Check the origin certificate and the SSL mode configured in Cloudflare; a mismatch between the two is the usual cause.
Confused with 526 Invalid SSL Certificate
Cloudflare could not validate the origin's certificate.
Common causes
- The origin certificate has expired.
- The certificate is self signed while strict validation is switched on.
What to do Renew or replace the origin certificate, or switch the SSL mode to one that matches it.
Confused with 525 SSL Handshake Failed
Always paired with a Cloudflare 1xxx error that carries the real detail.
Common causes
- Any of the Cloudflare 1xxx conditions, which vary widely.
What to do Read the 1xxx code shown with the 530. The 530 alone carries no diagnosis and looking it up on its own is a dead end.
Frequently asked questions
FAQHow many HTTP status codes are there?
The IANA HTTP Status Code Registry lists 64 assigned codes. On top of those, a handful of codes are returned by widely deployed software without ever being registered, such as 499 from nginx and 520 to 526 from Cloudflare. This page carries all 64 registered codes and 10 vendor codes, and labels which is which.
What do the HTTP status code classes mean?
The first digit sets the class. 1xx is informational, 2xx means success, 3xx is redirection, 4xx is a client error such as a bad request, and 5xx is a server error. Knowing the class alone tells you whether the problem is on your side or the server's.
What is the difference between 401 and 403?
A 401 Unauthorized means you are not authenticated, so the server does not know who you are and you should log in. A 403 Forbidden means the server knows who you are but you are not allowed to access the resource, so logging in again will not help.
When should I use 301 versus 302?
Use 301 Moved Permanently when a URL has changed for good, because clients and search engines will update their links and cache the redirect. Use 302 Found, or better 307, for a temporary move where the original URL will return.
What does a 429 status code mean?
429 Too Many Requests means you have been rate limited. The response often includes a Retry-After header telling you how long to wait. Back off, slow your request rate, and retry after the suggested delay.
Is 418 I'm a teapot a real status code?
It is real in the sense that IANA lists it, but it is registered as unused. It comes from RFC 2324, a 1998 April Fools specification for a coffee pot protocol, and RFC 9110 reserves the number so it can never be assigned a serious meaning. Do not build behaviour on it.
Put this table on your own page
EmbedPaste this anywhere. It loads a plain, self contained version of the table with a credit line underneath. Free under CC BY 4.0, and that credit line is the whole condition.