HTTP 200 OK: When Success Hides a Soft 404
A client once asked me why their organic traffic had been sliding for months when every page on the site returned HTTP 200. I crawled the site and the answer took about ten minutes to find: roughly 900 discontinued product URLs were serving a polite "Sorry, this item is no longer available" page — with a 200 status code. To Google, those weren't gone. They were 900 live, thin, nearly identical pages competing for crawl attention.
That's the thing about 200. It's the code everyone wants to see and the one code nobody bothers to question.
What a 200 status code actually promises
HTTP 200 OK means one thing: the server understood the request and returned a response body it considers valid. That's the entire contract. It says nothing about whether the body contains your product page, an empty search result, a JavaScript error screen, or the words "Page not found" rendered in a nice font.
The status code lives in the very first line of the response, before any headers or HTML:
HTTP/2 200
Browsers don't display it. Users never see it. But every crawler, monitoring tool, and cache decision keys off it, which is why serving the wrong 200 causes quiet, slow damage rather than a loud outage.
Checking what your server really returns
Don't trust the browser — it follows redirects silently and hides the status line. Ask the server directly:
curl -I https://example.com/some-page/
The -I flag sends a HEAD request and prints only the status line and headers. If you want to see the status after redirects, add -L and watch each hop, or use the write-out shortcut:
curl -s -o /dev/null -w "%{http_code}" https://example.com/some-page/
That prints just the three-digit code. Wrap it in a shell loop over a list of URLs and you have a poor man's status checker in one line.
The soft 404: when 200 is a lie
A soft 404 is a page that returns 200 while its content says "not found," "no results," or "this product is unavailable." Google detects many of them by analyzing the content and reclassifies them in Search Console under "Soft 404" — but it doesn't catch all of them, and the ones it misses get crawled, indexed, and scored as real pages.
The usual sources I run into:
- CMS error templates that render an error message but never set the status. WordPress themes with a custom "oops" page wired into the wrong hook do this constantly.
- Single-page applications where the server returns 200 with the app shell for every path, and the "404" only exists client-side in JavaScript.
- Ecommerce platforms that keep expired product URLs alive with an "out of stock forever" message instead of a proper 404 or a 301 to the replacement item.
- Empty search and filter pages —
/search?q=asdfghreturning 200 with zero results, multiplied by every query string a bot invents.
Why wrong 200s cost you rankings
Every URL that returns 200 is a candidate for crawling and indexing. When thousands of worthless URLs answer 200, Googlebot spends its time re-fetching them instead of your money pages — a direct hit to your crawl budget on larger sites. Worse, those pages dilute your site's overall quality signal: a domain where 20% of indexed pages are thin apology screens looks weaker than one where dead URLs cleanly say so.
There's also the redirect-adjacent version of this problem: sites that "fix" 404s by sending every dead URL to the homepage with a 200 or a redirect. Google explicitly treats mass homepage redirects as soft 404s. The link equity you hoped to save evaporates anyway.
Finding the impostors at scale
Checking URLs one at a time with curl works for spot checks, not for a 10,000-page site. Three places to look:
- Search Console → Pages → "Soft 404". This is Google telling you exactly which URLs it already distrusts.
- Your server logs. Pages with a 200 status but suspiciously small response sizes often share one byte count — the size of your error template.
awk '$9 == 200 {print $10, $7}' access.log | sort | uniq -c | sort -rnsurfaces clusters fast. - A full crawl. You can crawl your entire site and get every URL's status code in one report, then filter the 200s by title or word count to spot pages that all say the same "not found" thing.
Fixing a soft 404 properly
Each fake 200 needs one of three honest answers:
- The content is genuinely gone: return 404 (or 410 if you want to be explicit that it's permanent). Keep the friendly error design — just set the correct status with it.
- The content moved or has a clear successor: 301 to the specific replacement page, never to the homepage.
- The page should exist but is broken: fix whatever is emptying it — a dead database query, a deleted image feed, a misfiring template condition.
In WordPress, the fix usually means calling status_header(404) in the template that renders the error, or fixing the theme so the built-in 404 handling isn't bypassed. In an SPA, configure the server or a prerender layer to return real status codes for unknown routes.
Keeping 200 honest going forward
Add one assertion to your deployment checklist: fetch a deliberately fake URL like /this-should-404-xyz/ and verify the status is 404, not 200. It takes one line in a CI script and catches the single most common regression — a platform migration or theme change that silently swaps real error codes for soft ones. Then schedule a recurring crawl so new soft 404s show up in a report within days instead of surfacing as a Search Console warning three months later.
Frequently Asked Questions
Is an HTTP 200 status code always a good thing?
Not necessarily. A 200 only confirms the server returned a response it considers valid. If that response is an error message, an empty template, or a 'product unavailable' notice, the 200 is masking a problem — search engines may index the junk page or flag it as a soft 404.
How do I check the status code of a page without a browser?
Run curl -I followed by the URL to see the status line and headers, or use curl -s -o /dev/null -w "%{http_code}" with the URL to print just the three-digit code. Both approaches skip browser caching and redirect-following, so you see exactly what the server sends.
What's the difference between a soft 404 and a real 404?
A real 404 sends the 404 status code in the response's first line, so crawlers know the page is gone. A soft 404 sends a 200 status while the visible content says 'not found'. Google treats detected soft 404s as errors, but undetected ones waste crawl budget and dilute site quality.
Try WebsiteChecker.Tech Free
Run a free technical SEO audit on any website. Get a client-ready report in minutes.
Start Free Scan