WriteMySEO / Blog / How Google Decides Your 200 Page Is a Soft 404
SEO technology

How Google Decides Your 200 Page Is a Soft 404

Soft 404 is a content judgment, not a status code. Here's what triggers the classifier, what it costs you in crawling and indexing, and how to audit for it yourself.

A soft 404 is not something your server returns. It is something Google decides about a page that returned 200 OK. That distinction matters, because it means no amount of checking status codes in your crawler will find the problem. Your crawl report will show a clean wall of 200s while Search Console quietly drops a few thousand URLs into a bucket labelled "Soft 404".

Most teams discover this after the fact, when the Page Indexing report jumps and nobody changed anything. The underlying cause is usually a template that handles a missing, empty, or unavailable resource by rendering a friendly message instead of signalling failure at the HTTP layer.

What Google actually means by "soft 404"

Google's documentation defines a soft 404 as a page that returns a user-friendly "not found" message without a corresponding 404 or 410 HTTP status code. Search Console surfaces it as a distinct state in the Page Indexing report, and the URL Inspection API returns it in coverageState with a string like Submitted URL seems to be a soft 404.

The mechanism is a content classifier, not a rule. Google is looking at the page it fetched and rendered and deciding whether it looks like an error page. Google has not published the feature set, so treat specifics as inference rather than fact. What is well-established from Google's own guidance and public statements:

The reasonable inference, given how the signal behaves across sites, is that the classifier combines rendered text patterns with how little unique content remains relative to the rest of the template. It is not a keyword blocklist; a page that mentions a 404 error in a blog post about HTTP status codes does not get flagged.

Why returning 200 for missing content is the actual bug

The status code is the only unambiguous channel you have for telling a crawler that a URL has no resource behind it. When you overload a 200 with an error message, you force Google to guess, and you pay for the guess twice.

First, discovery. Google documents that it crawls and recrawls based on its model of a URL's value. A URL that returns 200 enters the normal recrawl rotation. A URL that returns 404 or 410 exits it quickly — Google has documented that 410 is treated slightly faster than 404, but both are terminal signals. Soft 404 pages keep getting crawled until the classifier is confident, then get crawled at a reduced rate afterwards.

Second, index coverage reporting. Soft 404s are not indexed, so they look like an indexing problem in Search Console. If the pages genuinely should not exist, the right fix is a status code change, not an indexing investigation. Teams routinely burn weeks on the wrong diagnosis here.

The patterns that trip the classifier

Page patternWhy it looks like an errorCorrect handling
Internal search with zero resultsNo primary content, template-only textnoindex, or block the search path in robots.txt
Empty category or filter combinationSame as above, often infinite in countReturn 404 for impossible combinations; noindex thin-but-valid ones
Deleted product served as "no longer available"Explicit error wording, stripped content404/410 if gone; redirect to a parent if a real equivalent exists
Out-of-stock item with content removedLittle left but boilerplateKeep the full description and reviews; mark availability in schema
JS app rendering an error state client-sideServer says 200 before the app runsSee the next section
Geo or auth gate that blanks the page for GooglebotRendered page has no contentServe the public content; do not gate on user agent

JavaScript error pages are the hardest case

A single-page app cannot set a status code from the client. The server returns 200 and the shell, the router resolves a route that does not exist, and the component renders "Page not found". Googlebot renders it, sees error text, and classifies accordingly — if you are lucky. If rendering is deferred or fails, it may index the empty shell instead.

Google's JavaScript SEO documentation gives two sanctioned workarounds, and both are worth implementing together:

  1. Redirect to a URL that the server answers with a real 404 or 410. This is the cleaner option because the signal reaches Google at the HTTP layer.
  2. Inject <meta name="robots" content="noindex"> into the head when the error state renders. This keeps the URL out of the index, but it does not tell Google the resource is gone, so recrawling continues.
// Option 2, in the error route component
const meta = document.createElement('meta');
meta.name = 'robots';
meta.content = 'noindex';
document.head.appendChild(meta);

If your framework supports server-side rendering, the better answer is to resolve the route on the server and return the correct status with the error HTML in one response.

How to audit for soft 404s yourself

Search Console tells you after Google has already decided. You can get ahead of it with a crawl you already run.

What to do about it

  1. Decide, per template, whether the resource exists. If it does not and never will, return 410. If it is temporarily gone, return 404 and keep the URL in your sitemap only if you expect it back.
  2. Stop stripping content from pages that still have a reason to exist. An out-of-stock product with its description, specs, reviews, and a clear availability state is a real page; a page that says "out of stock" and nothing else is not.
  3. Make every faceted or search URL that can return zero results either noindex or a hard 404, and make the rule deterministic so you can test it.
  4. Add an assertion to your release tests: fetch a known-missing URL per template and fail the build if it returns 200 with error text.
  5. Re-sample coverageState through the URL Inspection API a few weeks after shipping the fix. Soft 404 counts in the Page Indexing report move slowly because recrawl rates for these URLs are already suppressed; the API gives you per-URL confirmation faster than the aggregate chart does.
indexingcrawlingstatus codesSearch Console

WriteMySEO produces marketing content, not legal, medical, financial, or compliance advice. Figures cited reflect publicly reported industry data at time of writing and shift over time.

Get started

We write this well about your industry, every month.

AI-drafted, human-reviewed SEO content on a flat subscription. Blog posts, metadata, schema, and internal links, shipped on a monthly rhythm.

See plans

More from the blog