
A 400 Bad Request means the server rejected your request as malformed before any page or API code ran. In a browser the usual culprit is an oversized or corrupted cookie for that one site; in an API it is invalid JSON, a wrong Content-Type or a header that exceeds the server's size limit.
Because the refusal happens at the HTTP parsing layer — nginx, Apache, IIS, a CDN or a load balancer — the fix is rarely in the application the request was aimed at. Below: what the standard says, the exact error strings each server prints, a cause-by-cause table, step-by-step fixes for Chrome, Edge, Firefox and Safari, and the developer checklist for nginx, Postman and REST APIs.
What HTTP 400 Bad Request means
Status 400 Bad Request belongs to the 4xx class of client errors. Per RFC 9110, §15.5.1, the server returns 400 when it "cannot or will not process the request due to something that is perceived to be a client error" — for example, malformed request syntax, invalid request message framing, or deceptive request routing.
The key word is "client". Unlike 5xx errors, where the server is at fault, a 400 tells you: "I am working fine, but your request is assembled incorrectly." So the first diagnostic step is to figure out what exactly is wrong in the request — and which hop in the chain (CDN, reverse proxy, application) refused it.
What a 400 response looks like
HTTP/1.1 400 Bad Request
Content-Type: text/html; charset=utf-8
Connection: close
<html>
<head><title>400 Bad Request</title></head>
<body><h1>Bad Request</h1></body>
</html>The body text is the most useful clue you get. Different layers word it differently, and the wording tells you who rejected the request:
| Message on the page | Who sends it | What it actually means |
|---|---|---|
400 Bad Request — Request Header Or Cookie Too Large | nginx (internally status 494) | One header line or the whole header block did not fit into large_client_header_buffers; almost always a bloated Cookie or a long Authorization token |
400 Bad Request — The plain HTTP request was sent to HTTPS port | nginx (internally 497) | Plain http:// sent to a port that expects TLS, e.g. http://example.com:443/ or a proxy misconfigured to talk HTTP to an HTTPS upstream |
400 Bad Request — No required SSL certificate was sent | nginx (internally 496) | The server requires a client certificate (mutual TLS) and the browser or client did not present one |
Size of a request header field exceeds server limit. | Apache httpd | A header is longer than LimitRequestFieldSize (8190 bytes by default) |
Bad Request - Request Too Long. HTTP Error 400. The size of the request headers is too long. | IIS / Windows HTTP.sys | Headers exceed the HTTP.sys limits MaxFieldLength / MaxRequestBytes |
Bad Request - Invalid Hostname | IIS / HTTP.sys | The Host header does not match any binding on the server |
JSON body such as {"error":"invalid_request"} | Your API or framework | The request parsed as HTTP, but the application rejected its body or parameters |
If the page is a bare nginx or IIS error and not your site's own design, the application never saw the request — look at limits and proxies, not at your code. For the standard's full list of neighbors, see the complete HTTP status code reference and the MDN reference for status 400.
What is the root cause of a 400 Bad Request?
Although a 400 is formally the client's "fault", server configuration can provoke it too (for example, overly strict header-size limits). Here is a summary table of typical causes.
| Cause | Side | What happens | How to fix |
|---|---|---|---|
| Corrupted or oversized cookies | Client | Browser sends stale/broken cookies, header exceeds the limit | Clear the site's cookies |
| Malformed request syntax | Client | Bad request line, stray characters, broken framing | Check how the request is built in code |
| URL or headers too long | Client + Server | URL/header length exceeds the server limit | Shorten the URL, raise nginx buffers |
| Wrong Content-Type / broken JSON | Client | Body does not match the declared type, JSON error | Validate JSON, set the correct header |
| Invalid characters or bad percent-encoding in the URL | Client | A raw space, a lone % or a copy-pasted link with hidden characters breaks the request line | Re-type the address, encode query values |
Missing or duplicate Host header | Client | RFC 9112, §3.2 requires a 400 when an HTTP/1.1 request has no Host or more than one | Fix the client or the proxy that rewrites headers |
| Plain HTTP to an HTTPS port | Client + Server | A TLS port receives unencrypted HTTP | Use https://, fix proxy_pass scheme |
| Strict header limits | Server | large_client_header_buffers is too small | Raise the limits in the config |
Corrupted cookies — cause number one
The most common cause of a 400 for ordinary users is "bloated" or corrupted cookies. When the total cookie size exceeds the server's buffer limit (usually 4-8 KB), the server aborts the request with a 400. Symptom: the error appears on only one site, while the same site opens fine in incognito mode.
Cookies bloat for mundane reasons: an analytics or A/B-testing script that writes a new cookie on every visit, a single sign-on flow that stacks session cookies for several subdomains on the parent domain, or an app that stores a whole JSON object or a long JWT in a cookie. Every request to that domain carries all of them, so the header keeps growing until it crosses the limit. On the developer side, keep cookies small and scoped — the flags that control scope are covered in our guide to cookie security flags.
Broken JSON and wrong Content-Type
When working with an API, a 400 is often caused by an invalid request body. If you declared Content-Type: application/json but sent invalid JSON, the server responds with 400.
POST /api/v1/orders HTTP/1.1
Host: example.com
Content-Type: application/json
{ "name": "John", "amount": } <-- missing value after "amount"Other body errors that end the same way: a trailing comma after the last field, single quotes instead of double quotes, a JSON body sent with Content-Type: application/x-www-form-urlencoded, or a multipart/form-data body whose boundary does not match the one declared in the header.
Does a 400 error mean the site is down?
No. A 400 is proof the server is up: it received your request, parsed it far enough to find a problem, and answered. A site that is down produces a timeout, a connection refused, or a 5xx such as 502 or 503. If a site shows 400 to you but loads for everyone else, the problem is in your request — almost always cookies. If it shows 400 to everyone, the site's own configuration (a proxy, a CDN rule, a header limit) is broken.
The same applies to 400 errors on services you do not run, whether a streaming platform such as Kick, a bank or a SaaS dashboard: clear that site's data first; if the error persists in a clean browser, only the service's operators can fix it.
Is a 400 error permanent?
Not in the sense a 404 or 410 can be. The same broken request will keep getting 400 — resending it unchanged achieves nothing — but the moment the request changes (cookies cleared, URL fixed, body corrected, server limit raised), the error goes away. This is why a plain refresh rarely helps while deleting one site's cookies often does.
How to fix a 400 error as a user
If you hit a 400 as a site visitor, try these in order:
- Clear this site's cookies — in browser settings, delete data for the specific domain.
- Clear the cache and reload the page (Ctrl+F5 / Cmd+Shift+R).
- Check the URL — remove stray characters, trim an overly long link.
- Open the site in incognito mode — if it works, the problem is cookies/cache in your main profile.
- Disable extensions that may interfere with requests.
How to fix 400 Bad Request on Google Chrome
- Open the failing site, press F12 to open DevTools, go to the Application tab, select Storage and click Clear site data. This removes cookies, local storage and cache for that origin only.
- Alternatively, type
chrome://settings/content/allin the address bar, search for the domain and delete its data. Check the parent domain too: cookies set on.example.comare sent toshop.example.com. - Reload the page. If the 400 is gone, bloated cookies were the cause.
- Still failing? Open a Guest window or disable extensions at
chrome://extensions— header-modifying and privacy extensions can inject or rewrite headers.
Other browsers: in Edge, go to Settings → Cookies and site permissions → Manage and delete cookies and site data → See all cookies and site data; in Firefox, Settings → Privacy & Security → Cookies and Site Data → Manage Data; in Safari on macOS, Settings → Privacy → Manage Website Data. Remove only the affected domain. For full cache clearing steps per browser, see how to clear browser cache.
Why the same request fails in one browser but not another
If a 400 reproduces in Chrome but not in Firefox or incognito, the culprit is almost always profile-bound state: accumulated cookies, extensions that rewrite headers, or a stale cached request. Browsers store cookies independently, so a "bloated" set in one profile easily exceeds the server buffer while a clean profile stays under the limit. That is also why clearing a specific site's data is the fastest cure.
How to fix a 400 error as a developer
If your own server returns the 400, check request construction and limits. When sending JSON, always validate the body and set the correct header:
curl -v -X POST https://example.com/api/v1/orders \
-H "Content-Type: application/json" \
-d '{"name":"John","amount":100}'The -v flag in curl shows both the request headers you sent and the response you received — it is the best way to see what actually reached the server. To validate a body before sending it, run python3 -m json.tool body.json or jq . body.json: both print the exact line and column of a syntax error.
400 Bad Request Header or Cookie Too Large
If the error is caused by large headers (for example, a long JWT in a cookie or the Authorization header), raise the buffers in nginx:
http {
large_client_header_buffers 4 16k;
client_header_buffer_size 16k;
}The nginx defaults are client_header_buffer_size 1k and large_client_header_buffers 4 8k: no single header line may exceed one large buffer (8 KB), and the whole header block must fit into four of them. Put the directives at the http level — per the large_client_header_buffers documentation, a value set in a server block may be ignored in favor of the default server's. Then test and reload:
sudo nginx -t && sudo systemctl reload nginxYou can reproduce the error on purpose to confirm the diagnosis and the fix — send a 9 KB cookie:
curl -s -o /dev/null -w '%{http_code}\n' \
-H "Cookie: test=$(head -c 9000 /dev/zero | tr '\0' a)" \
https://example.com/On a default nginx this prints 400; after raising the buffers to 16k it returns your normal status. Raising limits treats the symptom, though. The real fix is to stop the cookie growth: find which cookie is large in DevTools → Application → Cookies, and move big payloads to server-side sessions.
Other servers have their own knobs. Apache: LimitRequestFieldSize 16380 in the server or virtual host config. IIS: the registry values MaxFieldLength and MaxRequestBytes under HKLM\SYSTEM\CurrentControlSet\Services\HTTP\Parameters, followed by a restart of the HTTP service. Gunicorn: --limit-request-field_size and --limit-request-line. Node.js answers oversized headers with 431 Request Header Fields Too Large rather than 400 and is tuned with --max-http-header-size. Remember that every hop has a limit: raising it on nginx does nothing if the app server behind it still rejects the header.
400 Bad Request nginx: reading the log
nginx logs client errors such as oversized headers at the info level, so with the default error level the error log stays silent. Temporarily lower it:
error_log /var/log/nginx/error.log info;Reproduce the request and look for lines like client sent too long header line, client sent invalid request or client sent plain HTTP request to HTTPS port. The access log confirms that the status came from nginx itself: a 400 with a tiny response size and no upstream timing means the request never reached the backend. More on where logs live and how to read them in our nginx logs guide.
400 Bad Request in Postman
Postman sends exactly what you configure, so a 400 there is almost always one of these:
- Body type mismatch. In Body → raw, the dropdown must say JSON, not Text; otherwise the request goes out as
text/plainand a JSON API rejects it. - A manual
Content-Typeheader in the Headers tab that overrides the one Postman sets automatically. - Unresolved variables. A
{{baseUrl}}or{{token}}without a value in the active environment is sent literally. - Required parameters missing from the query string or body.
Open the Postman Console to see the raw request that was actually sent, headers included, and compare it with a working curl -v call.
400 Bad Request in a REST API
If you build the API, make every 400 explain itself. A bare "Bad Request" forces clients to guess; a structured body tells them what to change. RFC 9457 defines a standard format for this:
HTTP/1.1 400 Bad Request
Content-Type: application/problem+json
{
"type": "https://example.com/problems/invalid-body",
"title": "Request body is not valid JSON",
"status": 400,
"detail": "Unexpected token '}' at line 1, column 29"
}Log the reason on the server side as well, with a request ID the client can quote. Never echo secrets, tokens or full request bodies back in the error.
How to diagnose the source of a 400
To find where the request breaks, work from simple to complex:
- Reproduce the error in incognito — rule out cookies/cache.
- Replay the request with
curl -v— see the exact headers and body. - Compare a working request against the failing one, header by header.
- Check server logs — nginx writes the reason (e.g. "client sent too long header").
- Walk the chain: bypass the CDN (request the origin directly, if you are allowed to), then the reverse proxy, and see at which hop the 400 appears.
400 versus other 4xx codes: don't mix them up
A 400 is the "generic" answer to a malformed request. But it has more specific neighbors, and a well-designed server returns those instead. Knowing the difference speeds up diagnosis.
| Status | Meaning | Typical fix |
|---|---|---|
| 400 Bad Request | The request syntax is broken and the server cannot parse it at all | Fix cookies, headers, URL or body |
| 401 Unauthorized | The syntax is fine, but authentication credentials are missing or invalid | Log in again, send a valid token |
| 403 Forbidden | You are authenticated, but lack rights to the resource | Check permissions, WAF rules |
| 413 Content Too Large | The request body exceeds the server limit | Raise client_max_body_size or send less |
| 414 URI Too Long | The request line is too long; nginx and Apache send this, not 400, for an overlong URL | Move data from the query string into a POST body |
| 422 Unprocessable Content | The syntax is fine, but the data fails business validation (e.g. a badly formatted email) | Correct the field values |
| 431 Request Header Fields Too Large | The precise code for oversized headers; many servers send 400 instead | Same as the cookie fix above |
An important nuance: some frameworks return 400 where 422 would be more accurate. If you build an API, try to separate "couldn't parse the request" (400) from "parsed it, but the data is logically invalid" (422) — it makes debugging much easier for your API's clients. Body-size failures have their own article: HTTP 413 Request Entity Too Large.
How to check the server response
The fastest way to see the status code and the full set of headers is a free HTTP header and response code checker on enterno.io. Enter an address and instantly see the status, request and response headers, redirects, and security hints. This helps you tell a client-side 400 from a server-side 5xx. When diagnosing an API, compare the headers of a working request against the failing one — the difference is usually obvious at a glance: an extra header, a wrong Content-Type, or a missing required parameter.
Two more checks help when the 400 is on your own site:
- Technology detector — shows whether nginx, Apache, IIS or a CDN such as Cloudflare answers, so you know whose limits and error page you are dealing with.
- Redirect checker — a redirect chain that bounces between
http://andhttps://or across subdomains can hand the browser to a port or host that answers 400.
If the checker gets a 200 while your browser gets a 400, the site is fine and your browser's stored cookies are the problem.
Related reading
To understand response codes more deeply, read the complete HTTP status code reference, plus breakdowns of neighboring errors: 403 Forbidden and 404 Not Found. If your 400 is cookie-related, see our guide to cookie security flags.
FAQ
How do you fix a 400 bad request?
As a visitor, delete that site's cookies and cached data, check the URL for stray characters, and retry in a private window. As a developer, replay the request with curl -v, validate the JSON body and Content-Type, and check whether a header exceeds the server's limit.
Is 400 Bad Request an error on my side or the site's side?
Formally, status 400 belongs to the 4xx class of client errors: the server reports that the request is malformed. But server settings can provoke it too — for example, overly strict header-size limits. Start diagnosis by clearing cookies and cache, then check how the request is built.
Why does a 400 appear on only one site?
Almost certainly corrupted or bloated cookies for that specific domain are to blame. Each site stores its cookies separately, so the problem is isolated. Clear that site's data in browser settings or open it in incognito mode — if everything works there, cookies or cache are the cause.
How do I fix a 400 when posting JSON to an API?
Make sure the request body is valid JSON with no trailing commas or missing values, and that the Content-Type: application/json header matches the actual format. Run the request through curl -v to see what actually leaves for the server, and validate the JSON with any linter before sending.
Why does a long URL cause a 400?
Servers limit the length of the request line and the size of headers, usually to a few kilobytes. nginx and Apache answer an overlong URL with 414, but some servers and proxies collapse it into a generic 400, and long headers produce 400 on most stacks. The user fix is to shorten the link; the developer fix is to raise the limit or move data into the POST body.
Does reloading the page help with a 400 error?
A plain refresh rarely helps because the cause is usually stored data. A hard reload with a cache purge (Ctrl+F5) plus deleting the site's cookies is far more effective. If the error disappears afterward, client data was to blame; if not, the problem is in the request itself or the server configuration.