HTTP 400 vs 422 — Bad Request vs Unprocessable Entity Comparison

http 400 vs 422 explained: when to return Bad Request for malformed syntax versus Unprocessable Entity for valid syntax that fails business validation. Includes API examples.

4xx

400

Bad Request

View full 400 page →

4xx

422

Unprocessable Entity

View full 422 page →

Quick Cheat Sheet

Layer 400 Bad Request 422 Unprocessable Entity
Failure type Syntax / parsing Semantics / validation
Can the server parse it? No Yes
Originally specced for Generic HTTP WebDAV (RFC 4918), now broadly used
Typical body Error message Field-level validation errors

What Each Code Actually Means

400 Bad Request (RFC 9110 § 15.5.1) is the "I literally cannot make sense of this" response. Malformed JSON, missing required headers, invalid query-string encoding, oversized cookies — anything where the request itself is structurally broken.

422 Unprocessable Entity (originally RFC 4918, formalized in RFC 9110 § 15.5.21) is for requests that are well-formed but contain instructions the server cannot execute. The classic example: a JSON body that parses fine but has age: -5 in a field that requires a positive integer.

Where the Line Lives

If your framework can deserialize the body without throwing, you've passed 400 territory. Anything beyond that — required-field checks, format constraints (email, UUID), range checks, cross-field rules, business rules — should produce 422.

Real-World API Examples

  • GitHub API is the canonical example: it returns 422 with a structured errors array when you POST a valid JSON body that fails validation (e.g., creating a repo with a name that already exists).
  • Stripe API mostly skips 422 and uses 400 with a typed error object (type: "invalid_request_error"), which is a deliberate design choice for backward compatibility.
  • Rails with render json: ..., status: :unprocessable_entity is so common that 422 is sometimes called "the Rails error code."

When to Prefer Which

  • New API? Use 422 for validation, 400 for parse failures. It's clearer and aligns with most modern style guides (JSON:API, IETF problem-details).
  • Talking to legacy clients that don't understand 422? Use 400 consistently and put the error category in the body.

Never return 200 with an error field in the body — that's the worst of both worlds.

Real-World Use Case

A typical FastAPI or Express endpoint should return 400 when JSON.parse throws on the request body, but 422 when Zod/Pydantic schema validation fails. For a /users endpoint, missing closing brace = 400, while {"email": "not-an-email"} = 422 with a per-field error map.

Look Up Any Status Code

Browse all status codes →