How to Fix a 400 Bad Request: The Part That Is the Server's Fault, and the Part That Is the Client's

Sean

Platform Writer

Jun 11, 2026
5 min read

A 400 Bad Request means the server received the request, the server understood the request syntactically (it parsed the HTTP, the headers, the URL), and the server decided the request was malformed in a way that the server could not process. The server is not telling the client what was wrong — the server is just saying “I refuse, the request is your problem.” The 400 is the catch-all for client-side errors that the server does not want to give a more specific code for (a missing required field, a malformed JSON body, an oversized cookie, a malformed URL, an oversized header). The interesting part is that half of the 400s are the client’s fault and half are the server’s fault, the seven places each lives, and the ten-minute debugging flow that turns a 400 from a guess into a fix.

The reason “how to fix 400 bad request” is its own question and not just “what is a 400” is that the question is the most common 4xx a developer is going to debug, and the question is the one that has the most “have you tried turning it off and on again” advice. The fix is in the request (the URL, the headers, the body, the cookies, the cache) or in the server (the validation, the URL parser, the proxy, the rate limiter), and the developer has to know which one to look at first.

How to fix a 400 bad request: the part that is the server's fault, and the part that is the client's

Table of contents

The short version

A 400 means the request was malformed, and the server is not telling the client what was wrong. The fix lives in one of seven client-side places (the URL, the headers, the cookies, the cache, the body, the encoding, the size) or one of seven server-side places (the validation, the URL parser, the proxy, the rate limiter, the WAF, the auth, the body parser). The right fix is in the place the request was malformed, and the developer has to know which place to look at first. The ten-minute debugging flow is: reproduce, isolate, inspect, fix, verify.

The part that is the client’s fault

A short, opinionated list of the four places the 400 is the client’s fault. The four are the ones a developer sees most often, and the four are the ones a developer can fix without touching the server.

The URL is malformed. A URL that has a typo, a malformed query string, a malformed path, a malformed fragment, a malformed scheme, or a malformed host is a URL that the server is going to reject. The fix is to check the URL character by character, and the fix is the lever that turns “the URL is wrong” into “the URL is right.”

The cookies are oversized or malformed. A request that has a Cookie header larger than the server’s limit (usually 4 KB, 8 KB, or 16 KB, depending on the server) is a request that the server is going to reject. The fix is to clear the cookies for the site (DevTools → Application → Cookies → Clear), the fix is the lever that turns “the cookies are too big” into “the cookies are the right size.”

The cache has a stale request. A request that was cached by the browser, the CDN, or the proxy is a request that may have been valid yesterday but is malformed today (a URL the server used to accept, a header the server used to accept, a body the server used to accept). The fix is to hard refresh the page (Cmd+Shift+R), the fix is the lever that turns “the cached request is wrong” into “the new request is right.”

The body is malformed. A POST, PUT, or PATCH request that has a malformed JSON body, a malformed XML body, a missing required field, a wrong content type, a wrong encoding, or a body that is too large is a request that the server is going to reject. The fix is to check the body in DevTools (Network → request → Payload), the fix is the lever that turns “the body is wrong” into “the body is right.”

The four are the floor. There is also the malformed header (a custom header with a value the server does not understand), the malformed multipart upload (a file upload with a missing boundary), the malformed WebSocket upgrade (a request that tries to upgrade a connection but the headers are wrong), and the malformed redirect (a request that has a Location header the server does not understand). The four are the ones a developer should know first, and the four are the ones a developer can fix without touching the server.

The part that is the server’s fault

A short, opinionated list of the four places the 400 is the server’s fault. The four are the ones a developer sees when the client is doing the right thing, and the four are the ones a developer has to fix in the application code or the server config.

The validation is too strict. A server that has a strict validator (an API that requires a specific JSON schema, a form that requires a specific field) is a server that is going to reject any request that does not match the schema. The fix is to relax the validator (accept optional fields, accept additional fields, accept the field with a default value), and the fix is the lever that turns “the validator is too strict” into “the validator is right.”

The URL parser is too strict. A server that has a strict URL parser (a URL with a specific character set, a URL with a specific encoding, a URL with a specific path format) is a server that is going to reject any URL that does not match the parser. The fix is to relax the URL parser (accept more characters, accept more encodings, accept more path formats), and the fix is the lever that turns “the URL parser is too strict” into “the URL parser is right.”

The body parser is too strict. A server that has a strict body parser (a JSON parser that requires a specific schema, an XML parser that requires a specific format, a multipart parser that requires a specific boundary) is a server that is going to reject any body that does not match the parser. The fix is to relax the body parser (accept more JSON, accept more XML, accept more multipart), and the fix is the lever that turns “the body parser is too strict” into “the body parser is right.”

The reverse proxy or load balancer has a limit. A reverse proxy (NGINX, HAProxy, Caddy, Cloudflare, AWS ALB) that has a header size limit, a body size limit, a URL length limit, a request line limit, or a timeout is a proxy that is going to reject any request that exceeds the limit. The fix is to increase the limit in the proxy’s config, and the fix is the lever that turns “the proxy is too strict” into “the proxy is right.”

The four are the floor. There is also the rate limiter that returns 400 instead of 429 (a misconfigured rate limiter), the WAF that returns 400 instead of 403 (a misconfigured Web Application Firewall), the auth middleware that returns 400 instead of 401 (a misconfigured auth middleware), and the custom error handler that converts a 422 into a 400 (a misconfigured custom error). The four are the ones a developer should know first, and the four are the ones a developer can fix in the server config.

The ten-minute debugging flow

A short, opinionated list of the ten-minute debugging flow. The flow is the one a developer follows when they are staring at a 400, and the flow is the one that turns a 400 from a guess into a fix.

Minute 0-1: reproduce the request. The developer opens DevTools (F12 in Chrome, Cmd+Option+I on macOS), the developer opens the Network tab, the developer reproduces the request (clicks the button, submits the form, hits the URL). The request is now visible in the Network tab, and the request has a 400 status code.

Minute 1-2: inspect the request. The developer clicks the request in the Network tab, the developer looks at the request headers, the request payload (body), the request cookies, and the response body. The response body usually has a hint (“missing field X”, “invalid JSON”, “URL too long”), and the hint is the source of truth for the fix.

Minute 2-3: check the URL. The developer looks at the request URL character by character, the developer checks for typos, the developer checks for malformed query strings, the developer checks for malformed paths. The URL is the most common source of a 400, and the URL is the one a developer should check first.

Minute 3-4: check the body. The developer looks at the request body (Payload tab in DevTools), the developer checks for malformed JSON, the developer checks for missing required fields, the developer checks for wrong content types, the developer checks for body size. The body is the second most common source of a 400, and the body is the one a developer should check second.

Minute 4-5: check the headers. The developer looks at the request headers, the developer checks for malformed custom headers, the developer checks for the wrong content type, the developer checks for the wrong authorization header, the developer checks for the wrong accept header. The headers are the third most common source of a 400, and the headers are the one a developer should check third.

Minute 5-6: check the cookies. The developer opens DevTools → Application → Cookies, the developer looks at the cookies for the site, the developer checks the size of the cookies, the developer checks for malformed cookies. The cookies are the fourth most common source of a 400, and the cookies are the one a developer should check fourth.

Minute 6-7: clear the cache and cookies. The developer hard refreshes the page (Cmd+Shift+R), the developer clears the cookies for the site (Application → Cookies → Clear). The cache and cookies are the fifth most common source of a 400, and the cache and cookies are the ones a developer should clear if the request is still 400.

Minute 7-8: try in an incognito window. The developer opens the URL in an incognito window (Cmd+Shift+N), the developer tries the request. The incognito window has no cookies, no cache, no extensions, and the incognito window is the cleanest possible test environment. The incognito window is the right answer for “is this my browser or is this the server.”

Minute 8-9: try in a different browser. The developer opens the URL in a different browser (Firefox, Safari, Edge), the developer tries the request. The different browser rules out a Chrome-specific issue, a Firefox-specific issue, a Safari-specific issue, and an Edge-specific issue. The different browser is the right answer for “is this my browser or is this the server.”

Minute 9-10: try with curl. The developer opens a terminal, the developer runs the request with curl -v (verbose), the developer looks at the request and the response. The curl request is the cleanest possible test (no cookies, no cache, no extensions, no JavaScript), and the curl request is the source of truth for “what does the server actually see.” The curl request is the right answer for “what is the server actually rejecting.”

The ten minutes are the flow. A developer who follows the flow is a developer who can fix a 400 in 10 minutes. A developer who skips the flow is a developer who is going to spend an hour guessing.

The seven fixes that work in the browser

A short, opinionated list of the seven fixes that have actually worked in real 400 debugging. The seven are the ones a developer can try without leaving the browser, and the seven are the ones a developer should know.

Hard refresh the page. Cmd+Shift+R (macOS) or Ctrl+Shift+R (Windows/Linux). The fix clears the browser’s cache and reloads the page from the server. The fix is the right answer for a 400 caused by a cached request, and the fix is the lever that turns “the cached request is wrong” into “the new request is right.”

Clear the cookies for the site. DevTools → Application → Cookies → Clear All. The fix clears all the cookies for the site and reloads the page. The fix is the right answer for a 400 caused by oversized or malformed cookies, and the fix is the lever that turns “the cookies are wrong” into “the cookies are cleared.”

Open in an incognito window. Cmd+Shift+N (macOS) or Ctrl+Shift+N (Windows/Linux). The fix opens the page in a window with no cookies, no cache, and no extensions. The fix is the right answer for a 400 caused by the browser’s state, and the fix is the lever that turns “my browser is wrong” into “my browser is clean.”

Disable the browser extensions. Open the extensions page (chrome://extensions or about:addons), disable all the extensions, reload the page. The fix is the right answer for a 400 caused by a browser extension (an ad blocker, a privacy extension, a security extension that is blocking the request), and the fix is the lever that turns “the extension is wrong” into “the extension is disabled.”

Try a different browser. Firefox, Safari, Edge, Brave, Arc. The fix is the right answer for a 400 caused by a Chrome-specific issue, a Firefox-specific issue, a Safari-specific issue, or an Edge-specific issue, and the fix is the lever that turns “my browser is wrong” into “the other browser is right.”

Update the browser. Check for updates (Chrome → About Chrome, Firefox → About Firefox), update to the latest version. The fix is the right answer for a 400 caused by a browser bug, a browser regression, or a browser incompatibility, and the fix is the lever that turns “the browser is buggy” into “the browser is up to date.”

Reset the browser settings. Reset the browser to its defaults (Chrome → Settings → Reset, Firefox → Help → Troubleshooting Information → Refresh Firefox). The fix is the right answer for a 400 caused by a misconfigured browser, a corrupted profile, or a corrupted cache, and the fix is the lever that turns “the browser is misconfigured” into “the browser is fresh.”

The seven are the floor. There is also the “disable the antivirus” fix (an antivirus that is intercepting the request and breaking it), the “disable the VPN” fix (a VPN that is changing the request headers or the cookies), and the “try on a different network” fix (a network that is intercepting the request and breaking it). The seven are the ones a developer should know first, and the seven are the ones a developer can try without leaving the browser.

The seven fixes that work in the application

A short, opinionated list of the seven fixes that have actually worked in real 400 debugging. The seven are the ones a developer can try in the application code or the server config, and the seven are the ones a developer should know.

Check the request in DevTools Network tab. The developer clicks the failed request in the Network tab, the developer looks at the request URL, the request headers, the request body, the response body. The request is the source of truth for what the server is seeing, and the request is the lever that turns “I do not know what the server is rejecting” into “I know what the server is rejecting.”

Look at the server’s error log. The developer opens the server’s error log (the application’s log, the framework’s log, the reverse proxy’s log, the load balancer’s log), the developer searches for the request’s timestamp, the developer reads the error. The server’s log is the source of truth for what the server is rejecting, and the server’s log is the lever that turns “I do not know what the server is rejecting” into “I know what the server is rejecting.”

Test the request with curl. The developer opens a terminal, the developer runs curl -v -X POST -H "Content-Type: application/json" -d '{"key": "value"}' https://api.example.com/endpoint, the developer looks at the request and the response. The curl request is the cleanest possible test (no cookies, no cache, no extensions, no JavaScript), and the curl request is the source of truth for “what does the server actually see.”

Test the request with Postman or Insomnia. The developer opens Postman or Insomnia, the developer constructs the request manually, the developer sends the request. Postman and Insomnia are the right answer for a developer who wants a UI for constructing requests, and the right answer is the lever that turns “I cannot test the request in the browser” into “I can test the request in Postman.”

Add request/response logging in the application. The developer adds a logger that logs every incoming request (URL, method, headers, body), the developer adds a logger that logs every outgoing response (status, body). The logger is the right answer for a developer who cannot reproduce the 400 with curl or Postman, and the logger is the lever that turns “I cannot see what the server is seeing” into “I can see what the server is seeing.”

Add a custom error response from the server. The developer changes the server’s error response from a generic 400 to a specific 400 with a JSON body that includes the field that failed, the validation rule, the request id. The custom error is the right answer for a developer who is debugging an API, and the custom error is the lever that turns “I do not know what is wrong” into “I know what is wrong.”

Fix the validation in the application. The developer updates the validator to be more permissive (accept optional fields, accept additional fields, accept the field with a default value), the developer updates the validator to be more specific (return a specific error code for each failure). The fix is the right answer for a developer who is debugging a 400 caused by a strict validator, and the fix is the lever that turns “the validator is too strict” into “the validator is right.”

The seven are the floor. There is also the “fix the URL parser in the server” fix, the “fix the body parser in the server” fix, the “increase the proxy’s body size limit” fix, and the “fix the rate limiter” fix. The seven are the ones a developer should know first, and the seven are the ones a developer can try in the application code or the server config.

The mistakes that turn a 400 into a debugging session

A short, opinionated list of the four mistakes that turn a 400 into a 30-minute debugging session. The four are the ones a developer will make, and the four are the ones a developer should know to avoid.

Skipping the response body. A developer who looks at the status code (400) and does not look at the response body is a developer who is going to guess at the cause instead of reading the cause. The fix is to always read the response body, and the fix is the lever that turns “I do not know what is wrong” into “I know what is wrong.”

Skipping the request payload. A developer who looks at the request URL and does not look at the request body is a developer who is going to miss the malformed JSON, the missing field, the wrong content type. The fix is to always look at the request payload, and the fix is the lever that turns “I do not know what is wrong” into “I know what is wrong.”

Trying the same fix five times. A developer who tries the same fix (e.g. clearing the cookies) five times is a developer who is not learning anything from each attempt. The fix is to try a different fix, and the fix is the lever that turns “I am stuck” into “I am making progress.”

Restarting the server without checking the logs. A developer who restarts the server without checking the logs is a developer who is going to lose the error that would have told them the cause. The fix is to check the logs first, then restart, and the fix is the lever that turns “I do not know what is wrong” into “I know what is wrong.”

The four are the floor. There is also the “asking the user to clear their cookies” mistake (the user’s cookies are usually fine, the problem is usually in the application), the “upgrading the framework” mistake (the framework upgrade usually does not fix the 400, the framework upgrade usually breaks something else), and the “rolling back the deploy” mistake (the rollback usually does not fix the 400, the rollback usually makes the user unable to use the site). The four are the ones a developer should know first, and the four are the ones a developer should avoid.

How this fits the rest of the stack

A 400 is rarely the whole problem. The 400 is the symptom. The cause is the request, the validation, the URL parser, the proxy, or the rate limiter. The platform that handles the 400 well is the platform where the developer can see the request, the response, the server log, the validation rule, and the proxy config in one place.

The services layer is the part of the platform that runs the long-lived API the 400 is happening in. The database layer is the part that holds the data the API is querying. The static layer is the part that hosts the static site the API serves. The environment variables are the part that holds the secrets the API needs at runtime.

A platform that handles 400s well is a platform where the logs are searchable, the request id is on every log line, the validation rules are visible, the URL parser is configurable, the proxy limits are visible, and the deploy history is one click to roll back. A platform that handles 400s well is a platform where the team’s debugging time goes to fixing the bug, not to finding the bug.

For a team that wants to see the full cost of the project before it commits, the RunxBuild hosting calculator shows the line items together. The API, the database, the storage, the worker, the bandwidth — each one is a separate number, and the team’s mental model for the platform is the sum of those numbers.

FAQ

What is a 400 Bad Request?

A 400 Bad Request means the server received the request, the server understood the request syntactically (it parsed the HTTP, the headers, the URL), and the server decided the request was malformed in a way that the server could not process. The 400 is the catch-all for client-side errors that the server does not want to give a more specific code for (a missing required field, a malformed JSON body, an oversized cookie, a malformed URL, an oversized header).

Is a 400 the server’s fault or the client’s fault?

It depends. About half of 400s are the client’s fault (the URL is wrong, the body is malformed, the cookies are oversized, the cache is stale) and about half are the server’s fault (the validation is too strict, the URL parser is too strict, the body parser is too strict, the proxy has a limit). The right answer is to check the request first, then check the server, and the developer should be ready to fix either one.

How do I fix a 400 Bad Request in the browser?

The seven fixes that work in the browser are: hard refresh the page (Cmd+Shift+R), clear the cookies for the site (DevTools → Application → Cookies → Clear), open in an incognito window (Cmd+Shift+N), disable the browser extensions, try a different browser, update the browser, and reset the browser settings. The seven are the ones a developer can try without leaving the browser, and the seven are the ones a developer should know.

How do I fix a 400 Bad Request in the application?

The seven fixes that work in the application are: check the request in DevTools Network tab, look at the server’s error log, test the request with curl, test the request with Postman or Insomnia, add request/response logging in the application, add a custom error response from the server, and fix the validation in the application. The seven are the ones a developer can try in the application code or the server config, and the seven are the ones a developer should know.

What is the difference between 400 and 422?

A 400 is “the request is malformed in a way the server could not process” — a generic catch-all for client-side errors. A 422 is “the request is well-formed but contains semantic errors” — a specific code for validation errors (a missing required field, a wrong value type, a business rule violation). The codes are not interchangeable, and a 400 that should be a 422 is a 400 that is hiding the validation failure from the client.

What is the difference between 400 and 401?

A 400 is “the request is malformed” — a client-side error that the client could fix. A 401 is “the request is unauthenticated” — the client needs to provide credentials (a token, a session, an API key) to access the resource. The codes are not interchangeable, and a 400 that should be a 401 is a 400 that is hiding the auth requirement from the client.

How do I prevent 400s in production?

Add input validation that returns specific error messages (a 400 with a JSON body that includes the field that failed, the validation rule, the request id), add a request size limit, add a URL length limit, add a header size limit, add a rate limiter that returns 429 (not 400), add a WAF that returns 403 (not 400), and add an auth middleware that returns 401 (not 400). The seven are the right answer for a developer who wants to ship an API that returns useful 400s instead of generic ones.