Check that your server returns a proper 404 for non-existent URLs, not a soft 404 that confuses search engines
This check only covers 404 behavior. For a full picture of your page, run a page audit.
For issues across your whole site — duplicate titles, orphan pages, broken internal links — run a site audit.
Want us to fix what we found? Our team can help.
When a browser or crawler requests a URL that doesn't exist, the server should respond with HTTP status 404 Not Found (or 410 Gone if the page was intentionally removed). That single number tells every downstream system — browsers, bookmarking tools, Google's crawler — that the URL has no content. A "soft 404" is when the server instead returns 200 OK along with a "Page not found" HTML page, or redirects to the homepage. The user experience looks the same, but machines can't tell the difference between a real page and a missing one. Google has a dedicated Soft 404 report in Search Console because this is one of the most common and most harmful indexing bugs.
/seorado-probe-404-{random} that cannot coincide with a real page/ is treated by Google as "equivalent to soft 404" per their own documentation, because the redirect target returns 200 and the crawler concludes the URL has real contentGood — Nginx with a proper 404 page:
error_page 404 =404 /404.html;
location = /404.html {
internal;
}
The =404 part is the critical override — without it, Nginx serves /404.html with status 200, creating a soft 404.
Good — Apache:
ErrorDocument 404 /404.html
Good — Express (Node.js):
app.use((req, res) => {
res.status(404).render('404');
});
Bad — the most common Express mistake (forgets the status):
app.use((req, res) => {
res.send('Page not found'); // ← sends 200 OK
});
Bad — SPA catch-all that serves the app shell for every path:
location / {
try_files $uri /index.html; // ← every unknown URL → 200 with app shell
}
Bad — redirecting every unknown path to the homepage:
location / {
try_files $uri @fallback;
}
location @fallback {
return 301 /; // ← Google treats this as soft 404
}
index.html with 200 — React/Vue/Angular apps where the server falls through to the app shell for unknown paths. The client-side router then shows a "404" component, but the HTTP status never becomes 404. Fix: use a framework-level 404 handler (Next.js not-found.tsx, Nuxt error.vue, React Router status={404} on the server render, or a small Node middleware that checks the resolved route and sets the status before responding)=404 in Nginx error_page — without the status override, Nginx serves the custom 404 page but with status 200. Always write error_page 404 =404 /404.html301 Moved Permanently to the new location. 301 is fine, 200-on-the-wrong-URL is notyoursite.com/this-page-does-not-exist-12345). Look at the status column — it should say 404. If it says 200 with a "page not found" page, that's a soft 404. You can also use curl -I https://yoursite.com/not-a-real-page from the command line: the first line of the response shows the status code directly.not-found.tsx file at any route level; calling notFound() in a page component will render it with status 404. Next.js handles the status code automatically. In the Pages Router, return { notFound: true } from getStaticProps / getServerSideProps. In a plain React SPA served by Nginx, the simplest fix is a server-side route list: Nginx tries each known path first, falls through to a named @not_found location that returns error_page 404 =404 /404.html. More robust: render the app server-side (Next.js, Remix) so the route resolver can decide status codes before responding.