Emergency server help: get in touch

Website Error Codes Explained: 403, 404, 500, 502, 503 and 504 Fixes

What the common website error codes mean, what nginx and Apache write in the log for each one, and the first fix to try. Every error reproduced in our lab.

Published 10 min read

Short answer: Website error codes tell you who failed. A 4xx code (403, 404) means the server understood the request but refused it or could not find the page: think permissions, a missing index file, a deleted or renamed URL. A 5xx code (500, 502, 503, 504) means the server or the application behind it failed: a PHP error, PHP-FPM not running, a backend that is too slow, or a limit being hit. The status code narrows the cause; the web server’s error log names it. Below is what each code means, what the log says when it happens, and the first fix to try.

Applies to nginx 1.29.8, Apache 2.4.69 and PHP-FPM 8.3.35 (lab reproduction of 403, 404, 500, 502, 503, 504)

We reproduced every error on 9 October 2026 in a lab with nginx 1.29.8, Apache 2.4.69 and PHP-FPM 8.3.35, and copied the real status codes and log lines into this guide. Two results surprised us: Apache returns 503 where nginx returns 502 for the same stopped PHP backend, and a server that does not answer at all gives a 504, not a 502.

Website error codes at a glance

Website error codes – short answer
In short: What the common website error codes mean, what nginx and Apache write in the log for each one, and the first fix to try. Every error reproduced in our lab.
Website error codes – what this guide covers
Website error codes: what this guide covers.
Website error codes – questions answered
Website error codes: the questions this guide answers.

Where to find the error log

The status code tells you which family of problem it is; the log line tells you the actual cause. The usual locations:

  • cPanel (Apache, EasyApache 4): /etc/apache2/logs/error_log; PHP errors also go to error_log files in the site’s folders, or the PHP-FPM log of the account.
  • DirectAdmin: /var/log/httpd/domains/example.com.error.log (and .log for the access log).
  • nginx: /var/log/nginx/error.log, or the error_log set in the site’s server block.
  • LiteSpeed: /usr/local/lsws/logs/error.log and stderr.log.
  • WordPress: set WP_DEBUG and WP_DEBUG_LOG to true and WP_DEBUG_DISPLAY to false in wp-config.php; errors are written to wp-content/debug.log, not shown to visitors.

Watch the log while you load the failing page: tail -f /var/log/nginx/error.log.

403 Forbidden

A 403 means the server found the path but will not serve it. We triggered the two most common causes, a folder without an index file and a file the web server user cannot read:

$ curl -s -o /dev/null -w "%{http_code}\n" http://errlab.test/files/
403
$ curl -s -o /dev/null -w "%{http_code}\n" http://errlab.test/secret.html
403

nginx logged:

[error] directory index of "/usr/share/nginx/html/files/" is forbidden
[error] open() "/usr/share/nginx/html/secret.html" failed (13: Permission denied)

Apache logged:

[autoindex:error] AH01276: Cannot serve directory /usr/local/apache2/htdocs/files/: No matching DirectoryIndex (index.html) found, and server-generated directory index forbidden by Options directive
[core:error] (13)Permission denied: AH00132: file permissions deny server access: /usr/local/apache2/htdocs/secret.html

Fix: add an index.html or index.php to the folder, and give files 644 and folders 755, owned by the site’s user (the chmod calculator explains the numbers). If the log shows nothing, the 403 comes from somewhere else: a ModSecurity or Imunify360 rule, a Deny or Require line in .htaccess, a firewall block on your IP, or Cloudflare. Never “fix” a 403 with chmod 777.

404 Not Found

A 404 means there is no file or route at that URL. In our test, neither nginx (using try_files) nor Apache at its default log level wrote anything to the error log for a 404; it only appears in the access log:

172.21.0.1 - - [09/Oct/2026:18:46:47 +0000] "GET /missing-page HTTP/1.1" 404 236

So search the access log, not the error log: grep ' 404 ' access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head lists the most requested missing URLs.

Fix: if the page moved, add a 301 redirect to the new address (the .htaccess redirect generator writes the rule, and the redirect checker confirms it). On Linux, URLs are case-sensitive, so /Guide.html and /guide.html are different files. If every WordPress page except the home page returns 404, the rewrite rules are missing: save Settings → Permalinks once, which rewrites .htaccess.

500 Internal Server Error

A 500 is a generic failure inside the server or the application. We produced three of the most common causes: a PHP fatal error, PHP running out of memory, and a typo in .htaccess. All three returned 500:

NOTICE: PHP message: PHP Fatal error:  Uncaught Error: Call to undefined function undefined_function_srvs() in /var/www/php/fatal.php:1
NOTICE: PHP message: PHP Fatal error:  Allowed memory size of 16777216 bytes exhausted (tried to allocate 67108896 bytes) in /var/www/php/memory.php on line 1
[core:alert] /usr/local/apache2/htdocs/badht/.htaccess: Invalid command 'RewriteEngin', perhaps misspelled or defined by a module not included in the server configuration

One detail to know: on our first run PHP still had display_errors on, and the same broken scripts returned 200 with half a page and the error text printed in it. A page that loads “white” or cut off with status 200 can be exactly the same bug, just reported differently.

Fix: read the PHP error log first; it names the file and line. For memory errors, raise memory_limit for that site only, and find what uses so much memory. For WordPress, the file path usually points to the plugin or theme at fault: rename that plugin’s folder to disable it. For an .htaccess error, the log quotes the bad line; fix or remove it.

502 Bad Gateway

A 502 comes from a proxy, usually nginx, when the backend behind it (PHP-FPM, Node.js, another server) refuses the connection or returns something invalid. We pointed nginx at a PHP-FPM port where nothing listened:

$ curl -sI http://errlab.test/down.php | head -1
HTTP/1.1 502 Bad Gateway

[error] connect() failed (111: Connection refused) while connecting to upstream, upstream: "fastcgi://172.21.0.2:9001"

Fix: check that PHP-FPM runs (systemctl status php-fpm, or the version-specific service such as php8.3-fpm) and that nginx points to the same socket or port the pool listens on. With a Unix socket, the log says (2: No such file or directory) when the socket does not exist and (13: Permission denied) when nginx may not use it. Our nginx 502 connection refused guide goes through each case.

503 Service Unavailable

A 503 means the server is temporarily unable to handle the request. In our lab, three different things produced it:

  • Apache with a stopped PHP backend. The same fault that gives a 502 on nginx gives a 503 on Apache: AH00957: FCGI: attempt to connect to 172.21.0.2:9001 (php:9001) failed followed by AH01079: failed to make connection to backend.
  • Rate limiting. nginx’s limit_req answers 503 by default. Four quick requests to a path limited to one per second returned 200 200 503 503, logged as limiting requests, excess: 1.982 by zone "one". Set limit_req_status 429; so limits are not mistaken for an outage.
  • Maintenance. A planned return 503, or WordPress’s .maintenance file during updates; delete a leftover .maintenance file in the site root if an update was interrupted.

On shared hosting, 503s also come from limits: LiteSpeed’s PHP process limits and CloudLinux LVE limits (which can also show as 508). See LiteSpeed 503 with lsphp on cPanel, DirectAdmin 503 and PHP-FPM and 508 Resource Limit Reached.

504 Gateway Timeout

A 504 means the proxy waited for the backend and gave up. We ran a PHP script that sleeps 10 seconds behind a 3-second timeout:

nginx:  [error] upstream timed out (110: Operation timed out) while reading response header from upstream
Apache: [proxy_fcgi:error] (70007)The timeout specified has expired: AH01075: Error dispatching request to :8092: (polling)

We also stopped the backend container completely, so its address no longer answered at all. nginx did not return 502 but 504, with upstream timed out (110: Operation timed out) while connecting to upstream. A 504 on a backend that “should be fast” can therefore mean the backend server is down or a firewall drops the traffic.

Fix: find what is slow before raising timeouts: a heavy database query (the slow query advisor helps read the MySQL slow log), an external API call, or an import or backup job run from a web request. Move long jobs to cron or the command line. Raise fastcgi_read_timeout (nginx), ProxyTimeout (Apache) or PHP’s max_execution_time only for the specific path that needs it.

Cloudflare 52x errors

If the site is behind Cloudflare, these codes come from Cloudflare and describe its connection to your server:

Check from outside first

An error you see may not be what everyone sees: a firewall can block only your IP, and a CDN can serve an old copy. Test from outside with our website down checker, look up any code in the HTTP status codes reference, or ask the Genie button at the bottom of this page with the exact error text.

Official documentation: RFC 9110: HTTP status codes, nginx limit_req module, Cloudflare 5xx errors.

Related guides: nginx 502: connect() failed (111) · LiteSpeed 503 on cPanel · 508 Resource Limit Reached.

Frequently asked questions

What is the difference between 4xx and 5xx website errors?

4xx codes mean the request could not be served as asked: the page does not exist (404) or access is refused (403). 5xx codes mean the server or the application failed while handling a valid request, for example a PHP error (500) or a backend that is down or too slow (502, 503, 504).

Why does my site show 502 Bad Gateway?

A proxy such as nginx could not get a valid answer from the backend, most often because PHP-FPM is stopped or nginx points to the wrong socket or port. The nginx error log shows connect() failed with the reason.

What is the difference between 502 and 504?

502 means the backend refused the connection or sent an invalid answer. 504 means it did not answer in time: a slow script, or a backend server that does not respond at all.

Why do I get 503 Service Unavailable?

Common causes are a stopped PHP backend on Apache, a rate limit, maintenance mode, or hosting resource limits on LiteSpeed or CloudLinux. The error log tells which one.

Why are 404 errors not in my error log?

Many servers record 404s only in the access log. Search the access log for ” 404 ” to find the missing URLs, then redirect moved pages with a 301.

Reading a lot of our guides? Go ad-free with srvScripts Pro for $6 a month. It also pays for new guides. Cancel any time.

Share this guide

Free website test

Is your website set up right?

Check SSL, security headers, redirects, robots.txt, sitemap, llms.txt and security.txt in one test. It takes about 30 seconds.