HTTP 400 Bad Request
400 is the generic "your request is broken" response. RFC 9110's examples are malformed syntax, invalid message framing and deceptive request routing. Sending the same request again won't help: something in it has to change.
400 Bad Request
The server can't or won't process the request because of something it considers a client error.
Who fixes it: Client. Something in the request must change. But check the server's logs: limits set too low and over-strict parsers also produce 400s.
What 400 means
Because it's generic, a 400 is only as useful as its body. Good APIs say what was wrong ("body is not valid JSON at position 42", "missing query parameter: from"). Web servers like nginx return a bare HTML page and write the reason to the error log.
If the request is well-formed but the values fail validation, 422 is more precise. If the credentials are the problem, it's 401.
Source: RFC 9110 §15.5.1.
Common causes
- Malformed JSON: a trailing comma, single quotes, an unescaped newline, or a body stringified twice so the server receives a JSON string where it expected an object.
- A missing or wrong
Content-Type, so the server's parser rejects the body, e.g. form-encoded data sent to a JSON-only endpoint. - nginx
400 Bad Request: Request Header Or Cookie Too Large: bloated cookies or a hugeAuthorizationtoken exceedlarge_client_header_buffers. - nginx
400 The plain HTTP request was sent to HTTPS port: something is speaking plain HTTP to port 443. - Invalid characters in the URL: unencoded spaces, a
%not followed by two hex digits. - A malformed header line, or no
Hostheader on HTTP/1.1. Usually a hand-written client or a misconfigured proxy. - Express with
express.json(): invalid JSON throws aSyntaxErrorthat becomes a 400 withtype: 'entity.parse.failed'.
How to debug and fix a 400
Reproduce it with curl
-v prints the exact request headers. In DevTools, right-click the failing request and choose Copy as cURL, then change one thing at a time until it works. Paste the body into a JSON validator first.
curl -v https://api.example.com/orders \
-H 'Content-Type: application/json' \
--data '{"sku": "A-1", "qty": 2}'nginx: headers or cookies too large
The default is 4 8k. Raising it treats the symptom, so also find out why cookies are that big (many analytics cookies, session data stored client-side) or why the token carries so many claims.
# http or server block
large_client_header_buffers 4 16k;Express: return a helpful 400 for bad JSON
An error-handling middleware (four arguments) can catch body-parser failures and return JSON instead of an HTML error page.
app.use(express.json());
// ... routes ...
app.use((err, req, res, next) => {
if (err.type === 'entity.parse.failed') {
return res.status(400).json({ error: 'invalid_json', detail: err.message });
}
next(err);
});Client side: encode once, label correctly
Build query strings with URLSearchParams, stringify the body exactly once, and set Content-Type.
const params = new URLSearchParams({ q: 'a&b c', page: '2' });
const res = await fetch(`/api/search?${params}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ tags: ['x', 'y'] }),
});Headers that matter with 400
- Content-Type
- Tells the server which parser to use. A mismatch is one of the most common 400 causes.
- Content-Length
- If it doesn't match the actual body size, the message framing is invalid and the server must reject it.
- Cookie / Authorization
- The usual culprits when headers exceed the server's buffer limits.
400 vs similar status codes
- 422 Unprocessable Content: The syntax is fine but the values are invalid. Use it for validation errors if you want to separate them from parse errors.
- 401 Unauthorized: The request is fine but has no valid credentials.
- 413 Content Too Large: The body is too big. nginx returns 400 for oversized headers but 413 for oversized bodies.
- 431 Request Header Fields Too Large: The precise code for oversized headers. Many servers, nginx included, send 400 instead.
SEO impact of 400
For Googlebot, every 4xx except 429 is treated the same way: the URL isn't indexed, and drops out if it was. If Search Console reports 400s, look for URL parameters or malformed links that your server rejects.
Related status codes
422Unprocessable Content
The server understands the content type and syntax of the request, but can't process the instructions it contains.
401Unauthorized
The request lacks valid authentication credentials for the target resource.
413Content Too Large
The request content is larger than the server is willing or able to process.
405Method Not Allowed
The method is known to the server but not supported by the target resource.
Looking for another code? Search the full HTTP status codes list, or read which code your API should return in the REST API status codes guide.
Learn more
HTTP Status Codes for REST APIs: 200 vs 201 vs 204, 400 vs 422 vs 429
A practical guide to choosing the right HTTP status code in REST API design. Covers the most confusing pairs: 200 vs 201, 400 vs 422, 401 vs 403, and when to use 503 vs 429.
REST API Design Best Practices: A Practical Guide
The conventions that make REST APIs intuitive and consistent. Covers URL design, HTTP methods, status codes, versioning, pagination, and error responses.
CORS Explained: Why It Happens and How to Fix It
CORS errors happen when a browser blocks a request to a different origin. Learn how the Same-Origin Policy works, what preflight requests are, and how to configure CORS correctly in Express, FastAPI, and Nginx.
Frequently Asked Questions
Is a 400 Bad Request a client or server problem?▾
By definition the server is blaming the client: something in the body, URL, headers or cookies is invalid. In practice it can still be a server issue, such as a header limit set too low or an over-strict parser, so check the server or proxy logs for the exact reason.
How do I fix 400 Bad Request: Request Header Or Cookie Too Large?▾
As a visitor, clear that site's cookies. As the site owner, find what's bloating the headers (often too many cookies or a very large JWT) and, if needed, raise nginx's large_client_header_buffers, for example to 4 16k.
Should validation errors return 400 or 422?▾
Both are common. 400 is fine for everything if you return field-level details in the body. Many frameworks (Rails, FastAPI, Laravel) use 422 when the body parsed correctly but values are invalid, which lets clients separate fix-your-code errors from fix-your-input errors. Pick one convention and document it.