
404 Not Found is the HTTP status (RFC 9110, section 15.5.5) a server returns when it was reached but found no current resource at the requested URL, or will not reveal that one exists. The site itself is up: the path is mistyped, the page was moved or deleted without a redirect, or a rewrite rule sends the request nowhere. It does not mean you are blocked.
That last point decides who has to act. A 404 is a client error (4xx class) because the request names something that is not there, yet the root cause is usually on the site's side: a missing redirect, a broken try_files line, an SPA without a fallback, or a CDN still serving a cached 404. This guide separates the visitor's quick checks from the site owner's fixes for nginx, Apache, IIS, WordPress, React and Next.js, and ends with soft 404s, the variant that quietly damages search visibility.
What HTTP 404 Not Found Means
The normative definition is in RFC 9110 §15.5.5, and it is shorter than most people expect:
The 404 (Not Found) status code indicates that the origin server did not find a current representation for the target resource or is not willing to disclose that one exists. A 404 status code does not indicate whether this lack of representation is temporary or permanent; the 410 (Gone) status code is preferred over 404 if the origin server knows, presumably through some configurable means, that the condition is likely to be permanent.
A 404 response is heuristically cacheable; i.e., unless otherwise indicated by the method definition or explicit cache controls (see Section 4.2.2 of [CACHING]).
Four consequences follow from that wording, and each one catches people out:
- It says «a current representation», not «the page». The resource may well exist as a concept — the server simply has nothing to serve for it right now. That is why a 404 on an API endpoint does not prove the record was deleted.
- «Or is not willing to disclose that one exists» is deliberate. The spec explicitly blesses answering 404 for a resource that does exist but that this client has no business knowing about. Returning 403 there would confirm the resource is real; 404 does not. This is why admin paths and private objects often answer 404.
- It carries no information about permanence. A 404 tells a client nothing about whether to come back. If you know the resource is gone for good,
410 Goneis the code the spec prefers. Google's own documentation says it handles every 4xx except 429 the same way, so 410 is the more honest signal rather than a faster de-indexing trick. - It is cacheable by default. This is the practical trap: unless you send explicit cache headers, a 404 may be stored and replayed by browsers, CDNs and proxies. It is the usual reason a page still 404s minutes after you fixed it — the fix is live, the cached 404 is not gone. Send
Cache-Control: no-storeon 404s you expect to fix, and purge the CDN after the fix.
Do not confuse 404 with the codes around it — the difference changes how crawlers and clients behave:
| Code | Meaning | When to use it |
|---|---|---|
404 Not Found | No current representation, permanence unknown | Default for a missing URL |
410 Gone | Removed on purpose, not coming back | Retired pages you want de-indexed |
403 Forbidden | Exists, access refused — and you admit it exists | Only when disclosure is acceptable |
451 Unavailable For Legal Reasons | Exists, withheld because of a legal demand | Court orders, regional legal restrictions |
301 Moved Permanently | Lives at a new URL | Anything you have relocated |
200 OK with a «not found» page | Soft 404 — a bug, not a status | Never; see the soft 404 section below |
Confusion between these hurts SEO — see our full HTTP status codes reference, and the 403 Forbidden troubleshooting guide when the server refuses rather than fails to find.
Why is error 404 called 404?
The number comes from the HTTP numbering scheme, not from a room. The first digit is the class — 4 means the request itself is at fault — and the remaining two digits identify the specific condition within that class: 400 is a malformed request, 401 needs authentication, 403 is refused, 404 is not found. The popular story about a CERN office numbered 404 is folklore with no support in the HTTP specifications.
Is a 404 error my fault?
Almost never, if you are the visitor. A 404 means your browser, your connection and DNS all worked: the request reached the server and the server answered. What failed is the address, and that address usually came from someone else's link. Use this table to see whose side the problem is on:
| What you see | Whose side | What to do |
|---|---|---|
| 404 after typing the URL by hand | Yours (typo) | Check spelling, case, trailing slash, file extension |
| 404 from a link on another site or an old bookmark | The linking site or the site owner (no redirect) | Open the site's home page and search; tell the owner |
| 404 on the site's own menu or button | Site owner | Report it — this is a broken internal link |
| Page loads on your phone but 404s on the laptop | Usually a local cache or extension | Hard reload, private window, flush DNS (steps below) |
| 404 for everyone, right after a deploy | Site owner (routing, cache, rewrite rules) | Server-side fixes below |
Browser shows ERR_NAME_NOT_RESOLVED or a timeout, not 404 | Not a 404 at all — DNS or network | A different problem; the server was never reached |
«404 not found in the system» messages inside apps (banking portals, HR systems, ticketing tools) are the same idea: the application looked up a record or route and found nothing, which is for the vendor or your IT team to fix.
Does a 404 error mean I was blocked?
No. When a server blocks you on purpose it normally says so: 403 Forbidden for refused access, 429 Too Many Requests for rate limiting, 451 Unavailable For Legal Reasons for legal restrictions, or a challenge page from a firewall such as Cloudflare. There are two exceptions worth knowing:
- Hiding private resources. As the RFC allows, some services answer 404 instead of 403 for things you are not allowed to see. GitHub, for example, returns 404 for a private repository when you are not signed in with access. Signing in to the right account makes the page appear.
- Security plugins and firewalls. A few WAF and CMS security rules are configured to return 404 for suspicious requests so as not to reveal what they protect. If a page works from another network but 404s from yours, and a hard reload does not help, contact the site owner with the exact URL and time.
How do I fix error 404 not found?
If you are a visitor, work through these in order — each takes seconds:
- Check the URL. Look for typos, doubled slashes, a missing or extra
.html, and letter case: on Linux servers/Aboutand/aboutare different paths. - Shorten the path. Remove the last segment (
/blog/2024/post-name→/blog/2024/) or go to the home page and use site search. - Reload without the cache (see the Chrome steps below). A 404 is cacheable, so your browser may be replaying an old answer.
- Try a private window or another browser. This rules out cookies, cached files and extensions in one step.
- Search for the page title. Moved content often lives on at a new address.
- Check an archived copy if the page is really gone, or contact the site owner.
If you own the site, the fix is on the server: find where the request lands (next sections), then add a redirect, restore the content, or correct the routing.
How can I fix a 404 error in Chrome?
- Hard reload:
Ctrl+Shift+RorShift+F5on Windows and Linux,Cmd+Shift+Ron macOS. With DevTools open you can also right-click the reload button and choose Empty cache and hard reload. - Open an Incognito window (
Ctrl+Shift+N/Cmd+Shift+N). If the page works there, the problem is your cache, cookies or an extension. - Clear cached files for that site: click the icon left of the address bar → Site settings → Delete data, or clear «Cached images and files» — see how to clear the cache in Chrome, Safari, Firefox and Edge.
- Disable extensions one by one at
chrome://extensions. Ad blockers and privacy tools can block or rewrite requests. - Clear Chrome's DNS cache at
chrome://net-internals/#dns→ Clear host cache, useful when a site recently moved to a new server.
The same steps apply in Edge (it is Chromium-based), and the shortcuts are the same in Firefox. In Safari on macOS, use Cmd+Option+R to reload from the origin.
7 Common Causes of 404 Errors
- URL typo. Most frequent cause — user or external link has an incorrect path, often differing only in case or a trailing slash.
- Deleted or moved page. Content removed or renamed but no redirect configured.
- Broken rewrite rules. Misconfigured
try_filesin nginx or.htaccessin Apache, ormod_rewritenot enabled at all. - Wrong document root or alias. The server looks for files in the wrong directory. Note that unreadable files (wrong chmod/chown) usually produce
403, not 404 — nginx logs them as(13: Permission denied). - SPA routing errors. React/Vue/Angular apps without
index.htmlfallback return 404 on direct navigation or refresh of a deep link. - Stale CDN cache. CDN serves an old 404 after you deploy the new page.
- DNS or upstream misrouting. Request hits the wrong origin server or a default virtual host that does not know the site.
How to check where a 404 comes from
Start by confirming the real status code, because the page a browser renders can lie. The Enterno.io HTTP Header Checker shows the status line and full response headers from an external server; the redirect checker follows every hop, which exposes a redirect that ends on a 404. Open DevTools (F12 → Network tab), reproduce the error, and inspect the full request: URL, method, headers. The Referer header reveals where the broken link originated.
From the command line:
curl -I https://example.com/broken-page
curl -v https://example.com/broken-page 2>&1 | head -50
# status code only, using GET (some servers answer HEAD differently)
curl -s -o /dev/null -w "%{http_code}\n" https://example.com/broken-page
# bypass the CDN and ask the origin directly
curl -sS -D - -o /dev/null --resolve example.com:443:203.0.113.10 https://example.com/broken-pageIf the origin answers 200 but the public URL answers 404, the CDN is serving a cached error: look for headers such as CF-Cache-Status: HIT, X-Cache: HIT or a growing Age, then purge — see CDN cache invalidation. If the origin also returns 404, the problem is in the server config or the application.
Check web server logs:
# nginx
tail -f /var/log/nginx/access.log | grep " 404 "
tail -f /var/log/nginx/error.log
# Apache
tail -f /var/log/apache2/access.log | grep " 404 "
tail -f /var/log/apache2/error.log
# top 20 URLs returning 404 (combined log format)
awk '$9 == 404 {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20The error log tells you which file the server actually looked for. In nginx it reads open() "/var/www/html/old-page" failed (2: No such file or directory); in Apache 2.4 it is AH00128: File does not exist: /var/www/html/old-page. If that path is not where your files live, the problem is root, alias or DocumentRoot, not the content.
Solutions by Platform
nginx: try_files and custom error page
server {
location / {
try_files $uri $uri/ /index.php?$args;
}
error_page 404 /404.html;
location = /404.html {
internal;
}
}Two traps. First, error_page 404 = /index.php; with an equals sign replaces the status with whatever the handler returns — often 200, which creates a soft 404. Keep the form without = for a static error page. Second, with alias inside a prefix location, a missing trailing slash on one side (location /static/ with alias /var/www/assets;) produces wrong paths and 404s. Reference: nginx error_page directive.
Apache (.htaccess)
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [L]
ErrorDocument 404 /404.htmlIf .htaccess rules are ignored completely, the vhost has AllowOverride None or mod_rewrite is off (on Debian and Ubuntu: sudo a2enmod rewrite, then reload Apache). Give ErrorDocument a local path, never a full URL: with http://… Apache sends a redirect to the error page, so the client never sees a 404.
IIS
IIS adds a substatus to 404 that names the reason. Look for it in the sc-substatus field of the logs under C:\inetpub\logs\LogFiles:
| Substatus | Meaning | Typical fix |
|---|---|---|
404.0 | File or directory not found | Restore the file or add a redirect |
404.3 | No MIME type mapped for the extension | Add a MIME map (e.g. for .webp, .json) |
404.7 | File extension denied by request filtering | Allow the extension in Request Filtering |
404.11 | URL contains a double-escape sequence | Fix the URL or allow double escaping |
404.13 | Request content too long | Raise maxAllowedContentLength |
WordPress
Go to Settings → Permalinks and click Save — this rewrites .htaccess. If that fails, check file permissions: chmod 644 .htaccess. On nginx there is no .htaccess: the try_files $uri $uri/ /index.php?$args; line above is what makes pretty permalinks work. If only some posts 404, check for a slug changed without a redirect.
React / Vue / Next.js SPA
For static hosting, set up index.html fallback:
# nginx
location / {
try_files $uri $uri/ /index.html;
}The fallback fixes deep links but makes every unknown URL return 200 — a soft 404 by design. Render a «not found» view for unknown routes and, where the host allows it, return a real 404 for them at the edge or server. In Next.js, call notFound() from next/navigation and add app/not-found.tsx in the App Router, or return { notFound: true } from getStaticProps/getServerSideProps in the Pages Router; see the Next.js notFound reference. Confirm the result with curl, not by looking at the page.
301 redirects for deleted pages
Return 301 instead of 404 when content moved — preserves SEO equity:
location = /old-url {
return 301 https://example.com/new-url;
}Redirect to the closest equivalent page, not to the home page; search engines may treat mass redirects to the home page as soft 404s anyway. When to use 301 and when 302 is covered in 301 vs 302 redirects.
API calls returning 404 (Postman, curl, fetch)
For APIs, a 404 is usually about the address, not the data: wrong base URL or environment variable, a missing version prefix (/v1/), a trailing slash the router does not accept, an ID that does not exist, or a resource hidden from your credentials. Print the final URL your client actually sent (the Postman console shows it) and compare it character by character with the documentation.
404 not found error HTML: building a useful error page
A custom 404 page keeps visitors on the site, but only if it still returns status 404. A minimal page that does its job:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Page not found</title>
<meta name="robots" content="noindex">
</head>
<body>
<h1>We can't find that page</h1>
<p>The link may be old or mistyped.</p>
<form action="/search"><input name="q" aria-label="Search"></form>
<p><a href="/en">Home</a> · <a href="/en/contact">Report a broken link</a></p>
</body>
</html>- Serve it through
error_page/ErrorDocumentso the status stays404; never redirect missing URLs to it. - Use absolute paths for CSS, images and links: the page is shown at every broken URL, so relative paths break on deep ones.
- Keep it light and self-contained; an error page that itself triggers 404s for its assets doubles the noise in your logs.
- Offer search and a way to report the broken link — that report is often your only signal about a bad external link.
Soft 404 Errors and Google Search Console
A soft 404 is a trickier problem: the page shows "not found" content to the visitor, but the server still returns an HTTP 200 OK status instead of a real 404. Google Search Console flags these under Pages → Not indexed → Soft 404. They waste crawl budget and can keep dead URLs in the index.
Common causes of a soft 404:
- An empty or "no results" page returned with status 200 (search pages, filtered category pages);
- A JavaScript app that renders a "not found" view client-side without setting the status code;
- A custom error page served through a 200 redirect instead of a real 404 response;
- Thin or near-empty pages that Google decides are effectively "not found".
The fix follows one principle: return the correct status code. A genuinely missing page must respond with 404 Not Found (or 410 Gone if removed permanently); a real page must return 200 with substantial content. For single-page apps, add server-side or edge logic that sends a 404 for unknown routes. You can confirm the actual status your server returns — separate from what the browser shows — with an HTTP status code checker, and read the exact wording of the code on the 404 Not Found reference (RFC 9110). Google describes how it treats each status in How HTTP status codes and network errors affect Google Search.
Preventing 404 Errors
- Scan regularly for broken links — at minimum monthly, and after every URL structure change.
- Monitor key pages via Enterno.io Uptime Monitoring — get alerts if a page suddenly returns 404.
- Use 301 redirects for any URL structure changes, and keep the redirect map in version control.
- Watch Google Search Console — Indexing → Pages lists every URL Googlebot saw as «Not found (404)», with the pages that link to it.
- Build an informative 404 page with site search, popular links, and a way to report the problem.
- Purge the CDN as part of every deploy that adds or renames URLs, so a cached 404 cannot outlive the fix.
FAQ
Does a 404 hurt SEO?
Isolated 404s for URLs that never existed or were removed on purpose are normal and harmless. The damage comes from 404s on pages that had rankings and backlinks — redirect those to the closest equivalent — and from soft 404s, which Google has to work out on its own.
Should I use 404 or 410?
Use 410 Gone when content is deleted permanently and you want to say so; use 404 when the URL is unknown or the absence may be temporary. Google documents that it treats both as «content does not exist», so choose by meaning, not for speed.
Can I detect 404s automatically?
Yes — use Enterno.io monitoring with expected_code=200. Any deviation triggers Email/Telegram/Slack alerts. Combine it with Search Console's Pages report to catch 404s on URLs you do not monitor.
Why does deploying a new page return 404?
Three usual suspects: (1) CDN cache — purge it, (2) PHP OPcache — restart php-fpm, (3) rewrite rules not reloaded — reload nginx/apache. Check the origin directly with curl --resolve to see which layer still has the old answer; the HTTP Header Checker shows what the outside world gets.
Why does a site work on my phone but show 404 on my laptop?
If both are on the same network and only the laptop fails, the difference is local: a cached 404, a stale DNS entry pointing at an old server, or a browser extension. Try a private window, then clear the browser cache and DNS cache. If every device on that network fails but mobile data works, the network's DNS or a filtering proxy is the likely cause — ask the network administrator.