HTTP Status Codes Reference_

Every HTTP status code, searchable by number or phrase, with what it means, what causes it, and what to do about it. All 63 codes in the IANA registry are here, and so are 24 vendor codes you meet in production logs but cannot look up in a specification — Cloudflare's 52x family, nginx's 499, Laravel's 419 — each labelled with who invented it.

Type 404, type redirect, or press a class chip and read the whole family. Every entry has a permanent address: /http-status-codes#404 goes straight to it.

toolkit.codes/http-status-codes

87 of 87 codes · 63 registered, 24 vendor

100Continue

The server has read your request headers and is willing to receive the body. Sent only when the client asked first by including an Expect: 100-continue header.

Why you are seeing it
  • A client uploading a large body that checks before sending it
  • curl sending an Expect header automatically on bodies above 1 KB
What to do

Nothing to fix — it is a green light. If a proxy chokes on it, send Expect: with an empty value to suppress the ask.

101Switching Protocols

The server is switching this connection to a different protocol at your request. In practice this means a WebSocket handshake succeeding.

Why you are seeing it
  • A WebSocket upgrade
  • An HTTP/2 upgrade over cleartext
102Processing

A WebDAV holding message: the request is being processed and will take a while, so no timeout please. Rare outside WebDAV servers.

Why you are seeing it
  • A long-running WebDAV method such as a deep COPY or MOVE
RFC 2518compare 103
103Early Hints

An early answer sent before the real response, carrying Link headers so the browser can start fetching stylesheets and fonts while the server is still thinking. A performance mechanism, not a result.

Why you are seeing it
  • A server sending preload hints ahead of a slow page render
RFC 8297compare 100
200OK

It worked, and the body is the result. The default answer for a successful GET, and for a POST or PUT that returns content.

Why you are seeing it
  • Any request the server understood and fulfilled
201Created

It worked and something new exists because of it. The response should carry a Location header pointing at the new resource.

Why you are seeing it
  • A POST that created a record
  • A PUT to a URL that did not previously exist
What to do

If you are the one returning it, include Location — clients look for it and a 201 without one is a half-answer.

202Accepted

The request was accepted for processing, which has not happened yet and might still fail. An honest answer from an asynchronous API, and a promise you must give the client a way to check on.

Why you are seeing it
  • A job queued for a worker
  • A batch import handed to a pipeline
What to do

Return a status URL the client can poll, or the 202 tells them nothing they can act on.

203Non-Authoritative Information

It worked, but a proxy modified the body on the way to you — the payload is not exactly what the origin sent. Almost never seen deliberately.

Why you are seeing it
  • A transforming proxy compressing images or stripping content
204No Content

It worked and there is deliberately nothing to send back. The correct answer to a successful DELETE, and to a PUT the client already has the state for.

Why you are seeing it
  • A DELETE that succeeded
  • A form submission with no result page
What to do

Never send a body with a 204 — it has no length and clients are entitled to stop reading.

205Reset Content

It worked, and the client should clear the form or view that sent the request. A UI instruction rather than a data answer.

Why you are seeing it
  • A data-entry form designed for repeated submission
206Partial Content

Here is the slice of the resource you asked for, not the whole thing. The basis of resumable downloads and video seeking.

Why you are seeing it
  • A Range request
  • A download resuming after a break
  • A media player seeking
What to do

Check Content-Range in the response before assuming which bytes you got.

207Multi-Status

A WebDAV multi-status: the request touched several resources and the XML body reports a separate status for each. The 207 itself tells you nothing about success.

Why you are seeing it
  • A WebDAV PROPFIND or a batch operation across a collection
What to do

Parse the body. A 207 with three 200s and a 423 inside is a partial failure wearing a success code.

RFC 4918compare 208
208Already Reported

Inside a WebDAV multi-status body: this resource was already reported earlier in the same response, so its properties are not repeated. A deduplication marker.

Why you are seeing it
  • A recursive WebDAV listing that meets the same binding twice
RFC 5842compare 207
226IM Used

The response is the result of applying delta encodings to the resource rather than the resource itself. Effectively unused on the public web.

Why you are seeing it
  • An A-IM request against a server that implements RFC 3229
RFC 3229compare 200
300Multiple Choices

Several representations exist and the server will not choose for you. Rarely implemented, because a server that cannot pick usually has a design problem instead.

Why you are seeing it
  • Content negotiation with no acceptable default
301Moved Permanently

This URL has moved for good; use the new one from now on. Clients and search engines are entitled to remember it, which makes a mistaken 301 expensive to undo.

Why you are seeing it
  • A site restructure
  • Forcing HTTPS or a canonical hostname
  • A slug rename
What to do

Be certain before you send one, and set an explicit Cache-Control — browsers cache 301s aggressively and by default indefinitely. Use 308 if the request method must survive.

302Found

Go here instead, but keep asking the original URL next time. The historical catch, still baked into every browser: a 302 on a POST is turned into a GET, which is not what the spec says and not always what you want.

Why you are seeing it
  • Post-then-redirect flows
  • Temporary maintenance pages
  • Login redirects
What to do

If the method must be preserved, use 307. If you meant "the result is elsewhere, go GET it", 303 says so explicitly.

303See Other

Your request was handled; the answer is at this other URL, and you should GET it. The method change is intentional here, which is exactly what distinguishes it from 307.

Why you are seeing it
  • The redirect after a successful POST, so a refresh does not resubmit
304Not Modified

Your cached copy is still current — no body sent, save the bandwidth. Triggered by a conditional request carrying If-None-Match or If-Modified-Since.

Why you are seeing it
  • A browser revalidating with an ETag
  • A CDN checking freshness with the origin
What to do

If you see 304 when content has genuinely changed, your ETag is not changing with the content — usually a build that reuses a hash or an mtime that does not move.

305Use Proxy

Deprecated and ignored: it told the client to repeat the request through a specific proxy. Browsers refuse it because an attacker who can inject one can route your traffic.

Why you are seeing it
  • Essentially nothing — it is dead
306(Unused)

Reserved and unusable. It was defined in an early HTTP/1.1 draft, withdrawn, and the number is kept reserved so nothing else can claim it.

Why you are seeing it
  • Nothing. If you are emitting a 306, something is generating status codes by arithmetic
307Temporary Redirect

Go here instead this time, and do it with the same method and body you used originally. The version of 302 that behaves as written — a POST stays a POST.

Why you are seeing it
  • A temporary move where the request is not a plain GET
  • HSTS-style forced upgrades
308Permanent Redirect

The permanent partner of 307: moved for good, and the method survives. Introduced because 301 in the wild silently rewrites POST to GET and nothing could be done about that without a new number.

Why you are seeing it
  • A permanent move of an endpoint that accepts POST or PUT
What to do

Prefer 308 over 301 for API endpoints; prefer 301 for pages, where the wider client support matters more.

400Bad Request

The server could not make sense of the request itself — malformed syntax, not a permission or logic problem. The generic 4xx, and often the laziest one.

Why you are seeing it
  • Malformed JSON in the body
  • An unencoded character in the query string
  • A header the parser rejected
  • A framework validation failure returned without a more specific code
What to do

Read the response body: a well-built API says which field failed. If the query string is the suspect, percent-encode the values properly. Prefer 422 when the syntax was fine but the content was not.

401Unauthorized

You are not authenticated — the server does not know who you are, or the credentials you sent were rejected. The name says "Unauthorized" and it has misled developers for thirty years; it means unauthenticated. It must carry a WWW-Authenticate header saying how to authenticate.

Why you are seeing it
  • A missing or malformed Authorization header
  • An expired token
  • A signature that does not verify
  • A session cookie the server no longer recognises
What to do

Authenticate and retry. If you are designing the API: 401 says "log in"; 403 says "logging in will not help". Sending 401 for a permission failure sends clients into a retry loop.

402Payment Required

Reserved for payment and never standardised into anything interoperable. Some APIs now use it for "your plan does not cover this" or "the account is in arrears", which is a reasonable reading of a number the spec left open.

Why you are seeing it
  • A metered API on an unpaid account
  • A quota tied to billing rather than rate limits
403Forbidden

The server knows who you are and you still may not do this. Authenticating again will not change the answer, which is the whole difference from 401.

Why you are seeing it
  • An authenticated user without the required role
  • File permissions on the server
  • A directory with no index and listing disabled
  • A WAF or geo-block rejecting the request
What to do

Check the permission model, not the credentials. If a 403 is also intended to conceal existence, return 404 instead — a 403 confirms the resource is there.

404Not Found

Nothing is at this URL. It says nothing about whether the resource ever existed or ever will — which is what makes it both the safest error and the least informative.

Why you are seeing it
  • A typo or stale link
  • A route that never matched
  • A deployment that dropped a file
  • A deliberate 404 hiding a resource from someone not allowed to know it exists
What to do

For content that has genuinely been removed, 410 says so and is honest with crawlers. For a moved page, 301 is the answer — leaving a 404 loses whatever the old URL had earned.

405Method Not Allowed

The URL exists but not with that verb — a POST to a read-only endpoint, a DELETE where only GET is implemented. The response must list the methods that do work in an Allow header.

Why you are seeing it
  • A client using the wrong verb
  • A route defined for GET only
  • A CORS preflight OPTIONS the server does not handle
What to do

Read the Allow header. If OPTIONS is the failing method, the server is missing preflight handling rather than the real route.

406Not Acceptable

The server has the resource but cannot produce it in any form your Accept header will take. Genuinely rare, because most servers send their default and let the client cope.

Why you are seeing it
  • An Accept header restricted to a type the server does not produce
  • Over-strict content negotiation
What to do

Loosen Accept, or drop it — an absent Accept means "anything".

407Proxy Authentication Required

Like 401, but the challenge comes from a proxy between you and the server rather than from the server. Carries Proxy-Authenticate instead of WWW-Authenticate.

Why you are seeing it
  • A corporate proxy requiring credentials
  • An authenticated egress gateway
What to do

Supply Proxy-Authorization. If you did not know a proxy was involved, that is the more interesting finding.

408Request Timeout

The client took too long to send the request and the server gave up waiting. Note the direction: this is the request being slow, not the response.

Why you are seeing it
  • An idle keep-alive connection the server reclaimed
  • A slow or stalled upload
  • A client that opened a connection and sent nothing
What to do

Usually safe to retry. Persistent 408s on uploads point at a body larger or slower than the server's timeout allows.

409Conflict

The request is valid but conflicts with the current state — an edit against a version that has since moved, a name already taken, two writers racing.

Why you are seeing it
  • Optimistic concurrency detecting a stale version
  • A duplicate unique key
  • A git-style push against a changed head
What to do

Re-read the current state, merge, and retry. Blind retries produce the same conflict.

410Gone

It was here and it is deliberately gone, permanently. Stronger and more useful than 404 because it is a statement of intent — crawlers drop a 410 faster than they drop a 404.

Why you are seeing it
  • Content withdrawn on purpose
  • An expired campaign URL
  • A deleted account
What to do

Use it when you know the removal is permanent; leave 404 for "no idea".

411Length Required

The server refuses a request whose body has no declared length. Almost always a chunked-encoding mismatch rather than a client forgetting a header.

Why you are seeing it
  • A body sent without Content-Length to a server that requires it
  • Chunked transfer to an endpoint that will not accept it
What to do

Buffer the body and send Content-Length.

412Precondition Failed

A precondition you attached to the request was false, so the server did nothing. The safety net that makes conditional writes safe.

Why you are seeing it
  • If-Match against an ETag that has moved on
  • If-Unmodified-Since on a resource that changed
What to do

Fetch the current representation, reconcile, and retry with the new validator. A 412 means your write was correctly refused, not that it broke.

413Content Too Large

The body is bigger than the server is willing to accept. Frequently the proxy in front of the application, not the application.

Why you are seeing it
  • An upload above the configured limit
  • nginx client_max_body_size
  • A gateway body cap in front of a service that would have accepted it
What to do

Check the proxy limit before the application's. If the response carries Retry-After, the limit is temporary.

RFC 9110 §15.5.14also called Payload Too Large, Request Entity Too Largecompare 414, 431, 411
414URI Too Long

The URL itself is too long. There is no limit in the spec, so this is entirely about what your server and the intermediaries were built to buffer.

Why you are seeing it
  • A GET carrying data that belonged in a body
  • A redirect loop appending parameters each time
  • A very long filter or search query string
What to do

Move the payload into a POST body.

RFC 9110 §15.5.15also called Request-URI Too Longcompare 413, 431
415Unsupported Media Type

The server understands the request but not the format the body arrived in — usually a Content-Type it does not accept, or one that does not match the actual bytes.

Why you are seeing it
  • Posting form-encoded data to a JSON-only endpoint
  • A missing Content-Type
  • An upload whose declared type does not match its content
What to do

Set Content-Type to what the endpoint documents. If you are unsure which type a file should declare, look it up rather than guessing.

416Range Not Satisfiable

The byte range you asked for does not exist in the resource — past the end, or reversed.

Why you are seeing it
  • A resumed download whose local file is longer than the remote one
  • A hand-written Range header
What to do

Ask for the whole resource, read its length, then range within it.

417Expectation Failed

The server will not meet the Expect header you sent. In practice this means it does not implement 100-continue and an intermediary passed the expectation on anyway.

Why you are seeing it
  • Expect: 100-continue reaching a server or proxy that refuses it
What to do

Send the request without the Expect header.

418(Unused)

A joke from a 1998 April Fools RFC about coffee pots, kept alive by developers and by servers that use it to turn away bots. IANA keeps 418 reserved precisely so nothing serious can claim it, which is why the registry calls it "(Unused)" rather than "I'm a Teapot".

Why you are seeing it
  • A deliberate joke endpoint
  • Some CDNs and WAFs answering automated traffic
RFC 9110 §15.5.19also called I'm a Teapotcompare 403, 429
419Page ExpiredLaravel

Laravel's CSRF token check failed — the token in the form no longer matches the session. Not an HTTP standard, just a framework picking an unused number.

Why you are seeing it
  • A form left open until the session expired
  • A cached page serving a stale token
  • A session driver losing state between requests
What to do

Reload the form to get a fresh token. If it recurs for everyone, the session store or the page cache is the suspect.

420Enhance Your CalmTwitter API v1

Twitter's rate-limit code before 429 was standardised, named after a line in Demolition Man. Spring once used the same number for "Method Failure", which is why 420 in a log needs context before it means anything.

Why you are seeing it
  • Legacy Twitter API clients exceeding a rate limit
What to do

Back off. Modern APIs use 429 for this.

421Misdirected Request

The request reached a server that is not configured to answer for that hostname. An HTTP/2 artefact: connections get reused across hostnames that resolve to the same address, and sometimes the far end disagrees.

Why you are seeing it
  • HTTP/2 connection coalescing across certificates
  • A misrouted virtual host
What to do

Retry on a fresh connection; the spec explicitly permits it.

422Unprocessable Content

The syntax parsed fine and the content is still wrong — a well-formed JSON body with an email that is not an email, or a date in the past where the future was required. The precise code for validation failures, which is why so many APIs reach for 400 instead and lose the distinction.

Why you are seeing it
  • Schema validation failing on a syntactically valid body
  • Business rules rejecting a plausible request
What to do

Return which fields failed and why. A bare 422 is barely better than a 400.

RFC 9110 §15.5.21also called Unprocessable Entitycompare 400, 409
423Locked

The resource is locked — a WebDAV concept, and increasingly a general one for "someone else is editing this".

Why you are seeing it
  • A WebDAV LOCK held by another client
  • An application-level edit lock
RFC 4918compare 409, 424
424Failed Dependency

This step failed because an earlier one did. The request itself was fine; its dependency was not.

Why you are seeing it
  • A WebDAV operation in a batch whose predecessor failed
  • A workflow step gated on a prior call
RFC 4918compare 423, 409
425Too Early

The server will not risk processing a request that arrived in TLS 1.3 early data, because early data can be replayed by an attacker.

Why you are seeing it
  • A 0-RTT request carrying a non-idempotent method
What to do

Retry once the handshake completes. Do not send state-changing requests in early data.

RFC 8470compare 400
426Upgrade Required

The server refuses this request over the current protocol but would accept it over an upgraded one, named in the Upgrade header.

Why you are seeing it
  • A plaintext HTTP/1.1 request to an endpoint requiring TLS or HTTP/2
428Precondition Required

The server requires your write to be conditional and yours was not. It is refusing to let you overwrite blindly, which prevents the lost-update problem.

Why you are seeing it
  • A PUT without If-Match to an API that mandates optimistic concurrency
What to do

GET the resource, take its ETag, and resend with If-Match.

RFC 6585compare 412, 409
429Too Many Requests

You have sent too many requests in too short a window. Should carry Retry-After telling you how long to wait.

Why you are seeing it
  • A client without backoff
  • Shared rate limits across a whole team's API key
  • A retry storm amplifying an outage
What to do

Honour Retry-After. If it is absent, back off exponentially with jitter — synchronised retries are how a rate limit becomes an outage.

RFC 6585compare 503, 403
430Request Header Fields Too LargeShopify

Shopify's variant of 431, used when too many headers arrive or a security rule rejects the request. Shopify also documents it as a security rejection, so the same number covers two situations.

Why you are seeing it
  • Oversized cookies on a Shopify storefront
  • A request tripping Shopify's protection rules
What to do

Trim cookies and headers; if that does not help, the security path is the one that fired.

431Request Header Fields Too Large

The headers are too large, either one of them or all of them together. Cookies are almost always the culprit.

Why you are seeing it
  • Cookie accumulation on a shared domain
  • An oversized Authorization or Referer header
  • A tracking cookie set on every subdomain
What to do

Clear cookies for the domain to confirm, then trim what is being set. The failing header is often not the one your request added.

RFC 6585compare 413, 414
440Login Time-outMicrosoft IIS

The session expired and IIS wants you to authenticate again. Common in SharePoint and older ASP.NET applications.

Why you are seeing it
  • An idle session timing out
  • An authentication cookie expiring mid-workflow
What to do

Log in again. Persistent 440s point at a session timeout shorter than the work takes.

444No Responsenginx

nginx closed the connection without answering at all. It never travels over the wire — it only ever appears in nginx's own logs, as a record of a deliberate hang-up.

Why you are seeing it
  • A `return 444;` rule dropping malicious or unwanted traffic
  • A default server block silently discarding unmatched hosts
What to do

Nothing to fix if it is deliberate. If your own client is getting it, you are matching a block rule.

449Retry WithMicrosoft IIS

The server wants the request repeated after the client supplies more information. A Microsoft extension that never spread beyond it.

Why you are seeing it
  • A Microsoft service asking for additional parameters
450Blocked by Windows Parental ControlsMicrosoft

Windows content filtering blocked the request before it reached the network. A local policy decision reported as an HTTP status.

Why you are seeing it
  • A family-safety policy on the machine
What to do

Adjust the policy on the device — the server never saw the request.

451Unavailable For Legal Reasons

Access is blocked for legal reasons — a court order, a takedown, a sanctions regime. Numbered after Fahrenheit 451, deliberately.

Why you are seeing it
  • Geo-blocking for regulatory compliance
  • A DMCA or court-ordered removal
  • Sanctions screening
What to do

Nothing technical. The response should identify who imposed the restriction via a Link header with rel="blocked-by".

RFC 7725compare 403, 410
460Client Closed ConnectionAWS Elastic Load Balancing

The load balancer had a response ready and the client had already gone. AWS's counterpart to nginx's 499.

Why you are seeing it
  • A user navigating away from a slow page
  • A client timeout shorter than the backend's response time
What to do

Look at backend latency: 460s cluster around responses slower than clients are willing to wait for.

463Too Many X-Forwarded-For IPsAWS Elastic Load Balancing

The request arrived carrying more than 30 addresses in X-Forwarded-For, which ALB refuses.

Why you are seeing it
  • Chained proxies each appending an address
  • A forwarding loop
What to do

Find the proxy chain. More than a handful of hops usually means a loop rather than a topology.

494Request Header Too Largenginx

nginx's internal code for oversized headers, logged before the standard 431 is returned.

Why you are seeing it
  • Cookies exceeding large_client_header_buffers
  • A very long query string in the request line
What to do

Raise large_client_header_buffers, or trim what is being sent.

nginx docscompare 431
495SSL Certificate Errornginx

A client certificate was presented and failed verification. Only appears where mutual TLS is configured.

Why you are seeing it
  • An expired or revoked client certificate
  • A certificate signed by a CA the server does not trust
What to do

Check the client certificate chain and expiry against the server's trusted CA list.

nginx docscompare 496
496SSL Certificate Requirednginx

Mutual TLS is required and the client presented no certificate at all.

Why you are seeing it
  • A client not configured for mTLS reaching an mTLS endpoint
What to do

Configure the client certificate. Note the difference from 495: nothing was presented, rather than something invalid.

nginx docscompare 495
497HTTP Request Sent to HTTPS Portnginx

A plaintext request arrived on a port expecting TLS. The server can read enough to say so rather than dropping the connection.

Why you are seeing it
  • A client using http:// against an https:// port
  • A health check missing the scheme
What to do

Use https://, or configure a redirect on the plaintext port.

498Invalid TokenEsri ArcGIS

An ArcGIS token is expired or malformed. Esri's own numbering, paired with 499 for a missing token in the same product.

Why you are seeing it
  • An expired ArcGIS token
What to do

Request a new token.

499Client Closed Requestnginx

The client disconnected before nginx could answer. Like 444, it exists only in the log — nobody ever received it, because there was nobody left to receive it.

Why you are seeing it
  • A user cancelling or navigating away
  • A client timeout shorter than the server's response time
  • A load balancer giving up on a slow backend
What to do

Treat clustered 499s as a latency signal, not a client bug: they mark the point where your responses became slower than callers will tolerate.

nginx docscompare 408, 460
500Internal Server Error

Something broke on the server and it will not say what. The catch-all: an unhandled exception is the usual reality behind it.

Why you are seeing it
  • An uncaught exception in application code
  • A failed database connection
  • A misconfiguration that only shows up at runtime
What to do

The client cannot fix a 500. Read the server logs — the response body is deliberately vague and the stack trace is not in it.

501Not Implemented

The server does not implement this functionality at all — the method is unrecognised, not merely disallowed here. Different from 405, which means the method exists but not on this URL.

Why you are seeing it
  • An exotic verb against a basic server
  • A proxy asked to do something it does not support
502Bad Gateway

A server acting as a gateway got an invalid answer from the server behind it. The failure is upstream of whatever answered you.

Why you are seeing it
  • An application process that crashed or is not listening
  • A reverse proxy pointed at the wrong port
  • An upstream returning a malformed response
What to do

Check the upstream service first, not the proxy. A 502 usually means the proxy is working correctly and reporting honestly.

503Service Unavailable

The server is temporarily unable to handle the request — overloaded, or deliberately down. The one 5xx that is often intentional.

Why you are seeing it
  • Planned maintenance
  • An overload shedding load on purpose
  • A health check failing so the load balancer has no backend
What to do

Retry after the interval in Retry-After. If you are serving it, always set Retry-After — it is the difference between a well-behaved client and a stampede.

504Gateway Timeout

A gateway waited for an upstream server and gave up. The upstream may still be working on it, which is what makes 504s dangerous for non-idempotent requests.

Why you are seeing it
  • A slow query behind a proxy timeout
  • An upstream in a retry loop of its own
  • A timeout set shorter than the work takes
What to do

Do not blindly retry a POST — the first attempt may have succeeded after the gateway stopped listening. Use an idempotency key.

505HTTP Version Not Supported

The server refuses the HTTP version in the request line. Nearly always a client speaking to something that predates it, or a protocol confusion.

Why you are seeing it
  • An HTTP/2 preface reaching an HTTP/1.0 server
  • A malformed request line parsed as a version
506Variant Also Negotiates

A content-negotiation misconfiguration: the chosen variant is itself configured to negotiate, so the server is going in circles.

Why you are seeing it
  • An Apache mod_negotiation loop
RFC 2295compare 300, 508
507Insufficient Storage

The server cannot store what the request needs it to store. Disk, quota, or an object-store limit.

Why you are seeing it
  • A full disk on the origin
  • A per-account storage quota reached
RFC 4918compare 413, 500
508Loop Detected

The server detected an infinite loop while processing — usually WebDAV bindings that point at each other.

Why you are seeing it
  • Circular WebDAV bindings
  • A recursive include with no depth limit
RFC 5842compare 506, 500
509Bandwidth Limit ExceededApache (mod_bandwidth) / cPanel

A hosting bandwidth quota has been used up. Not an IANA code, but widespread enough on shared hosting that jshttp's statuses package carries it.

Why you are seeing it
  • A monthly transfer allowance exhausted
  • A traffic spike against a capped plan
What to do

Raise the quota or wait for the billing period to reset. A CDN in front usually prevents a repeat.

510Not Extended (OBSOLETED)

Obsolete. It asked the client to add extensions to the request before retrying, from a mechanism that never gained adoption and has been reclassified as historic.

Why you are seeing it
  • Essentially nothing in current use
RFC 2774also called Not Extendedcompare 501
511Network Authentication Required

You need to authenticate to the network, not to the site — a captive portal telling you so in a way a machine can recognise. Sent by the intercepting device, never by the origin.

Why you are seeing it
  • Hotel and airport Wi-Fi before you accept the terms
  • A corporate network requiring sign-in
What to do

Open a browser and complete the portal. An API client seeing 511 is on a network it cannot reach the internet from.

RFC 6585compare 401, 407
520Web Server Returned an Unknown ErrorCloudflare

Cloudflare reached your origin and got something it could not interpret — an empty reply, a malformed response, or a connection reset mid-answer. The catch-all of the 52x family, and the least specific.

Why you are seeing it
  • An origin process crashing mid-response
  • Headers too large for Cloudflare to parse
  • An origin returning an empty response
What to do

Check origin logs for the same timestamp. A 520 means Cloudflare is reporting honestly that your server confused it.

Cloudflare docscompare 521, 522, 502
521Web Server Is DownCloudflare

Cloudflare could not open a connection to your origin at all — refused, not merely slow.

Why you are seeing it
  • The origin process is not running
  • A firewall blocking Cloudflare's address ranges
  • The wrong origin IP in DNS after a migration
What to do

Confirm the server is listening, then confirm it accepts Cloudflare's IP ranges — blocking them is the most common cause after a move.

Cloudflare docscompare 520, 522
522Connection Timed OutCloudflare

The TCP handshake to your origin never completed. Different from 524: this one failed before any request was sent.

Why you are seeing it
  • An overloaded origin not accepting connections
  • Packet loss or a routing problem
  • A firewall dropping rather than rejecting
What to do

A dropped packet and a refused connection look different: 522 usually means something is silently discarding traffic.

Cloudflare docscompare 521, 524
523Origin Is UnreachableCloudflare

Cloudflare could not route to your origin at all — the address does not resolve or has no path.

Why you are seeing it
  • A DNS record pointing at an address that no longer exists
  • An origin taken down without updating DNS
What to do

Verify the origin record. This is a routing failure, not a server failure.

Cloudflare docscompare 521
524A Timeout OccurredCloudflare

The connection succeeded, the request was sent, and your origin did not finish answering within Cloudflare's window (100 seconds on the default plans).

Why you are seeing it
  • A long-running report or export
  • A slow database query
  • A synchronous job that should be asynchronous
What to do

Return 202 and a status URL rather than holding the connection. Raising the timeout treats the symptom.

Cloudflare docscompare 504, 522, 202
525SSL Handshake FailedCloudflare

TCP connected but the TLS handshake with your origin failed — no shared cipher, or the origin is not serving TLS on that port.

Why you are seeing it
  • Full (Strict) mode against an origin with no valid certificate
  • A cipher mismatch after a TLS policy change
  • Port 443 not actually serving TLS
What to do

Check the origin certificate and the SSL mode together — the pair is what has to agree.

Cloudflare docscompare 526, 495
526Invalid SSL CertificateCloudflare

The origin presented a certificate that Cloudflare could not validate, while set to Full (Strict).

Why you are seeing it
  • An expired origin certificate
  • A self-signed certificate under Full (Strict)
  • A hostname mismatch
What to do

Install a valid certificate on the origin, or switch off Strict — knowing that turns off origin verification.

Cloudflare docscompare 525
530Cloudflare Error (see accompanying 1xxx code)Cloudflare

A wrapper: the real diagnosis is the four-digit Cloudflare error number shown alongside it, most often 1016 (origin DNS error). The 530 alone tells you nothing.

Why you are seeing it
  • A CNAME pointing at a hostname that does not resolve
  • A Worker throwing an unhandled exception
What to do

Read the 1xxx number in the response body — that is the actual error.

Cloudflare docscompare 523
UTF-8
Ready
100% LOCAL

Five classes, one number

What the leading digit commits the server to

A client must understand the class even when it has never heard of the code — meet an unknown 499 and you treat it as a generic 4xx rather than guess. The table below is the whole contract, but two subtleties hide inside it: 2xx means accepted, and 202 accepts only the request, not the work; 3xx means go elsewhere, and the interesting question is whether your method survives the trip. The retry rule follows from the blame: 5xx faults the server and is worth retrying, 4xx faults the request and will fail again unchanged.

The four redirects people mix up

301 and 302 came first and share a defect: browsers turn a redirected POST into a GET, dropping the body. That contradicted the specification but was too widespread to fix, so two new codes were minted to mean what the originals were supposed to. 307 is the temporary one that preserves the method, 308 the permanent one. Where a redirect only ever sees GET traffic the distinction costs nothing, which is why 301 remains right for pages; for an API endpoint accepting POST, 308 is the one that does not silently mangle the request. 303 is the odd one out: it changes the method on purpose, which is what you want after a form submission so a refresh does not resubmit.

401 is not "unauthorized"

The most expensive naming mistake in the protocol. 401 Unauthorized means unauthenticated: the server does not know who you are. 403 Forbidden means it knows and the answer is still no. The test is whether logging in again could change the outcome — if yes, 401; if no, 403. Sending 401 for a permission failure puts well-behaved clients into a re-authentication loop that can never succeed, and every retry hits your auth server. A third option is worth knowing: when the resource's existence is itself privileged, 404 is right, because a 403 confirms something is there.

Choosing a code for an API you are building

Three rules cover most of it. Return 201 with a Location header when you create something, not a bare 200 — the client should not have to guess the new URL. Use 422 when a well-formed request fails validation and keep 400 for malformed input; collapsing both into 400 discards the one bit of information the client needed. When work is asynchronous, say so with 202 and hand back a URL to poll, rather than holding the connection until a gateway times out at 504 and leaves the caller unsure whether the job started. The status code is an interface, and a vague one costs your callers real debugging time.

How to use

  1. 01Type a number to jump to it — 4 narrows to the client errors, 40 to the 400s, 404 to one entry. Digits match the code, never the prose.
  2. 02Or type words: a reason phrase like "not found", an old name like "unprocessable entity", or a symptom like "timeout".
  3. 03Use the class chips to read a family end to end; untick vendor codes for the registry alone. Chips and search combine.
  4. 04Open an entry for the causes, the fix and the RFC, then Copy to paste it into a ticket. Link a colleague straight there with /http-status-codes#404.

Four ways this gets used

A failing request at 2am

The log says 502 and you need to know whose problem it is before reading code.

Search
502
Answer
the upstream failed, not the proxy — check the app process

Picking a code for your own API

The body parsed but the email is invalid. 400 or 422? The entries state the difference and the cost of getting it wrong.

Compare
400 vs 422
Answer
422 — syntax was fine, content was not

A code that is in no specification

Cloudflare returned 521 and the RFCs say nothing about it, because it is not theirs.

Search
521
Answer
the origin refused the connection — usually a firewall

Explaining a redirect to whoever owns SEO

You need 301, 302 and 308 in a sentence each, with something to link to.

Chip
3xx
Answer
the family, side by side, each with its own anchor

The five classes at a glance

ClassNameWhat it commits the server toRetry?
1xxInformationalInterim — the real response is still coming
2xxSuccessReceived, understood and acceptedNo need
3xxRedirectionLook elsewhere — usually the Location headerFollow, do not retry
4xxClient errorThe request was wrong — the same request fails againOnly after changing it
5xxServer errorThe request was fine and the server failed to fulfil itYes, with backoff

A client meeting an unfamiliar code must fall back to its class — the rule that lets new codes be added without breaking what is already deployed.

The redirects, side by side

CodePermanent?Method preserved?Use it when
301YesNo — POST becomes GETA page moved for good; cached hard, so be sure
302NoNo — POST becomes GETA temporary move where everything is a GET anyway
303NoNo — deliberately becomes GETAfter a POST, so refreshing does not resubmit
307NoYesA temporary move that must keep method and body
308YesYesAn API endpoint that moved for good and takes POST

307 and 308 exist only because 301 and 302 were implemented the wrong way round and could not be corrected in place.

Tips & best practices

  • Search by symptom, not only by number: "timeout", "certificate" and "cloudflare" land on the family you are chasing.
  • Untick vendor codes when writing a spec or a client library — mixing invented codes into a conformance list is how they end up in someone's switch statement.
  • Retry 5xx with exponential backoff and jitter; retry 4xx only after changing something. Synchronised retries turn one slow backend into an outage.
  • Always send Retry-After with a 429 or 503. Without it every client invents an interval, and they all pick the same round number.
  • Reading an API response body? Paste it into the JSON formatter — the useful error detail usually lives there, not in the status line.
  • Link to the anchor rather than the page: /http-status-codes#422 lands on the entry, not the top of a long list.

Gotchas — what status codes hide

401 means unauthenticated, whatever the word says

The registered phrase is "Unauthorized" and it means the server does not know who you are. Permission failures are 403. Get it backwards and clients lacking rights re-authenticate, succeed, retry, fail identically and loop — hammering your auth server with requests that were never going to work. The test: could logging in again change the answer?

302 rewrites your POST into a GET

Every browser turns a redirected POST into a GET on a 302, dropping the body. It contradicts the specification and was too entrenched to fix, which is precisely why 307 and 308 were minted. If a redirect might see anything but a GET, use one of those — otherwise the request arrives as something you did not send.

200 with an error inside is the worst answer

An API returning 200 with {"error": "not found"} in the body makes every client parse prose to find out whether the call worked. Monitoring reads it as success, retry logic never fires, and load balancers keep a broken backend in rotation. The status line is the machine-readable part — if the answer is "no", say so in the number.

301 is cached far longer than you expect

Browsers may cache a 301 indefinitely and often do, with no expiry unless you set one. Redirect a URL by mistake and everyone who visited during the mistake keeps being redirected after you fix it — there is no way to reach their cache. Send an explicit Cache-Control with any 301, and use 302 while you are still unsure.

404 and 410 say different things to a crawler

Both mean "not here", but 410 adds "and it is not coming back". Search engines drop a 410 considerably faster, while a 404 is treated as possibly temporary and revisited for a long time. If you removed content deliberately, 410 is honest; if it moved, neither is right — 301 to the new location keeps what the old URL had earned.

The code you are reading may never have reached your server

A CDN, load balancer or WAF can answer on your behalf, and its codes look exactly like yours in a browser. Cloudflare 520-527, nginx 499 and ALB 460 come from the intermediary; your origin logs show nothing at that timestamp, which is the giveaway. Confirm the request arrived before debugging code.

Technical details

Coverage
87 codes — all 63 in the IANA registry plus 24 from Cloudflare, nginx, AWS, IIS, Laravel, Esri, Shopify and Apache
Source
The IANA HTTP Status Code Registry via a snapshot captured 2026-07-31, cross-validated at build time against the statuses package, failing the build on any disagreement
Explanations
Written for this page — nothing copied from MDN or Wikipedia, whose paraphrase of the spec is what every other reference already offers
References
Registered codes deep-link to their RFC section; vendor codes link that vendor's own documentation
Search
Digits match the code by prefix; text matches the phrase, older names and the explanation. Class chips and the vendor toggle compose with it
Anchors
Every entry has a permanent id — #404 opens and highlights it
Without JavaScript
Every code is in the HTML at build time and every entry opens natively; only search and filtering need script
Network
None from tool code. A test sweep calls every function this page uses with fetch and XMLHttpRequest replaced by stubs that throw, so a stray request fails the build instead of shipping. Disconnect from the network and the page still works.

Frequently asked questions

What are the HTTP status codes?

Three-digit numbers a server returns to say what happened to a request. The first digit is the class — 1xx interim, 2xx success, 3xx redirect, 4xx your request was wrong, 5xx the server failed — and a client that does not recognise a code must fall back to its class. 63 are registered with IANA; this page also carries 24 that vendors invented and never registered.

What is the difference between 401 and 403?

401 means the server does not know who you are — authenticate and retry. 403 means it knows and is refusing anyway, so authenticating again will not help. The test is whether logging in could change the outcome. If the resource's existence is itself private, 404 beats both.

When should I use 301 instead of 302?

301 when the move is permanent and you are certain, because browsers cache it hard and may never ask again; 302 while you are still deciding. If the endpoint accepts anything other than GET, use 308 or 307 — 301 and 302 both turn a redirected POST into a GET and drop the body.

What is a 422 and how is it different from a 400?

400 means the server could not parse the request. 422 means it parsed fine and the content is still wrong — valid JSON with an invalid email address. Returning 400 for both discards the distinction the client needed: fix the syntax, or fix the data.

Why am I getting a Cloudflare 521 or 522?

Neither came from your server. 521 means Cloudflare could not open a connection to your origin — usually the process is down or a firewall is blocking Cloudflare's IP ranges. 522 means the attempt timed out, pointing at something dropping packets rather than refusing them. Your origin logs are empty at that timestamp either way.

Which codes should my API return?

201 with a Location header when you create something; 204 for a successful delete; 422 for validation failures and 400 only for malformed input; 202 plus a status URL for async work; 429 with Retry-After when you rate-limit. The rule behind all of them: do not make callers parse prose to learn whether the call worked.