Skip to content

HTTP Status Codes

Look up any HTTP status code and what it actually means.

31 of 31 codes

100

Continue

Keep sending the request body.

Sent when the client used an Expect: 100-continue header to check the server will accept a large body before uploading it.

RFC 9110

101

Switching Protocols

Protocol is changing at the client’s request.

The handshake response for a WebSocket upgrade.

RFC 9110

103

Early Hints

Preload hints before the real response.

Lets the browser start fetching stylesheets and scripts while the server is still generating the page.

RFC 8297

200

OK

The request succeeded.

The default success response. Do not return 200 with an error object inside — clients, caches and monitoring all read the status line, not your payload.

RFC 9110

201

Created

A new resource was created.

The correct response to a POST that creates something. Include a Location header pointing at the new resource.

RFC 9110

202

Accepted

Accepted for processing, not yet done.

For asynchronous work. Return something the client can poll for the eventual result.

RFC 9110

204

No Content

Success, and there is no body.

Ideal for DELETE and for PUT when you do not echo the resource back. A 204 must not include a body — some clients error if one is sent.

RFC 9110

206

Partial Content

Only part of the resource is returned.

The response to a Range request — how video seeking and resumable downloads work.

RFC 9110

301

Moved Permanently

The resource has a new permanent URL.

What SEO migrations need: it transfers ranking signals to the new URL. Browsers cache it aggressively, so a wrong 301 is painful to undo.

RFC 9110

302

Found

Temporarily at a different URL.

Historically ambiguous: most clients change POST to GET when following it, contrary to the spec. Use 307 or 303 when the method matters.

RFC 9110

303

See Other

Fetch the result with GET.

The correct redirect after a successful POST — it stops a browser refresh from resubmitting the form.

RFC 9110

304

Not Modified

Your cached copy is still valid.

Sent when the client’s If-None-Match or If-Modified-Since matches. Carries no body, which is the entire point.

RFC 9110

307

Temporary Redirect

Temporary, and keep the method.

Like 302 but guarantees a POST stays a POST. Prefer it whenever the method must be preserved.

RFC 9110

308

Permanent Redirect

Permanent, and keep the method.

The 301 equivalent that does not rewrite POST to GET.

RFC 9110

400

Bad Request

The request itself is malformed.

Reserve it for syntax problems — unparseable JSON, a missing required parameter. For a well-formed request that fails business rules, 422 is more precise.

RFC 9110

401

Unauthorized

You are not authenticated.

Misnamed: it means unauthenticated. Use it when credentials are missing, invalid or expired, and include a WWW-Authenticate header. If the user IS logged in but lacks permission, that is 403.

RFC 9110

403

Forbidden

Authenticated, but not allowed.

The server knows who you are and is refusing anyway. Re-authenticating will not help. Some APIs return 404 instead to avoid confirming a resource exists.

RFC 9110

404

Not Found

No resource at this URL.

Also the polite way to hide a resource from someone not allowed to know it exists.

RFC 9110

405

Method Not Allowed

Wrong HTTP method for this URL.

The response must include an Allow header listing the methods that are supported.

RFC 9110

409

Conflict

Clashes with the current state.

Duplicate creation, or an edit against a stale version. Pair it with ETags for optimistic concurrency.

RFC 9110

410

Gone

Deliberately removed, permanently.

Stronger than 404: it tells crawlers to drop the URL rather than keep retrying it.

RFC 9110

413

Content Too Large

The request body is too big.

Commonly hit at the proxy rather than the app — check nginx client_max_body_size before your handler.

RFC 9110

415

Unsupported Media Type

Wrong Content-Type.

Usually a client sending form-encoded data to an endpoint expecting JSON, or omitting the header entirely.

RFC 9110

418

I'm a teapot

A joke from 1998 that never went away.

Defined by the Hyper Text Coffee Pot Control Protocol as an April Fools RFC. Occasionally used as a deliberate "no" to bots.

RFC 2324

422

Unprocessable Content

Well-formed, but semantically wrong.

The right code for validation failures: the JSON parsed fine, but the email is already taken or the date is in the past.

RFC 9110

429

Too Many Requests

Rate limit exceeded.

Include a Retry-After header. Without it, well-behaved clients cannot back off correctly.

RFC 6585

500

Internal Server Error

Something broke on the server.

The catch-all for unhandled exceptions. Never leak a stack trace in the body — log it, return an opaque reference the user can quote to support.

RFC 9110

501

Not Implemented

The server does not support this method.

Different from 405: 501 means the method is unrecognised anywhere on the server, not just at this URL.

RFC 9110

502

Bad Gateway

An upstream server sent an invalid response.

Almost always the proxy telling you your application crashed, is not listening, or is behind a misconfigured port.

RFC 9110

503

Service Unavailable

Temporarily down or overloaded.

The correct code for maintenance windows. Add Retry-After so crawlers come back instead of dropping your pages.

RFC 9110

504

Gateway Timeout

An upstream server did not answer in time.

The proxy gave up waiting. Distinguish it from 502: the upstream is reachable but slow, not broken.

RFC 9110

About the HTTP Status Codes

Every HTTP status code, with what it means and when to actually return it. Most of the value here is in the distinctions people get wrong — 401 means unauthenticated while 403 means authenticated-but-refused, and a 302 quietly turns a POST into a GET where a 307 would not.

How to use it

  1. 1 Search by number, name, or the situation you are describing.
  2. 2 Read the summary for the one-line meaning.
  3. 3 Read the detail for when to use it and what people commonly get wrong.
  4. 4 Filter by class to browse all 4xx or 5xx codes together.

What it does

  • Every commonly used code from 100 to 504
  • Plain-English meaning plus practical guidance
  • Grouped by class: informational, success, redirect, client error, server error
  • Notes on the pairs people confuse
  • Instant search by number, name or description

Frequently asked questions

What is the difference between 401 and 403?

401 means unauthenticated — you have not proved who you are, so credentials are missing, invalid or expired, and the response should carry a WWW-Authenticate header. 403 means authenticated but not permitted: the server knows exactly who you are and is refusing anyway, so retrying with the same credentials will never help. The name 'Unauthorized' for 401 is simply a historical mistake.

When should I use 422 instead of 400?

Use 400 when the request itself is malformed — unparseable JSON, a missing required field. Use 422 when the request parsed perfectly but fails your business rules: the email is already registered, the date is in the past. The distinction tells the client whether to fix its serialisation or its data.

Should I return 200 with an error message in the body?

No. Caches, proxies, monitoring, retry logic and client libraries all read the status line, not your payload. A 200 with {"error": ...} inside will be cached as a success and will not trigger any error handling. Return the status that describes what happened.

What is the difference between 301 and 308?

Both are permanent. The difference is method preservation: most clients turn a POST into a GET when following a 301, while a 308 guarantees the method and body are kept. For page moves a 301 is standard and is what transfers SEO ranking; for API endpoints that accept POST, use 308.

Which redirect should I use after a form submission?

303 See Other. It tells the client to fetch the result with GET, which means refreshing the resulting page does not resubmit the form. This is the classic post/redirect/get pattern.