Soft 404: a page that says not found while answering 200
A soft 404 is a page that tells people it does not exist while telling machines that it does: the content says "not found", but the server answers 200 OK. Google reports it because the two signals contradict each other. The fix is to make the status match the content: return a real 404 (or 410) for pages that are gone, and give pages that should exist real content.
How a site ends up with soft 404s
- A single-page app with a catch-all. Every unknown path is answered with the app shell and a 200, and the "Page not found" message only appears after JavaScript runs. This produces soft 404s at unlimited scale, one for every URL anyone ever mistypes or links to.
- A friendly error page served with 200. A CMS or server configured to show "Sorry, we couldn't find that" without changing the status code.
- A redirect to the home page instead of a 404 when a product, article or category is removed. Visitors land somewhere unrelated to what they asked for.
- A page that exists but is effectively empty: an out-of-stock product with no description, a tag page with nothing on it, a search results page with no results.
We had this exact bug on this site
Until 20 September 2026, every address that did not exist on checkbeforepublish.com answered 200 with the home page, including the home page's own title and canonical. The cause was mechanical: the build did not emit a top-level 404.html, so our host treated the site as a single-page app and served index.html for anything it did not recognise. Nothing looked broken in a browser, because the app showed "Page not found" after loading.
We found it by requesting addresses that should not exist and reading the status code rather than the page. The fix was to emit a real 404.html at build time, which restores a genuine 404 status; it is marked noindex and carries no canonical, so it can never be mistaken for a real page. Before every release we now request ten addresses that do not exist and refuse to ship unless every one returns 404, so it is a rule rather than a one-off repair.
How to check your own site in a minute
Make up an address that cannot exist on your site, for example yourdomain.com/this-page-does-not-exist-12345, and check what it returns. Paste it below: the check reports the HTTP status the server sends, and a 404 is reported as a 404. If an invented URL answers 200, you have a soft 404, and you probably have it on every wrong URL, not just this one.
Note what this does and doesn't prove: we report the status code the server sends. We don't judge whether your page's wording reads like an error, which is the other half of how Google decides. A 404 here means the mechanical half is right.
How to fix it
- Gone for good: return 404, or 410 if you want to say "deliberately removed". Google treats all 4xx errors except 429 the same way, so the two are equivalent for Search; choose whichever your server makes easier.
- Moved: redirect (301) to the page that replaces it. If nothing replaces it, return 404 rather than redirecting to the home page, which is rarely an answer to what that URL was about.
- Single-page app: make the host answer a real 404 for unknown paths, usually by emitting a 404 page at build time or configuring the rewrite rules. The "Page not found" view your users see should keep working, but the status underneath must be 404.
- Page should exist but is thin: give it real content, or noindex it until it has some.
How to confirm the fix
Re-check two or three invented URLs and confirm they return 404. Then use URL Inspection on one of the URLs Search Console listed, and validate the fix in the Soft 404 report. Google revisits on its own schedule, so the report lags behind the live site.
While you are there: broken links on your own pages are a common source of these URLs. The Broken Link Checker lists every link and file on a page that answers 404 or an error.
Source: Google Search Console Help: Page indexing report for the status and its remedy; Google Crawling Infrastructure: How HTTP status codes affect Google's crawlers for 404 and 410 being treated alike. The account of our own earlier bug is first-hand.