100 Continue
The server got the request headers and the client should send the body. Clients send Expect: 100-continue before a large upload to check it will be accepted first. curl does this over HTTP/1.1 for bodies over 1 MB.
Every HTTP status code, what it means and what to do about it. Type a number or a word like timeout, redirect or cookie.
The server got the request headers and the client should send the body. Clients send Expect: 100-continue before a large upload to check it will be accepted first. curl does this over HTTP/1.1 for bodies over 1 MB.
The server agrees to change protocol, as asked in the Upgrade header. You see it when a WebSocket connection opens.
WebDAV: the server is still working on a long request. Deprecated; rarely seen today.
Sent before the final response with Link headers, so the browser can start preloading CSS, fonts or scripts while the server is still building the page.
The request worked. For GET the body is the resource; for POST it is the result of the action.
A new resource was created, usually by POST or PUT. The Location header should point to it.
The request was accepted for processing but isn't done yet, like a queued job. The body often says where to check its status.
The response was changed by a proxy in between, so it isn't exactly what the origin sent. Rare.
It worked and there is no body. Common for DELETE, for PUT that saves without returning anything, and for CORS preflights.
It worked; the client should reset the form or view that sent the request. Rare.
The body is only the part asked for with a Range header. Used for resuming downloads and seeking in video.
WebDAV: the body is XML with a separate status for each of several resources.
WebDAV: members of a collection already listed earlier in the same 207 response.
The response is a delta (changes) applied to the current resource, for delta encoding. Rare.
There is more than one version of the resource (for example different formats) and the client should pick one. Rare in practice.
The resource has a new permanent URL, given in Location. Browsers and search engines update to it and pass ranking to the new URL. Clients may turn a POST into a GET when following it; use 308 to keep the method.
A temporary redirect to the URL in Location. Keep using the old URL later. Clients usually turn POST into GET; use 307 to keep the method.
Go GET the URL in Location. Used after a form POST so that refreshing the result page doesn't submit the form again (Post/Redirect/Get).
The cached copy is still good: the client sent If-None-Match or If-Modified-Since and nothing changed. There is no body; use the cached one.
Deprecated and ignored by browsers for security reasons.
Was Switch Proxy in an early HTTP/1.1 draft. Reserved and no longer used.
Like 302, but the client must repeat the same method and body at the new URL. Browsers also show 307 for an internal HSTS upgrade from http to https.
Like 301, but the method and body must stay the same. The right choice for permanently moving an API endpoint that takes POST.
The server can't or won't handle the request because something in it is wrong: invalid JSON, a missing field, a malformed header or a cookie that is too large. The body usually says which.
You need to log in: no credentials were sent, or they are wrong or expired. The response must include a WWW-Authenticate header. Despite the name it means unauthenticated; compare 403.
Reserved for future use. Some APIs use it when a plan's quota or payment has run out.
The server knows who you are (or doesn't care) and still refuses. Logging in again won't help. Also returned for blocked IPs, missing file permissions on the server, and WAF blocks.
Nothing exists at this URL, or the server won't say that something does. Check the path, the spelling and the trailing slash.
The URL exists but doesn't accept this method, like POST to a read-only page. The Allow header lists the methods that work.
The server can't produce a response in any format the Accept headers ask for.
Like 401, but for a proxy between you and the server. Send Proxy-Authorization.
The client took too long to send the request, and the server closed the connection. Usually safe to retry.
The request conflicts with the current state: an edit on an outdated version, or creating something that already exists. Fetch the latest state and try again.
The resource was deliberately removed and won't come back. Search engines drop it faster than a 404.
The server needs a Content-Length header for this request.
A condition in If-Match or If-Unmodified-Since wasn't met, so nothing was changed. Used to stop lost updates.
The request body is over the server's limit. In nginx the limit is client_max_body_size (1 MB by default). Formerly Payload Too Large, and before that Request Entity Too Large.
The URL is longer than the server accepts, often from a huge query string. Send the data in a POST body instead. Formerly Request-URI Too Long.
The server doesn't accept the body's format. Check the Content-Type header, for example application/json for JSON.
The Range asked for is outside the file, for example resuming a download that is already complete. Formerly Requested Range Not Satisfiable.
The server can't meet the Expect header. Retry without Expect: 100-continue.
An April Fools' joke from 1998 (RFC 2324). Reserved so it is never given a real meaning; some sites use it to turn away bots.
Laravel: the CSRF token is missing or expired, usually because a form sat open too long. Reload the page and submit again.
The request reached a server that can't answer for this host, usually because an HTTP/2 connection was reused for another domain on the same certificate.
The body is well formed but its contents are invalid, like a failed validation. Many APIs (Rails, Laravel, FastAPI) use it for form errors. Formerly Unprocessable Entity.
WebDAV: the resource is locked.
WebDAV: the request failed because an earlier one it depended on failed.
The server won't risk processing a request sent in TLS 1.3 early data, because it could be replayed. Retry after the handshake.
The client must switch to another protocol, given in the Upgrade header.
The server requires a conditional request (If-Match), to stop clients overwriting each other's changes.
Rate limited: you sent too many requests in a given time. Wait for the number of seconds in Retry-After if it is there, and back off exponentially.
The headers are too big, most often because of too many or too large cookies. Clearing the site's cookies usually fixes it.
nginx closed the connection without sending anything. Used in nginx configs to drop unwanted requests; clients see an empty reply.
Blocked for legal reasons, such as a court order or government censorship. The number is a nod to Fahrenheit 451.
nginx: the request headers were too large (often cookies). Shown to clients as 400.
nginx: the client certificate is invalid. Shown to clients as 400.
nginx: a client certificate is required but none was sent. Shown to clients as 400.
nginx: a plain http request reached a port that expects https. Shown to clients as 400 unless redirected with error_page 497.
nginx: the client hung up before the server answered, often because it timed out first. You see it in logs, never in a browser. Look for slow upstreams.
Something broke on the server and it has no more specific code. It's a bug or crash on their side: check the server logs.
The server doesn't support the method or feature at all, for any resource.
A proxy or load balancer (nginx, a CDN) got an invalid response from the app behind it, or couldn't connect. Usually the app crashed, isn't running, or closed the connection.
The server is overloaded or down for maintenance. Temporary; Retry-After may say when to try again.
A proxy or load balancer waited too long for the app behind it. The request may still finish on the server, so be careful retrying a POST.
The server doesn't support the HTTP version of the request.
A server configuration error in content negotiation. Rare.
WebDAV: the server has no room to store what was sent.
WebDAV: the server found an infinite loop while processing the request.
cPanel and Apache hosting: the site used up its monthly bandwidth allowance. The site owner has to raise the limit or wait for the reset.
Obsolete: further extensions to the request are needed.
You have to log in to the network first, like a hotel or airport Wi-Fi captive portal.
Cloudflare: the origin sent an empty, unknown or unexpected response, or reset the connection.
Cloudflare: the origin refused the connection. The server is down, or a firewall blocks Cloudflare's IPs.
Cloudflare: the TCP connection to the origin timed out. Check the server is up and that Cloudflare's IPs aren't blocked.
Cloudflare: it can't reach the origin at all, often a wrong DNS record.
Cloudflare: it connected to the origin but got no HTTP response within 100 seconds (on most plans). Move long work to a background job.
Cloudflare: the TLS handshake with the origin failed.
Cloudflare: in Full (strict) mode, the origin's certificate is invalid or expired.
Some large APIs return it when they are overloaded. Retry later with backoff.
Cloudflare: shown together with a 1xxx error (like 1016, origin DNS error). Look up the 1xxx code for the cause.
No status code matches that. Try a number like 404 or a word like timeout.
| Situation | Code |
|---|---|
| Not logged in, or the token expired | 401 Unauthorized |
| Logged in, but not allowed to do this | 403 Forbidden (or 404 to hide that it exists) |
| Malformed request (bad JSON, wrong type) | 400 Bad Request |
| Valid JSON that fails validation | 422 Unprocessable Content (or 400) |
| Duplicate, or edited an outdated version | 409 Conflict |
| Rate limit reached | 429 Too Many Requests with Retry-After |
| Created something | 201 Created with Location |
| Success with nothing to return | 204 No Content |
| Page moved for good | 301 (or 308 to keep POST) |
| Temporary redirect | 302 (or 307 to keep POST) |
| After a form POST | 303 See Other |
| Down for maintenance | 503 Service Unavailable with Retry-After |
401 means the server doesn't know who you are: log in or send a valid token, then try again. 403 means it knows (or doesn't need to) and the answer is still no, so new credentials won't help unless they belong to someone with more access.
All three usually come from a proxy, load balancer or CDN in front of the app. 502 Bad Gateway: the app answered with garbage or the connection failed, often because it crashed or isn't listening. 503 Service Unavailable: the server says it's overloaded or in maintenance. 504 Gateway Timeout: the app didn't answer in time. Look at the app's logs and the proxy's timeout settings.
408, 429, 502, 503 and 504 are usually temporary: retry with exponential backoff, and honor Retry-After. Don't retry other 4xx codes without changing the request. Be careful retrying a POST after a timeout, since the first attempt may have worked; use an idempotency key if the API supports one.
Not Found: the server has nothing at that URL. Check the path, spelling and trailing slash. If it was removed for good, 410 Gone tells search engines to drop it sooner.
301 is permanent: browsers cache it and search engines move rankings to the new URL. 302 is temporary: keep using the old URL. 308 and 307 are the same pair, but they keep the method and body, so a POST stays a POST.
You hit a rate limit. Wait the number of seconds in the Retry-After header if there is one, and slow down or back off exponentially.
It's an nginx log code: the client closed the connection before the server answered, usually because the client's own timeout was shorter than the request took.
They come from Cloudflare, not your app. 520: the origin sent an unexpected or empty response. 521: the origin refused the connection. 522: connecting to the origin timed out. 524: the origin connected but took over 100 seconds to answer.
The browser's cached copy is still current, so the server sent no body. It's normal and saves bandwidth; it shows up when you reload a page.
It started as an April Fools' joke (RFC 2324) and is reserved, so it will never mean anything else. Some sites use it to refuse bots.