How to make missing pages return a real 404
When someone requests a page that does not exist, your server should say so with HTTP status 404 (or 410 if the page is gone for good). A soft 404 is when it answers 200 OK instead, usually with the home page or a friendly not-found message. Search engines then find endless addresses that all show the same content, spend crawl time on them, and report them as soft 404s in Search Console. Redirecting every missing address to the home page causes the same problem, and Google may report those as soft 404s too.
Test it
Request an address that cannot exist and read the status code. -L follows any redirects, so the last status shown is the final answer:
curl -sIL https://example.com/this-page-does-not-exist-123
Or open the address in a browser with developer tools on the Network tab and read the status of each request, including any redirects.
- 404 or 410: correct.
- 200: a soft 404. The server is serving a page, often the home page, for an address that does not exist.
- 301 or 302 to the home page: Google may treat this as a soft 404. Redirect old pages to their real replacements, not everything to the home page.
Fix it on your platform
Cloudflare Pages
Add a 404.html file at the root of the site's output. Without one, Pages assumes the site is a single-page app and serves index.html with a 200 for every unknown address.
Netlify
A 404.html at the root of the publish directory is served with a 404 status automatically. If you have a catch-all rewrite such as /* /index.html 200 for a single-page app, unknown addresses will return 200; see the single-page app section below.
Vercel
Static sites: add a 404.html. Next.js: call notFound() for missing content and add a not-found.js file. Next.js sends a 404 if notFound() runs before the page starts streaming; if it runs later (for example under a loading.js), the status stays 200 and Next.js adds a noindex tag instead. Check the status with curl.
Apache
ErrorDocument 404 /404.html
Use a local path. If you give a full address (https://example.com/404.html), Apache redirects to it and the 404 status is lost.
Nginx
location / {
try_files $uri $uri/ =404;
}
error_page 404 /404.html;
location = /404.html {
internal;
}
For a site that is not a single-page app, make sure try_files ends in =404 rather than /index.html.
WordPress
WordPress returns a real 404 by default, using the theme's 404 template (404.php, or templates/404.html in a block theme). If missing pages redirect to the home page, something added that, usually a redirect or SEO plugin: look for a "redirect all 404s to the home page" option and turn it off. If no plugin has one, check the theme and any server or host redirect rules.
Shopify, Squarespace and Wix
These return real 404s by default. If yours does not, check for an app or redirect setting that sends missing pages to the home page.
Single-page apps
Apps built with React, Vue or similar frameworks often have the server return the same index.html for every address and let JavaScript decide what to show, so the server answers 200 even for pages that do not exist. The fixes, best first:
- Render on the server, or pre-render known routes, and have the server return 404 for anything else. Frameworks such as Next.js, Nuxt, SvelteKit and Astro can do this for you when set up to.
- If the server cannot know, have the app's not-found view add
<meta name="robots" content="noindex">, or redirect to an address that the server does answer with a 404. Google's JavaScript SEO guide lists these two options; use either one.
Redirect what moved, 404 the rest
When you remove or rename a page, add a 301 redirect from the old address to its closest replacement. Anything without a real replacement should return 404. Make the 404 page itself useful: say plainly that the page was not found, and link to the home page and your main sections.
Check it worked
Run WEBCHKR again. The 404 Handling check requests a made-up address on your site and follows any redirects. It passes on a 404 or 410, and warns when the final answer is any 2xx status, which includes a redirect to a home page that loads normally. Any other answer, such as a 403 from a firewall, is reported for information because it cannot confirm either way.