Server 404 checker

Check that your server returns a proper 404 for non-existent URLs, not a soft 404 that confuses search engines

Free
No Sign-up
Instant Results

Check results

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.

What is a soft 404 and why it matters

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.

What this tool checks

  • Requests a random non-existent URL — we generate a probe path like /seorado-probe-404-{random} that cannot coincide with a real page
  • Reads the HTTP status code — without following redirects, so we see the server's actual response, not where a redirect sends us
  • Classifies the response — 404/410 is correct; 200 is a soft 404 (bad); 3xx is a redirect anti-pattern (attention); 401/403 means the site is auth-gated and the check is inconclusive; 5xx means the server crashes on unknown paths

Why soft 404s hurt SEO

  • Wasted crawl budget — Googlebot keeps revisiting URLs that return 200, believing they host content. Large sites with thousands of soft 404s (common in SPAs) can starve real pages of crawl attention
  • Index bloat — some soft 404s end up in the index as thin, duplicate, or low-quality pages. This drags down the perceived site-wide content quality
  • Slow deindexing of real removals — when you legitimately delete a page, a soft 404 means Google doesn't learn that it's gone. The URL lingers in the index for weeks or months
  • Search Console Soft 404 report — flags every detected instance sitewide. Pages listed here are actively hurting your indexing health; manual fixing is the canonical action
  • Redirect-to-homepage anti-pattern — a 301 from every unknown URL to / 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 content

Good vs bad examples

Good — 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
}

Common mistakes

  • SPA catch-all routes serving 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)
  • Missing =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.html
  • Redirecting to the homepage for "SEO" — sometimes done deliberately to "keep users on the site". Google explicitly documents this as equivalent to soft 404. Return 404 honestly
  • Returning 200 for moved pages — if a page actually moved, use 301 Moved Permanently to the new location. 301 is fine, 200-on-the-wrong-URL is not
  • Custom CMS plugins that override status codes — WordPress, Drupal, and similar platforms sometimes have plugins that serve a "friendly error page" with status 200 instead of 404. Check the response headers, not the page content

Frequently asked questions

Open the browser DevTools Network tab and visit a URL that definitely doesn't exist on your site (e.g. yoursite.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.
For users, the pretty page is fine — they see "Oops, this page doesn't exist" and go elsewhere. For machines it's catastrophic. Browsers cache 200 responses in history, bookmarking tools save the URL as valid, and Google's crawler concludes the URL is a real page with content. The status code is a contract between the server and every non-human client; a custom-designed 404 page should still respond with status 404. The two things are independent — you can absolutely have a beautifully designed, on-brand "Page not found" page that responds with HTTP 404. In fact, that's exactly what you want.
404 Not Found — the default for "this URL doesn't match anything I know about". Ambiguous: might be a typo, might be a deleted page, might be a page that will exist tomorrow. Use for the catch-all handler.

410 Gone — explicit signal "this URL intentionally has no content and never will again". Google deindexes 410s faster than 404s because the intent is unambiguous. Use for products you've discontinued, users who deleted their accounts, or pages you've consciously retired. For everyday "URL not found" routing, 404 is correct.
Partially. If the whole site returns 401 or 403 to unauthenticated requests, our probe gets the same response and the tool flags the result as inconclusive (attention, not good or bad). That's the correct outcome: we can't tell how your server would handle a non-existent URL for a logged-in user. If this is an intranet or members-only site, the check doesn't apply. If the site is supposed to be public but returns 401/403 to the probe, investigate your WAF or rate-limiting rules — they may also be blocking Googlebot, which is a bigger issue than soft 404s.
Framework-specific. In Next.js (App Router) add a 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.