A soft 404 is a page that tells the visitor it cannot be found while telling the crawler that everything is fine. Google defines it as a 2xx response that carries error content, and Search Console reports the ones it detects. The page looks correct in a browser, so only the status line gives it away.
Which status for which situation
Google’s documentation gives each status family a different consequence, and a crawler reads the status before it reads a single word of your page. The table keeps to what that documentation states and adds our own usage in the last column.
| Status | Meaning | What Google does | Our use |
|---|---|---|---|
| 200 | The page exists and has content | Eligible for indexing | Every real page, and nothing else |
| 301, 308 | Moved permanently | A strong signal that the target is the new address | A page that has a true replacement |
| 302, 307 | Moved temporarily | A weaker signal | Only a move that will really be reverted |
| 404 | Nothing here | The URL is removed from the index | Any address that has no page |
| 410 | Gone on purpose | Treated like a 404, removed from the index | Pages we deleted deliberately |
| 401, 403 | Login required, or forbidden | Handled like other 4xx errors | Private areas |
| 429 | Too many requests | Read as overload, crawling slows down | Rate limiting, with care |
| 500, 503 | Server failure, or maintenance | Crawling is reduced | 503 for planned maintenance, never for a missing page |
Two details are worth keeping. Google follows up to 10 redirect hops, but every hop is another request, so we aim for exactly one. And it treats 301 as strong and 302 as weak, with 308 and 307 behaving like their 301 and 302 counterparts, so a permanent move should say so. How redirects feed the choice of a canonical address is in our canonical tags guide.
Google lists 404 and 410 as equivalent for removal. Our convention, which is not a Google distinction, is 410 for pages we removed on purpose and do not plan to bring back, and 404 for everything else.
How soft 404s get made
Soft 404s are almost always an accident of how the site was assembled. Four patterns are worth checking, in this order.
The first is the catch-all route. A single-page application, or a server rule written to support one, answers every unknown path with the same HTML shell and a 200, and the app then draws “page not found” in JavaScript. The crawler sees a 200 for /anything-at-all. The clean fix is on the server: known routes get the shell, everything else gets a 404 status. If routing is purely client-side and you cannot change the server, the fallback we recommend is to have the app add a noindex robots meta tag when the route is unknown, or to send the visitor to a URL that the server answers with a 404.
The second is the friendly error page with the wrong status. In nginx, error_page 404 =200 /404.html; rewrites the status to 200. In Apache, ErrorDocument 404 https://example.com/404.html with a full URL makes Apache send a redirect instead of serving the page, so the visitor ends up on a URL that answers 200. The Apache documentation says as much: with an absolute URL, the client no longer sees the original error status.
The third is the empty listing: a search page with no results, a tag page with no posts, a category that holds nothing. They answer 200 and say “no results found”. These are also thin pages by the logic of Google’s policy on low value content. If an empty set is legitimate, return a 404 for it or keep it out of the sitemap and add noindex.
The fourth is the tidy redirect: every deleted URL sent to the home page. The visitor who wanted one article lands on another page, and Search Console can report such redirects as soft 404s too. Redirect only to a page that replaces the old one. When nothing replaces it, answer 404 or 410.
Test your own site in three commands
Use an address that cannot exist, such as one with a random suffix. curl -sI sends a HEAD request and prints only the headers, and head -n 1 keeps the status line. In Windows PowerShell 5.1, type curl.exe, because plain curl is an alias for Invoke-WebRequest there.
# 1. A URL that cannot exist must answer 404 (or 410)
curl -sI https://example.com/no-such-page-7f3k2x | head -n 1
# 2. A page you deleted on purpose must answer 404, 410 or a 301 to a real replacement
curl -sI https://example.com/a-page-you-deleted | head -n 1
# 3. An old URL should reach its target in one hop: status and Location of each step
curl -sIL http://example.com/old-url | grep -iE '^(HTTP|location)'
The first two should print something like HTTP/2 404. The third prints a status line and a Location line for each hop, so count the pairs: you want one 301, then a 200. Some applications answer HEAD requests differently from GET, so if a result looks wrong, repeat it with curl -s -o /dev/null -w '%{http_code}\n' URL. In a browser, the Network tab of the developer tools shows the status of the document request, and a page whose text says “not found” next to a 200 is a soft 404 caught in the act.
Serve a real 404 page
In nginx, the default behavior is right as long as you do not override the status. The file below is served with a 404 status because error_page has no = code in front of the path.
server {
listen 443 ssl;
server_name example.com;
root /var/www/example.com;
# ssl_certificate and ssl_certificate_key omitted for brevity
location / {
try_files $uri $uri/ =404;
}
error_page 404 410 /404.html;
location = /404.html {
internal;
}
# A page removed on purpose
location = /old-guide/ {
return 410;
}
}
The version that creates soft 404s looks innocent, which is why it spreads from tutorial to tutorial:
# Do not copy: every unknown URL gets the app shell and a 200
location / {
try_files $uri /index.html;
}
error_page 404 =200 /404.html;
In Apache, give ErrorDocument a local path, never a full URL. In .htaccess the directive needs AllowOverride FileInfo.
ErrorDocument 404 /404.html
# A page removed on purpose
Redirect gone /old-guide/
The 404 page itself should keep the site header, say plainly that nothing exists at this address, and offer two or three useful destinations. Do not refresh it automatically to the home page, which is a redirect in disguise, and keep ads off it: Google’s policy on screens without publisher content names error pages among the places its ads are not allowed.
Our probe, our logs, and what to do when Search Console flags a URL
Our AdSense checker has a “Proper 404 handling” test. It requests a made-up path under your domain. A 404 or 410 passes. A 200 whose text says the page does not exist is a warning for a soft 404, and a 200 with ordinary content fails. This site is static files served by nginx with try_files $uri $uri/ =404; and error_page 404 /404.html;, the same shape as the first snippet, and it passes its own probe.
The logs show why the habit matters. Between 23 September and 7 October 2026, 3,317 of our 5,213 requests were answered with a 404, 63.6% of everything, mostly scanners looking for .env files and WordPress paths (the full breakdown is in our server log study). Each of those answers carried a genuine 404 status, so a crawler that wandered onto one would learn in a single request that the address is a dead end. Had we answered with a friendly 200 page instead, every such address a crawler reached would have been a candidate for Search Console’s soft 404 list.
When Search Console lists a URL as a soft 404, decide per URL. If the page should not exist, return 404 or 410 and remove it from your sitemap. If it should exist but is thin, enrich it or merge it into a better page. If it is a real page flagged by mistake, check that its main content is in the HTML the server sends and that nothing breaks while it loads, then ask Search Console to validate the fix. Our SEO checker tests a single page for indexability, sitemap listing and redirect chains, which covers the usual suspects.
Quick answers
Should a 404 page redirect visitors to the home page?
No. A redirect from a missing URL to the home page sends the visitor somewhere they did not ask to go, and Search Console can report it as a soft 404. Answer with a 404 status and a page that explains the situation and offers a few useful links.
Is a soft 404 a penalty?
It is a classification, not a manual action: Search Console reports the URL as a soft 404, and you can fix the cause and ask it to validate the fix. The cost is a muddled index and noisy reports, which is reason enough to fix it.
Do I need to fix soft 404s on pages that scanners request?
Scanners probing for files such as .env do not index anything, so the status code is not an SEO issue for them. It is still worth returning a plain 404, because it keeps your logs honest and uses the same configuration that protects real visitors and crawlers.