DriversRecommendedOutdated drivers can make a good PC feel brokenScan driver issues before chasing fixes manually.Scan NowHalloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PC×
Skip to content
World desk12 min

How to Create Custom Nginx Error Pages (404, 403, and 5xx)

A practical guide to mapping Nginx errors to static HTML, application handlers, named locations, or redirects—while preserving the right status, method, URL, and security posture.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The reliable pattern is to create a static HTML file beneath the active Nginx root, map an HTTP status to that file with error_page, mark the file location internal, validate the configuration, and reload Nginx. For example, error_page 404 /404.html; serves a branded page without changing the URL or normally changing the 404 status.

What a custom Nginx error page actually does

Nginx generates an error response when it cannot satisfy a request itself or when an upstream application returns an error that Nginx handles. A missing static file, for example, produces HTTP 404 by default. The error_page directive tells Nginx what content or handler to use when a specified status occurs.

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The directive accepts a status code, an optional response override, and a target URI, named location, or external URL:

error_page code ... [=[response]] uri;

It is valid in the http, server, and location contexts, and inside if in a location. Put it in the narrowest context that should own the behavior. A rule in one virtual server does not automatically affect an unrelated server block.

For a local target, Nginx performs an internal redirect. The browser keeps its original URL, while Nginx internally requests the error document. For methods other than GET and HEAD, that internal request uses GET. This matters if a failed POST, PUT, or DELETE must retain its method or request body.

The simplest working 404 page

1. Put the HTML file under the active document root

Suppose the virtual server uses /var/www/example as its root. Create /var/www/example/404.html:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Page not found</title>
</head>
<body>
  <main>
    <h1>We couldn't find that page</h1>
    <p>The address may be mistyped, or the page may have moved.</p>
    <p><a href="/">Return to the home page</a></p>
  </main>
</body>
</html>

The URI /404.html maps to that file because Nginx appends the request URI to the configured root. If the file is outside the active root, the internal redirect reaches another missing file and you will see a second 404 instead of the custom content.

2. Add the mapping to the correct server block

server {
    root /var/www/example;

    error_page 404 /404.html;

    location = /404.html {
        internal;
    }
}

internal is optional hardening, not a requirement for rendering. It prevents visitors from requesting the error document directly. A direct request to an internal location intentionally receives a 404.

3. Validate and reload

After editing the file, validate the configuration and then reload the running process:

nginx -t
nginx -s reload

Run these commands with the same privileges and configuration path used by your installation. If your packaging uses a service manager, an equivalent reload command is appropriate. If nginx -t is not recognized, consult the installed binary’s command-line help before changing a live configuration.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

4. Test the actual virtual host

Request a path that does not exist on the intended hostname. Check both the HTTP status and the response body:

curl -i https://example.com/path-that-does-not-exist

You should see a 404 response with your HTML. Also inspect the configured access.log and error.log; they reveal which server handled the request, which URI failed, and whether the error document itself could be opened.

Use one page for several status codes

When the same explanation and recovery link make sense for multiple server failures, list the codes on one directive. This is the standard shared 5xx fallback:

error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;

The first rule handles only 404. The second maps internal server errors, bad gateway responses, temporary unavailability, and gateway timeouts to one file. Create /var/www/example/50x.html under the same root and keep its wording general enough to cover each condition.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

You can group other codes when the user action is identical, but do not hide materially different situations behind an unhelpful message. A 403 usually means the resource exists but access is denied; a 404 means Nginx could not find it. Separate pages can explain those next steps more accurately.

When to give 403 its own page

A forbidden response often needs different guidance from a missing-page response. A 403 page can direct an authenticated user to sign in, explain that access is restricted, or provide a support contact. Do not include filesystem paths or permission diagnostics in the public HTML. If revealing whether a protected resource exists would disclose sensitive information, review whether the wording of your 403 and 404 responses should intentionally be similar.

Keep 5xx wording deliberately general

The same 50x.html file may be displayed for an Nginx failure, an unavailable upstream, or a gateway timeout. Say that the service is temporarily unable to complete the request and provide a safe retry or support path. Do not promise that the problem is fixed, and do not expose upstream hostnames, stack traces, credentials, or internal paths.

Choose the right error-page target

Local files, explicit response overrides, named locations, and external redirects behave differently. Select the form based on the status, URL, method, and backend behavior you need.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Configuration form Keeps original status? Changes browser URL? Changes method? Typical use
error_page 404 /404.html; Yes, unless another directive overrides it No Non-GET/HEAD requests become GET during the internal redirect Branded static 404 or 50x content
error_page 404 =404 /404.html; Explicitly sets 404 No Internal redirect rules apply Guaranteeing a selected status while serving a local or application page
error_page 404 = /404.php; The upstream handler can determine the returned status No Internal redirect rules apply Passing an error request to an application endpoint
error_page 404 = @fallback; The named location or backend decides No Preserves the original URI and method for error processing Proxy or application fallback that must retain request details
error_page 404 =301 https://example.net/notfound.html; No; it returns the selected redirect status Yes The browser follows the redirect Permanent migration to another address

Serve a local page while selecting the response status

The equals form lets you choose the status sent to the client:

error_page 404 =404 /404.html;

Without an explicit code, Nginx normally retains the status that triggered processing. With =response, the chosen response code is used. This is useful when a handler’s status must be explicit rather than inherited.

Pass the request to an application or upstream

An application endpoint can render a dynamic page:

error_page 404 = /404.php;

With the equals form and no response number, the status returned by the upstream handler can be passed through. Ensure the application sets the status deliberately; otherwise it may turn a missing page into a misleading 200 response.

Use a named location when method and URI preservation matter

location / {
    error_page 404 = @fallback;
}

location @fallback {
    proxy_pass http://backend;
}

A named location avoids the ordinary local-URI behavior that changes non-GET/HEAD methods to GET. It is a better fit for an upstream service that needs the original method, URI, headers, or request body to decide how to respond.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Redirect the browser to another URL

An external URL makes the browser navigate elsewhere:

error_page 403 http://example.com/forbidden.html;
error_page 404 =301 http://example.com/notfound.html;

When no redirect code is specified, Nginx uses a 302 redirect. The equals form supports 301, 302, 303, 307, or 308. A redirect therefore changes both the visible URL and the status the browser initially receives. Use it for a deliberate migration or centralized error site, not merely to display a local page.

Make sure Nginx can reach the error file

Understand root mapping

Nginx forms a filesystem path by adding the request URI to the root value. With root /var/www/example;, a request for /404.html resolves to /var/www/example/404.html. Check the effective root in the exact server and location that handles the failing request; a more specific location can use a different root.

Use try_files for explicit fallback rules

For sites that serve extensionless pages or a front controller, make the fallback order explicit:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
location / {
    try_files $uri $uri/ $uri.html =404;
}

error_page 404 /404.html;

try_files checks files and directories in order. If none exists, =404 returns that status, which then invokes the configured error page. A misplaced fallback can create loops, so keep the error document itself available as a real file and avoid routing it back through a rule that always fails.

Account for location precedence and inheritance

An error_page setting is inherited from the previous configuration level only when the current level defines no error_page directives. If a nested location declares its own error-page rule, it stops inheriting the parent rules. This explains why a page may work at the site root but not inside an API or upload location.

Check permissions and deployment contents

The Nginx worker must be able to read the HTML file and traverse its parent directories. A deployment that copied the configuration but omitted 404.html or 50x.html has the same visible symptom as an incorrect root. Verify the file name’s capitalization, the generated path, and the permissions on every directory in that path. The error log is the quickest way to distinguish a missing file from an access failure.

Why a custom page is not showing

The request is handled by another server block

Multiple virtual hosts can share an IP address. If the Host header, listen address, or default-server selection points elsewhere, you will test the wrong configuration. Confirm the hostname in your request and inspect the access log for the selected server.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The target file is missing or outside the active root

Check the exact path produced by the active root, file permissions, and case sensitivity. A typo in /404.html, a different root in a nested location, or a deployment that omitted the file causes the internal request to fail as another 404.

An internal location is being tested directly

Requesting /404.html in a browser is not a valid test when that location is marked internal; Nginx must reach it through an error. Test a genuinely missing URL instead.

The application supplied its own error body

For proxied requests, the upstream may return an error response that Nginx passes through rather than replacing. Decide whether the application or Nginx owns the page. If Nginx should intercept selected upstream errors, configure the relevant proxy error handling and use the appropriate = form; otherwise fix the template in the application.

A child location overrides the parent rule

Search the complete configuration for additional error_page directives. A rule in a more specific location can replace the server-level behavior. Include generated configuration files when your distribution assembles the final configuration from snippets.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The redirect is working, but the result looks different

External redirects intentionally change the URL and may return 301, 302, 303, 307, or 308 instead of the original error. Inspect with curl -i and follow redirects only when you want to test the destination as well.

An error loop hides the original problem

If the error URI is itself processed by the same failing location, Nginx can repeatedly attempt to render a page that cannot be opened. Give the document an exact location, keep it as a real file under the effective root, and make sure try_files does not send that URI back to the same failing fallback.

Hide Nginx version information

Generated error pages and the Server response header can disclose the Nginx version. Disable that disclosure with:

http {
    server_tokens off;
}

Place the directive in the http block for a site-wide setting, or in an applicable server block when you need narrower scope. This changes Nginx’s version emission; it does not remove application banners, debug headers, or identifying text you put in your own HTML.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Custom pages should never expose stack traces, upstream hostnames, credentials, internal filesystem paths, request headers, or other diagnostic data. Keep detailed diagnostics in protected logs rather than in a response visible to every visitor.

Design the page for recovery, not just appearance

  • State what happened in plain language instead of displaying only “Error 404.”
  • Provide a working link to a stable home page or relevant section.
  • Offer site search when users commonly arrive through old links.
  • Include a support or contact route if the failure may need human action.
  • Use semantic headings, sufficient color contrast, keyboard-accessible links, and a responsive layout.
  • Keep the page self-contained enough to render when stylesheets, JavaScript, APIs, or the application backend are unavailable.
  • Do not reveal whether a sensitive resource exists merely by changing the wording of a 403 and 404 response unless that distinction is intentional.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Complete example for a static site

The following configuration gives a static site a dedicated 404 page, a shared 5xx page, an explicit file fallback, and version suppression:

http {
    server_tokens off;

    server {
        listen 80;
        server_name example.com;
        root /var/www/example;

        location / {
            try_files $uri $uri/ $uri.html =404;
        }

        error_page 404 /404.html;
        error_page 500 502 503 504 /50x.html;

        location = /404.html {
            internal;
        }

        location = /50x.html {
            internal;
        }
    }
}

Save the two HTML files under /var/www/example, run the configuration test, reload Nginx, and request one nonexistent path plus a controlled upstream failure if the site has a proxy. Verify the status code, body, URL, and logs separately; a visually correct page can still return the wrong status.

Production checklist

  1. Identify the exact server and location that handles the failing request.
  2. Confirm the active root and place each error document beneath it.
  3. Choose a local URI, explicit response override, named location, or external redirect according to method and status requirements.
  4. Add internal to static error-document locations if direct access should be blocked.
  5. Check whether nested locations or generated snippets override the rule.
  6. Run nginx -t and correct every reported error before reloading.
  7. Reload with nginx -s reload or your operating system’s equivalent.
  8. Test missing files, forbidden resources, and representative upstream failures with curl -i.
  9. Inspect access.log and error.log when the body, status, or selected server is unexpected.
  10. Review the HTML for accessibility and confirm it contains no secrets, stack traces, hostnames, or filesystem paths.

Frequently Asked Questions

How do I create a custom Nginx 404 page?

Create a file such as /var/www/example/404.html, add error_page 404 /404.html; in the applicable server block, optionally protect the exact location with internal, then test and reload Nginx.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Can one page handle several Nginx errors?

Yes. Use a grouped directive such as error_page 500 502 503 504 /50x.html;. Keep the wording broad enough for every status, and use a separate 403 or 404 page when users need different guidance.

Why does requesting /404.html return 404?

If its location is marked internal, direct external requests intentionally receive 404. Trigger the page through a genuinely missing URL instead.

Can Nginx redirect an error to another URL?

Yes. An external target such as error_page 403 https://example.com/forbidden.html; redirects with 302 by default. Use =301, =302, =303, =307, or =308 when a specific redirect status is required.

How can I preserve the original method for an error handler?

A local URI internally changes methods other than GET and HEAD to GET. Use a named location, for example error_page 404 = @fallback;, when the fallback must preserve the original URI and method for an upstream.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How do I keep an upstream error status?

Route to an application endpoint with the equals form and no response number, such as error_page 404 = /404.php;. The upstream handler can then determine the returned status, so make sure it sets that status deliberately.

Why is my custom page not appearing for proxied requests?

The upstream application may be returning its own body and status. Decide whether Nginx or the application owns the error page, then configure the selected layer consistently and inspect both access and error logs.

How do I hide the Nginx version on error pages?

Set server_tokens off;, commonly in the http block for site-wide scope. This suppresses Nginx version emission on generated error pages and in the Server header, but not banners added by your application.

The Bottom Line

Put each static error document beneath the active root, map statuses with error_page, and use internal to prevent direct access when appropriate. Choose local URIs, explicit status overrides, named locations, or redirects based on whether the status, URL, method, and upstream response must be preserved. Validate, reload, test with curl -i, and use the logs to diagnose the selected server, file path, and final response.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.