Free tools Windows power users keep installed
One-click scans. No signup required.
iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Antihost offers Linux VPS plans with full root access, unlimited traffic on a 1 Gbps port and a 14-day free trial.
Use NGINX’s error_page directive to map an existing HTTP 400 response to an HTML file or named location. Keep the response as a 400 with error_page 400 = /custom-400.html;, or send the browser elsewhere with an explicit 3xx code. If the 400 comes from a reverse-proxied application, enable proxy_intercept_errors on; so NGINX can apply that mapping.
The basic configuration
Create the error document, then add an error_page mapping and an internal location for it in the server block that handles the request:
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;
}
}
With this layout, NGINX serves /var/www/errors/custom-400.html when a request ends with status 400. The internal directive prevents a client from requesting the error document as a normal public URL; NGINX can use it during error handling, but a direct request receives an access denial.
error_page handles an error that already exists. It does not create a 400 response by itself. To generate a predictable 400 for testing or for a deliberate rule, use return 400; in a suitable location and let error_page render the page.
#1 Best Overall
Choose whether the response stays 400 or redirects
There are two different outcomes that are often called a “redirect.” An internal error-page transfer keeps the request inside NGINX and can preserve the 400 status. A client-visible redirect sends a 3xx response and makes the browser request another URL.
| Goal | Configuration form | What the client receives | Use when |
|---|---|---|---|
| Serve a local page and retain the error status | error_page 400 = /custom-400.html; |
The custom HTML with status 400 | Monitoring, API clients, and clients should still recognize the request as invalid |
| Serve a local page and allow NGINX’s normal error handling | error_page 400 /custom-400.html; |
Normally an internally generated error response | You do not need to explicitly control the resulting status |
| Send the browser to another URL | error_page 400 =302 https://example.com/bad-request; |
A 302 response followed by a new request | The destination is a separate route, application, or site |
The equals form controls the response code. With = followed by a URI, NGINX can serve the target while retaining the original 400. With =302 (or another explicit 3xx code), NGINX returns that redirect status instead. A URI error-page transfer is internal; for methods other than GET and HEAD, NGINX changes the method to GET during that transfer. That behavior matters if the failing request was a POST, PUT, or another non-GET method.
Build the local custom page step by step
- Create the file. Save an HTML document at
/var/www/errors/custom-400.html, or choose another directory that the NGINX worker can read. Keep the page self-contained if it must also work while an upstream application is unavailable. - Add the mapping in the correct server block. Put
error_page 400 = /custom-400.html;at server scope unless only one location should use it. The relevant block is the one that actually fulfills the request, not necessarily the first block in the configuration file. - Add an exact-match location. Use
location = /custom-400.htmlso the path is unambiguous. Setrootto the directory containing the file and addinternal;. - Check the syntax. Run
nginx -t. Do not reload if the test reports an error; fix the indicated file, directive, or path first. - Reload NGINX. Reload using the service method for your operating system after a successful syntax test. A reload applies the new configuration without requiring you to stop the web server.
- Trigger a controlled 400. Temporarily add
return 400;in a test-only location, request that URL, and verify both the HTML and the HTTP status. Remove the test rule after validation.
If the page is missing, unreadable, or mapped to the wrong filesystem path, NGINX may fall back to its default error response or produce another file error. Check the effective path formed by the root and URI: with the example above, the expected file is exactly /var/www/errors/custom-400.html.
Handling 400 responses from a reverse proxy
When an application server returns the 400, NGINX normally passes that upstream response directly to the client. To make NGINX replace it with your custom page, enable interception in the proxied location:
Rank #2
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 off, the upstream body and status are returned instead, so the local custom page never runs.
Prevent an interception loop
Keep the error-page location outside the broad proxy location, or explicitly exclude it from proxying. If /custom-400.html is itself sent to the backend, the backend can return another 400 and send NGINX back through the same mapping. An exact location for the file, as shown above, takes precedence over location / and serves the local document directly.
Decide whether the upstream body is needed
Interception replaces the upstream response with the configured target. If the application’s JSON error body or diagnostic headers are required by API clients, do not intercept that route, or use a separate location policy for browser-facing HTML requests. A custom page is most useful when a consistent presentation is more important than preserving the upstream payload.
Place the directive where NGINX really handles the request
NGINX applies an error response using the error_page directive in the server that is currently fulfilling the request. This makes configuration scope a common source of surprises.
Separate HTTP and HTTPS servers
If port 80 and port 443 use separate server blocks, placing the rule in only one block affects only that listener. Add the mapping and the local error location to each block that should display the page, or centralize the behavior through an arrangement that both blocks include.
Default servers and invalid Host headers
A request with an unknown or malformed Host header may be handled by the default server rather than the named virtual host you were editing. Put a suitable mapping in that default server when those failures must use the same page, and verify the selected server with logs and a request that supplies the exact host name.
Location-level rules
An error_page declared inside a location applies within that location’s context. Use location scope when only one application path should be customized; use server scope for a site-wide policy. Avoid assuming that a rule in one virtual host or location automatically covers another.
Why some 400 errors do not follow the page you expect
Not every 400 is produced after ordinary location processing. NGINX has parser-level and protocol-specific failure paths, and several internal status codes are rendered to clients as HTTP 400.
Rank #4
| Internal condition | Client-visible result | Typical cause |
|---|---|---|
| 400 | 400 Bad Request | General malformed request handling |
| 494 | 400 Bad Request | Request header or cookie is too large |
| 495 | 400 Bad Request | Client TLS certificate verification error |
| 496 | 400 Bad Request | Client did not provide a required TLS certificate |
| 497 | 400 Bad Request | Plain HTTP was sent to an HTTPS port |
These conditions can occur before NGINX reaches the location you are testing. Consequently, a deliberate return 400; proves only that ordinary error handling works; it does not prove that a header-size, certificate, or protocol failure will use the same path. Test each listener and failure mode that matters to your deployment.
Internal page versus browser-visible redirect
Use an internal page when status semantics matter
An internal page keeps the client-facing status at 400 when you use the equals-URI form. That is generally the right choice for malformed requests, API consumers, automated monitors, and security controls that need a non-success status. The browser displays the custom content without changing the address bar to another resource.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsUse an explicit 3xx redirect when a different route is the product requirement
An explicit form such as error_page 400 =302 https://example.com/bad-request; tells the client to make a new request to the destination. Choose the status deliberately: a temporary redirect communicates a different intent from a permanent one. The destination must be reachable by the client, and the new request is no longer the original 400 response.
Test the configuration systematically
Use a small matrix rather than relying on one browser refresh:
- Local, deliberate error: a temporary
return 400;confirms that the directive, file path, and page content work. - Upstream-generated error: make the backend return 400 and confirm that
proxy_intercept_errors on;changes the response to the local page. - Status check: inspect the response headers with an HTTP client and verify whether the result is 400, 302, or another code chosen in the configuration.
- HTTP and HTTPS: test both listeners when they have separate server blocks.
- Host selection: send the intended host name and an unknown host to confirm which virtual server handles each request.
- Parser-level cases: test only in a controlled environment, using an oversized header or cookie, certificate failure, and HTTP sent to an HTTPS port when those cases are relevant.
After testing, remove deliberate failure rules and keep only the production mapping. Review access and error logs for the selected server, upstream status, and final response code; those entries help distinguish a wrong server block from a missing file or an un-intercepted upstream response.
Troubleshooting checklist
The default NGINX page still appears
- Run
nginx -tand reload after every accepted edit. - Confirm that the request reached the server block containing the rule, especially when HTTP, HTTPS, and default servers differ.
- Confirm the file exists at the exact path produced by
rootplus the error-page URI. - Check that the NGINX worker can read the file and its parent directories.
- Ensure the target URI is not being proxied by a broader location.
The upstream’s 400 page appears instead
- Add
proxy_intercept_errors on;to the location that containsproxy_pass. - Verify that the upstream really returns status 400; a different status needs its own
error_pagemapping. - Check whether the request failed at the NGINX parser before proxying; parser-level failures never reach the application.
The browser follows an unexpected redirect
- Look for
=301,=302, or another explicit status in theerror_pageline. - Use
= /custom-400.htmlwhen the desired result is a local page with a 400 response, not a client-visible redirect. - Remember that an internal URI transfer changes non-GET and non-HEAD methods to GET.
The page works for one URL but not another
- Check whether the second request is served by another location or virtual server.
- Check whether it uses HTTPS, an unknown host, or a different listener.
- Determine whether it is an internal 400, an upstream 400, or one of the protocol-specific variants.
Recommended production pattern
For a normal site-wide custom document, keep the page in a readable local directory, map 400 at server scope, use an exact internal location, and preserve the status with the equals-URI form. For proxied applications, add interception only where replacing upstream errors is intentional. Maintain separate tests for ordinary request validation and parser-level protocol failures, because a successful test of one path does not establish that every 400 variant follows it.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →The essential division is simple: return 400; or an upstream/parser failure produces the error; error_page chooses the response representation; proxy_intercept_errors on; lets NGINX apply that choice to qualifying upstream responses.
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.

