Use Nginx’s error_page directive to map an existing HTTP 400 response to a local HTML page or to a client-visible redirect. For a locally generated page that still returns status 400, define the mapping in the server block that handles the request, serve the target from an internal location, test with return 400;, and reload Nginx. If the 400 comes from an upstream application, enable proxy_intercept_errors on; in the proxied location first.
Antihost offers Linux VPS plans with full root access, unlimited traffic on a 1 Gbps port and a 14-day free trial.
The shortest working configuration
Create the custom file, for example /var/www/errors/custom-400.html, then add this configuration to the virtual server that receives the request:
As an Amazon Associate I earn from qualifying purchases.
Recommended Free Tools
server {
listen 80;
server_name example.com;
error_page 400 = /custom-400.html;
location = /custom-400.html {
root /var/www/errors;
internal;
}
}
The error_page directive does not create a bad request. It tells Nginx what to do after a 400 status already exists. The equals form, = /custom-400.html, makes the intent explicit: render the custom resource while retaining the original 400 response status. The internal directive prevents visitors from requesting the error document as a normal public URL.
After saving the file, validate and reload the configuration:
#1 Best Overall
nginx -t
nginx -s reload
On systems managed by systemd, an equivalent reload is commonly performed with systemctl reload nginx. Use the command appropriate to your installation.
What Nginx is doing when an error page is configured
Nginx maps an error status to a URI or a named location. Its official guide describes error_page as a way to return a custom page with an error code, substitute a different response code, or redirect the browser to another URI. The directive is therefore an error-handling rule, not an error generator.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →- Generate a test or policy error: use
return 400;or let an application produce the 400. - Map that status: use
error_page 400 .... - Render privately: point the mapping at a local resource in an
internallocation. - Redirect publicly: specify an explicit 3xx response and a URL when the browser must navigate elsewhere.
For an internal URI error page, Nginx performs an internal redirect. For request methods other than GET and HEAD, that internal redirect changes the method to GET. This is useful for a static document, but it matters if you expect a POST body or another non-GET method to reach the error-page URI.
Serve a custom page and keep the 400 status
Use an exact-match internal location
Place the file under the directory named by root. With root /var/www/errors; and the URI /custom-400.html, Nginx looks for /var/www/errors/custom-400.html.
server {
listen 80;
server_name example.com;
error_page 400 = /custom-400.html;
location = /custom-400.html {
root /var/www/errors;
internal;
}
}
location = is an exact match, so the error document cannot accidentally fall through to a broad application or proxy location. The file must exist and be readable by the Nginx worker process. If the URI is sent back through a proxy instead of being served locally, the upstream may generate a second response or an error loop.
Rank #2
Generate a deliberate 400 for testing
During a controlled test, add a temporary rule to the relevant server or location:
location = /test-bad-request {
return 400;
}
Request /test-bad-request with a client that shows response headers and status. You should see a 400 response and the contents of custom-400.html. Remove the test rule after verification; it is not needed for naturally occurring errors.
Do not expose the file as a normal endpoint
Without internal, anyone could request /custom-400.html directly. Keeping the location internal makes it available to Nginx’s error flow while rejecting ordinary external requests to that URI. If you intentionally want a public help page, use a separate public location and do not rely on the error-page URI for normal navigation.
Choose between an internal page and a browser redirect
These configurations produce different client behavior. Select one based on whether the original request should remain a 400 at the HTTP layer.
| Goal | Configuration | What the client receives | Typical use |
|---|---|---|---|
| Render a local page while preserving 400 | error_page 400 = /custom-400.html; |
HTML from the internal URI with status 400 | Branding, instructions, or a support reference for malformed requests |
| Map to a local page with the basic URI form | error_page 400 /custom-400.html; |
Nginx handles the error through the configured URI | Simple server-level error-page mapping |
| Send a client-visible redirect | error_page 400 =302 https://example.com/bad-request; |
A 302 response with a Location header |
Move the browser to a separate, public explanation page |
The explicit redirect form is different from an internal error-page URI: the browser receives a redirect and makes a new request. Choose the redirect status deliberately. A 302 is temporary; use another status only when its caching and permanence match your migration plan. An external redirect also exposes the destination and can make debugging the original malformed request less direct.
Handle 400 responses from a reverse proxy
A reverse proxy commonly has two possible sources of a 400: Nginx itself or the upstream application. If the application returns 400 and Nginx simply passes it through, the server-level error page will not replace it unless proxy interception is enabled.
server {
listen 80;
server_name example.com;
error_page 400 = /custom-400.html;
location / {
proxy_pass http://backend;
proxy_intercept_errors on;
}
location = /custom-400.html {
root /var/www/errors;
internal;
}
}
proxy_intercept_errors on; tells Nginx to intercept proxied responses with status 300 or greater and process them through its error_page rules. With interception disabled, the upstream response is passed directly to the client, so the upstream’s body and status remain visible.
Prevent the error page from going back upstream
Keep the custom URI in an exact local location. If /custom-400.html is covered only by location /, the request can be sent to backend, where the application may return another 400, a 404, or an authentication response. That can create a loop or hide the intended document. The exact internal location shown above takes precedence and serves the file from disk.
Separate upstream and Nginx-generated failures
Test both paths. A temporary return 400; proves that Nginx’s own mapping works. A request that makes the upstream application return 400 proves that interception and proxy-location scope are correct. Passing the first test does not prove the second.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Put the directive in the server that actually handles the request
Nginx applies an error response using the error_page directive in the server currently fulfilling the request. A rule in the wrong virtual server has no effect, even if another server block contains an identical hostname-looking configuration.
Rank #4
HTTP and HTTPS can use different server blocks
If port 80 and port 443 are configured in separate server blocks, add the mapping to each block that should present the custom page. A test over HTTPS will not use a rule that exists only in the HTTP server.
Invalid or missing Host headers
A request with an invalid, missing, or unexpected Host header may be handled by a default server rather than the named virtual server you normally edit. Confirm which listener and server block received the request before diagnosing the page mapping. The same issue can occur when several addresses, ports, or wildcard names compete for a request.
Location-level rules and inheritance
Keep a server-wide mapping at server scope when all locations should use the same document. If only one proxied route needs interception or a different error page, configure the relevant behavior in that location and verify that the chosen scope is not overridden by a more specific rule. The key test is always the server and location that actually processed the failing request.
Free tools Windows power users keep installed
One-click scans. No signup required.
Why some 400 errors do not follow an ordinary location test
Not every 400 is produced after normal URI and location processing. Nginx has parser-level and protocol-specific failure paths. Its source identifies specialized conditions that are rendered to clients as 400-class responses:
- 494: request-header or cookie-size problems, presented as a 400 response.
- 495: a TLS certificate error, presented as a 400 response.
- 496: a client certificate was not provided, presented as a 400 response.
- 497: plain HTTP was sent to an HTTPS port, presented as a 400 response.
These failures can occur before ordinary location processing. As a result, a custom page that appears for return 400; may not appear for an oversized header, a client-certificate failure, or an HTTP request sent to the TLS listener. Test the exact failure mode and the relevant listener rather than treating one successful location test as proof that every 400 path is covered.
Keep the protocol context in mind
A 497-style failure, for example, belongs to the HTTPS listener even though the client used plain HTTP. Editing only the port-80 server will not change the response. Certificate-related cases likewise depend on the TLS server configuration and can happen before an application location is selected.
Do not assume all 400 bodies have the same source
The visible status alone does not identify the origin. Record whether the response came from Nginx’s parser, the TLS layer, a proxy, or the application. Response headers, the listener used, and the server block selected are more useful clues than the number 400 by itself.
A reliable troubleshooting sequence
- Validate syntax: run
nginx -t. Fix every reported error before reloading. - Reload the active instance: use
nginx -s reloador the service manager’s reload command, then confirm that the running process accepted the new configuration. - Check the file path: verify that the custom HTML file exists exactly under the configured
rootand is readable by the Nginx worker. - Check the URI location: make sure the error-page URI has an exact local location and is marked
internal; confirm it is not caught by a proxy location. - Test Nginx-generated 400: use a temporary
return 400;rule and inspect both the status and response body. - Test the upstream path: if the application generates the 400, confirm
proxy_intercept_errors on;is present in the proxied location. - Identify the server block: repeat the test over the correct scheme and port, and check behavior with the Host header that the client actually sends.
- Classify the failure: determine whether it is an ordinary application/location error or a parser- or protocol-level variant such as 494, 495, 496, or 497.
- Check for loops: ensure the custom URI is not proxied, rewritten back to itself, protected by an authentication rule that fails, or missing from the filesystem.
Common configuration mistakes and their fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| The default Nginx page still appears | The edited server block is not handling the request, or the configuration was not reloaded | Run nginx -t, reload, and verify the scheme, port, Host header, and default-server selection |
| The upstream’s 400 body is unchanged | Proxy interception is off | Add proxy_intercept_errors on; to the location containing proxy_pass |
| The custom URI returns a proxy response | The URI matches a broad proxied location | Add an exact local location for the error file before relying on the broad route |
| The custom page returns 404 | The file is not beneath the configured root, is misspelled, or is unreadable |
Check the complete filesystem path and worker read permissions |
| A direct request can open the error document | The location is not internal | Add internal; to the custom-page location |
| The test works but a real malformed request does not | The real failure is parser- or protocol-level | Identify the specialized 400 path and test the listener where it occurs |
| A POST error page behaves unexpectedly | Internal error-page processing changes non-GET/HEAD methods to GET | Design the page as a static GET resource and do not depend on the original request body |
Use a named location when error handling needs more control
For a simple static document, a URI target is easiest to audit. More involved setups can route the error to a named location so that Nginx can apply a dedicated set of directives before serving the response. The same scope rules still apply: define the error mapping in the server that fulfills the request, keep a local error handler out of the upstream route, and test the resulting status and body.
Do not introduce a named location merely to replace a one-file static page. Extra routing can make loops, authentication interactions, and proxy interception harder to diagnose. Start with an exact internal URI and move to a named handler only when the response needs additional, deliberately configured processing.
Design the custom 400 document for malformed requests
A 400 page should explain that the server could not understand the request without exposing parser details, request headers, cookies, credentials, or upstream diagnostics. Include a stable support path or request identifier only if your logging system supplies one safely. The page should work as a standalone static document because parser-level failures may happen before application rendering is available.
- Use a concise explanation rather than blaming the visitor.
- Provide a safe link back to the site’s home or help area.
- Do not echo untrusted request data into the HTML.
- Keep the document available without the application being healthy.
- Make it readable when JavaScript, cookies, or the upstream service are unavailable.
Deployment checklist
- The HTML file exists under the configured
root. - The Nginx worker can read the file.
- The mapping is in every HTTP or HTTPS server block that needs it.
- The custom URI uses an exact local location and
internal. - The page is not sent back to the upstream proxy.
proxy_intercept_errors on;is enabled where an upstream must be replaced.nginx -tsucceeds and the active instance has been reloaded.- A deliberate
return 400;test has been completed. - The real failing request has been tested separately.
- Parser- and protocol-level cases have been considered on the correct listener.
Decision guide: which configuration should you use?
Use a local internal page when the client should still receive an HTTP 400 and you want the response body branded or explained by your server. Use proxy_intercept_errors on; when the status originates in an upstream and Nginx should replace its body. Use an explicit =302 (or another intentional redirect status) only when the browser must navigate to a separate public URL. If one configuration works for a synthetic return 400; but not for production failures, investigate server selection and parser-level variants before changing the HTML or adding rewrites.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




