400 Bad Request
Client Error
The server cannot or will not process the request because it appears to be malformed. Invalid syntax, framing errors, deceptive request routing, or a request body that violates the declared Content-Type. 400 is intentionally generic; it signals a problem at the protocol or parser level rather than a business rule violation, which is what 422 exists for. A well-designed API returns 400 only when the request literally cannot be parsed.
When does this happen?
Return 400 when the request itself is broken at the protocol or syntax level. Malformed JSON in a POST body, a Content-Length that does not match the body, a missing required query parameter that is needed before any business logic can run, or a request line that violates the HTTP grammar all warrant 400. Most APIs return a JSON error body describing what went wrong, ideally referencing a specific field or token. Browsers do not surface 400 specially. The page or fetch call simply fails. Watch the distinction between 400 (the request is broken) and 422 (the request is well-formed but the data is invalid). Mixing them up makes client error handling harder because clients cannot tell whether to retry the same payload, fix the structure, or fix the values. Some frameworks default to 400 for any validation error, which is sloppy but widespread. If you control the API, separate the two.
Common causes
- Malformed JSON or XML in the request body. A missing comma, unbalanced brace, or trailing data after the closing tag.
- Content-Type header that does not match the actual body, e.g. Content-Type: application/json with form-encoded data.
- Required query parameter missing. The request is unprocessable before any handler logic can run.
- Request URL too long, exceeding the server's URI length limit (often 8KB on Nginx, lower on some load balancers).
- Invalid HTTP framing. Chunked encoding errors, mismatched Content-Length, or oversized headers.
- Cookie parsing failure. A corrupt or oversized cookie sent by the browser that the server cannot read.
- Invalid bytes in the request body. Typically a UTF-8 decoding error when the server expects text.
- Server-side request smuggling defense. Some gateways return 400 when they detect inconsistent Content-Length and Transfer-Encoding headers.
How to fix it
- Inspect the response body. Most APIs include an error message indicating which part of the request is broken.
- Validate JSON payloads with a linter or in-IDE schema before sending. Most 400s on JSON APIs are typos or stray characters.
- Confirm Content-Type matches the body. Application/json for JSON, application/x-www-form-urlencoded for form data, multipart/form-data for file uploads.
- Check the request URL length. If it is over 4KB, switch to POST with a body or trim the parameters.
- Clear browser cookies for the domain if a 400 appears suddenly and only for logged-in users. A corrupted session cookie is a likely cause.
- Look at the gateway or proxy logs. 400 is sometimes injected by the load balancer before the request reaches the application.
- If you are the server operator, distinguish 400 (protocol-level) from 422 (semantic) in your handlers so clients can react correctly.
Real-world examples
- Client sends POST /v1/users with a body of {"email":"[email protected]",} where the trailing comma makes the JSON invalid.
- Server returns 400 with body {"error":"invalid JSON","position":21}. Client retries with corrected JSON.
- Browser submits a form with a session cookie that has been corrupted by a buggy extension.
- Server returns 400 because it cannot parse the cookie. User clears cookies and the next request succeeds.
- Client sends GET /search with no q parameter to an endpoint that requires it.
- Server returns 400 with {"error":"missing required parameter: q"}. UI surfaces the validation message inline.
- Misconfigured client sends POST with Content-Type: application/json but a body of [email protected]&password=secret.
- Server tries to parse the body as JSON, fails, and returns 400. Client must either fix the Content-Type or send a JSON body.
- URL contains a parameter list so long it exceeds Nginx's 8KB request line limit.
- Nginx returns 400 before the request reaches the application. The client must POST the data instead.
- Reverse proxy detects conflicting Content-Length and Transfer-Encoding headers (a request-smuggling indicator).
- Proxy returns 400 and refuses to forward the request. The client must clean up the request framing.
Debugging
- Run curl -v with the exact payload and read the response body. Most APIs include a detailed error.
- Pipe your JSON body through jq . to validate it locally before sending: cat payload.json | jq . will fail loudly on syntax errors.
- Check Content-Type and Content-Length headers with curl -v. Mismatches show up here clearly.
- If the 400 is sporadic, capture both a failing and a succeeding request and diff the headers and body. Usually the difference is a stray character or a missing field.
- Inspect upstream proxy logs (Nginx access.log, Cloudflare logs). Many 400s never reach the application.
How it differs from related codes
HTTP 401
401 is specifically about missing or invalid authentication. 400 is about the request being broken at the syntax or protocol level. Auth is unrelated.
HTTP 404
404 means the URL does not exist. 400 means the URL exists but the request is malformed. The distinction matters because 400 is the client's fault to fix, 404 may be either.
HTTP 422
422 means the request was syntactically valid but failed business rules (e.g., email already taken). 400 means parsing failed. Conflate them and clients cannot tell what to fix.
Related status codes
See HTTP 400 in your redirect chains?