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

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Use Apache’s ErrorDocument directive or Nginx’s error_page directive to map HTTP errors to clear, branded responses. The safest setup serves a local static page while preserving the original 4xx or 5xx status. That keeps browser behavior, monitoring, crawlers and API clients truthful.

This guide shows production-ready configurations for 404, 403, 500, 502, 503 and 504 responses, explains dynamic and reverse-proxy handlers, and provides a validation and troubleshooting checklist.

Design the error responses before configuring the server

Create separate documents for the statuses your site can actually emit. A typical set is:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • 404 Not Found: the requested resource does not exist. Offer navigation or search.
  • 403 Forbidden: the server understood the request but will not authorize it. Do not reveal sensitive details.
  • 500 Internal Server Error: an unexpected application or server failure.
  • 502 Bad Gateway: a proxy received an invalid response from an upstream service.
  • 503 Service Unavailable: the service is temporarily unavailable, commonly during maintenance or overload.
  • 504 Gateway Timeout: an upstream service did not respond in time.

Each page should explain the problem in plain language, link to a known-good location, and provide a retry or contact path where appropriate. Keep the files outside application routes that might fail themselves. They must be readable under the same virtual host, server block and access rules as ordinary site assets.

Implement custom errors in Apache

Map status codes with ErrorDocument

Apache’s syntax is ErrorDocument <3-digit-code> <action>. The directive is valid in server-wide configuration, a virtual host, a directory context, and (when AllowOverride permits FileInfo) an .htaccess file.

ErrorDocument 404 /errors/404.html
ErrorDocument 403 /errors/403.html
ErrorDocument 500 /errors/500.html
ErrorDocument 502 /errors/502.html
ErrorDocument 503 /errors/503.html
ErrorDocument 504 /errors/504.html

A path beginning with / is handled as an internal redirect. The browser keeps the original address, and Apache uses the mapped resource to generate the response body. Put the files in the document root’s errors directory, or adjust the paths to match your deployment.

Choose the action form deliberately

  • Local path: ErrorDocument 404 /errors/404.html serves a local resource.
  • Full URL: a valid URL causes an external client redirect. This changes the visible request flow and should be exceptional.
  • Quoted text: quoted content sends a direct message, useful for a minimal response but less suitable for a branded page.

For a dynamic CGI or application handler, the handler must emit an appropriate Status: header. Otherwise the error document can accidentally be returned as a successful response. With an internal redirect, Apache exposes redirect information such as REDIRECT_URL, REDIRECT_STATUS and REDIRECT_QUERY_STRING to the next handler.

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

Example virtual-host layout

<VirtualHost *:80>
    ServerName example.test
    DocumentRoot /var/www/example/public

    ErrorDocument 404 /errors/404.html
    ErrorDocument 403 /errors/403.html
    ErrorDocument 500 /errors/500.html
    ErrorDocument 502 /errors/502.html
    ErrorDocument 503 /errors/503.html
    ErrorDocument 504 /errors/504.html
</VirtualHost>

After changing a server-level or virtual-host configuration, run your platform’s Apache configuration check, reload Apache, and request a deliberately missing path through the production virtual host. If you use .htaccess, confirm that the directory’s AllowOverride setting permits FileInfo; otherwise Apache will ignore or reject the directive.

Implement custom errors in Nginx

Map one or more codes with error_page

Nginx documents the syntax as error_page code ... [=response] uri;. It is valid in http, server, location and if in location contexts.

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

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

    location = /404.html {
        internal;
    }

    location = /403.html {
        internal;
    }

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

Nginx internally redirects to the configured URI. For methods other than GET and HEAD, it normally changes the method to GET while processing the error page. The original error status is retained unless you explicitly replace it.

Replace a status only when that is intentional

This example deliberately turns a 404 into a successful response:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
error_page 404 =200 /empty.gif;

Do not use this pattern for ordinary HTML error pages. Returning 200 for a missing page makes uptime checks, search crawlers and API consumers believe the request succeeded. Use the simple form, such as error_page 404 /404.html;, when the original status must remain 404.

External redirects

An external URL makes Nginx redirect the client. The default redirect status is 302 unless a supported redirect code is specified. Because this adds another request and changes the client-visible URL, prefer an internal local page for normal error handling.

Dynamic handlers and reverse proxies

Apache dynamic handlers

If an error page is generated by CGI, PHP or another application handler, make the handler return the triggering status explicitly. A page that renders attractive HTML but sends 200 is still an incorrect error response. Pass only the information the handler needs, and avoid exposing stack traces, filesystem paths or upstream credentials.

Nginx with a proxied fallback

For a backend-generated response, use a named location:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
error_page 404 = @fallback;

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

The equals sign allows the handler to determine the resulting status. You can also send the request to a FastCGI or other application endpoint:

error_page 404 = /404.php;

Use this approach when the application must localize the page, choose content based on the request, or record an error event. Verify that the backend does not turn every error into 200 and that it cannot recurse into the same failing route.

Preserve status codes through proxies and applications

A reverse proxy can encounter failures that a static-file test never exercises. Test an ordinary missing file separately from an upstream outage. For 502, 503 and 504 pages, confirm that the proxy emits the corresponding status when the upstream is unavailable, rather than returning a generic success page. If a backend supplies its own error body, decide whether Nginx or the application owns the final status and configure only one authoritative path.

Keep error assets publicly readable if they are meant for unauthenticated visitors. An authentication redirect, access denial or rewrite loop on /404.html can replace the intended error with a second error and obscure the original failure.

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

Validate the body and status

  1. Create the files and ensure the web-server user can read them.
  2. Reload the relevant Apache virtual host or Nginx server block after a successful configuration check.
  3. Request a deliberately nonexistent path through the production hostname, not only through an IP address or a development listener.
  4. Inspect headers and body with curl -i, for example curl -i https://example.test/does-not-exist.
  5. Confirm that the response status is 404 and that the body is your custom page.
  6. Repeat for forbidden access and each 5xx path that can be safely simulated.
  7. Trigger a proxied failure separately from a static-file miss, then check both status and body.
  8. Test a non-GET request where your application accepts one; Nginx’s internal error redirect changes such methods to GET.

Also check the browser address bar, response headers, cache behavior and monitoring alerts. A branded page is useful only if clients still receive the correct HTTP semantics.

Troubleshooting common failures

The custom page is not displayed

Check that the mapping is in the active virtual host or server block, that the file path is correct relative to the document root, and that permissions allow the web-server account to read it. A request sent to a different hostname may select a different configuration.

The page returns 200 instead of 404

Look for Nginx syntax such as =200, an external redirect, or an application handler that defaults to success. Remove deliberate status replacement and make the dynamic handler emit the original status.

Apache reports an override or configuration error

When using .htaccess, verify that AllowOverride FileInfo (or an equivalent permitted override) is enabled. Otherwise move the directives into the virtual-host configuration.

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.

A second error or redirect loop appears

Request the error URI directly and inspect its response. Remove rewrites, authentication requirements or application routing that send the error document back to the failing endpoint. Keep the asset in a simple, independent directory.

POST or other methods behave unexpectedly in Nginx

Nginx normally processes an internally redirected error URI as GET for methods other than GET and HEAD. Use a handler designed for that behavior, or return an appropriate response directly from the application when method preservation matters.

Proxy errors show the wrong page

Confirm whether the failure is generated by Nginx or by the upstream. A named location or = dynamic handler may be required. Inspect upstream logs and compare them with the proxy’s status and headers.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If you need screenshots of the finished error pages for documentation, regression checks or issue reports, ScreenshotNeo can capture the production URL without configuring a local browser. Cookie banners, popups and chat widgets are removed before the shot. Bot checks, blank pages and failed loads are never billed, and each response identifies the page verdict and billing result in headers. Its MCP server lets AI agents use take_screenshot, get_page_info and capture_pdf from Claude, Cursor or another MCP client.

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

One GET request is enough:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo documentation for capture options such as full-page output, CSS selectors, custom headers, waiting rules and PDF settings. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

FAQ

Can one error page handle every status?

Technically yes, but separate pages let you give useful guidance: a missing URL needs navigation, while a 503 needs retry or maintenance information.

Should error documents be indexed?

Ensure missing and failed resources retain their 4xx or 5xx status. Search behavior follows the HTTP response; a 200 error page is the more serious indexing and monitoring problem.

When should the application own the error page?

Use an application handler when you need localization, request-aware content or centralized logging. Keep a static fallback for failures where the application itself is unavailable.

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.

Frequently Asked Questions

Can one error page handle every status?

Technically yes, but separate pages let you give useful guidance: a missing URL needs navigation, while a 503 needs retry or maintenance information.

Should error documents be indexed?

Ensure missing and failed resources retain their 4xx or 5xx status. Search behavior follows the HTTP response; a 200 error page is the more serious indexing and monitoring problem.

When should the application own the error page?

Use an application handler when you need localization, request-aware content or centralized logging. Keep a static fallback for failures where the application itself is unavailable.

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.

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