Custom 404 Pages: What a Good One Does, With Examples and the SEO Rules
The design can be as friendly as you like, but the status code can't be. Here's what Google expects from a missing page, what visitors need from it, and copy-paste setups that keep the 404 intact.
The short answer
A good custom 404 page does two jobs. For search engines, it must answer with a real 404 (or 410) HTTP status code, not a 200, and it must not quietly redirect every missing URL to your home page. For people, it should say plainly that the page doesn't exist, keep your normal header and navigation, and offer a way forward: a search box, links to your main sections, and a way to report the broken link. The design can be as playful as you like. The status code can't.
The SEO rules a 404 page has to follow
Return a real 404 or 410, never a 200
Google calls it a soft 404 when a URL shows a "not found" message (or an empty page) but returns 200 (success). Google keeps these pages out of search, and when its systems spot one, Search Console lists the URL as Soft 404 in the Page indexing report, separately from Not found (404). A common cause is assuming a friendly error page needs a 200 to display. It doesn't: a server can send any HTML it likes with a 404 status.
Don't redirect every missing URL to the home page
A catch-all redirect feels friendly, but Google's site-move guide warns that pointing many old URLs at one irrelevant destination such as the home page confuses users and may be treated as a soft 404.
Redirect only when there's a genuine replacement
If the content moved, or a new page clearly replaces it, send a permanent 301 straight to that URL. If several old pages were merged into one, redirecting them all to the merged page is fine. If nothing on your site meets the same need, return a 404. See 301 vs 302 redirects for choosing the right code.
404 or 410: pick either
410 Gone says the removal is deliberate and permanent, while 404 just says nothing is there. Google's crawling documentation says all 4xx codes except 429 are handled the same way: the URL is dropped from the index if it was there, and crawling of it slows down over time. Use 410 if it describes your situation more accurately, but don't expect a ranking difference.
You don't need noindex on a real 404
Google doesn't index URLs that return a 4xx status and ignores their content, so a noindex tag on a page that really returns 404 changes nothing. It's only a useful safety net where you can't control the status code, like the single-page-app and Next.js streaming cases below.
Do 404 errors hurt SEO?
Not on their own. Google has said that some URLs returning 404 doesn't affect how your other pages perform in search, and Search Console's help says a 404 isn't necessarily a problem when a page was removed with no replacement. Fix the 404s you care about: a deleted page that still gets traffic, a mistyped link from a big site, and above all broken internal links, which strand visitors and send crawlers to URLs that no longer exist. The broken link checker guide covers finding them. A good 404 page softens the landing; it doesn't fix the link.
CheckSEO's Custom 404 Checker requests a random URL on your domain that can't exist and reports the status code it gets back, whether it was redirected to your home page, and the page title served. Free, no signup.
Test your 404 status codeWhat should a good 404 page include?
- A plain message. "We can't find that page" beats a bare "Error 404". Say it may have moved or been mistyped, and skip anything that blames the visitor.
- Your normal header, navigation and footer. Google's own tips ask for the same look and feel as the rest of the site, so the visitor can tell they're still in the right place.
- A search box, if your site has search. It's the fastest way out for someone who knows what they wanted.
- Links to your home page and your most popular pages or categories. Pick a handful, not a sitemap.
- A way to report the broken link, such as a contact link or a short form. Google suggests this too, and those reports show you which links to fix.
- A light page. It's a detour, so a heavy hero video only delays the links people came for.
404 page examples: patterns that work
Famous 404 pages change often, so here are the patterns rather than the brands:
- Search first. The search box sits right under the headline. You can pre-fill it with words from the requested path.
- Shop categories. Online stores list their top categories or best sellers, so a dead product link still leads somewhere useful.
- Latest or most-read posts. Blogs and publishers show a short list of recent or popular articles.
- Help links. Software and docs sites point to the docs home, the status page and support.
- A touch of humour. An illustration or joke is fine if the way out stays above the fold.
How to create a custom 404 page
The page itself. A minimal, accessible template: a language attribute, a real <title>, one <h1>, a labelled search field and plain links. Link to your CSS with a root-relative path, because the same file is served at every missing URL, however deep.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Page not found | Example</title>
<link rel="stylesheet" href="/css/site.css">
</head>
<body>
<header><!-- your normal site header and nav --></header>
<main>
<h1>We can't find that page</h1>
<p>It may have moved, or the link may have a typo.</p>
<form role="search" action="/search" method="get">
<label for="q">Search the site</label>
<input id="q" name="q" type="search">
<button type="submit">Search</button>
</form>
<h2>Popular pages</h2>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/contact/">Report a broken link</a></li>
</ul>
</main>
</body>
</html>Nginx. error_page 404 /404.html; is an internal redirect, so the 404 status survives. Two traps: a full URL in error_page makes Nginx send a redirect (302 by default), and a single-page-app fallback like try_files $uri /index.html answers 200 for every path.
server {
# ...
error_page 404 /404.html;
location = /404.html {
internal; # direct requests for /404.html also get a 404
}
location / {
# For missing files, fall through to a real 404,
# not "try_files $uri /index.html" (that answers 200)
try_files $uri $uri/ =404;
}
}Apache. Use a local path starting with a slash. The Apache docs warn that a full URL in ErrorDocument makes the server send a redirect, so the client gets a redirect code instead of the original 404.
# .htaccess or virtual host
# A local path keeps the 404 status:
ErrorDocument 404 /404.html
# A full URL makes Apache send a redirect instead,
# so the client never sees the 404. Don't do this:
# ErrorDocument 404 https://example.com/404.htmlNext.js App Router. A root app/not-found.tsx handles every unmatched URL, and notFound() from next/navigation shows it for missing records. Next.js adds a noindex tag automatically. The catch is streaming: the docs say the status is 404 only if the response hasn't started streaming, because headers can't change once sent. Once a loading.tsx fallback or <Suspense> boundary has streamed, you get a 200 plus noindex. Call it before those boundaries and any await that may suspend, or check in proxy.ts if you use Cache Components.
// app/not-found.tsx
// Renders for notFound() calls and for any URL that matches
// no route. It renders inside the root layout, so a header
// defined there still shows.
import Link from "next/link";
export default function NotFound() {
return (
<main>
<h1>We can't find that page</h1>
<p>It may have moved, or the link may have a typo.</p>
<ul>
<li><Link href="/">Home</Link></li>
<li><Link href="/blog">Blog</Link></li>
</ul>
</main>
);
}
// app/blog/[slug]/page.tsx
import { notFound } from "next/navigation";
export default async function Post({ params }: PageProps<"/blog/[slug]">) {
const { slug } = await params;
const post = await getPost(slug);
// If this route has a loading.tsx, or this check runs inside
// <Suspense>, streaming has already started and the status is 200.
if (!post) notFound();
return <article>{post.title}</article>;
}For client-side single-page apps, Google suggests a JavaScript redirect to a URL where the server returns 404, or adding a noindex robots tag to the error view.
How to confirm the status code
Run curl -sI https://example.com/this-page-does-not-exist. The first line should read HTTP/2 404 (or HTTP/1.1 404). If it shows a 301 or 302, add -L to follow it; a chain ending in 200 is a soft 404. In a browser, open DevTools, go to the Network tab, load a made-up URL and read the Status column for the document request. A page that merely says "404" proves nothing. To see what Googlebot gets, run a live test in Search Console's URL Inspection tool.
Test your 404 handling
CheckSEO's Custom 404 Checker requests a random path on your domain that can't exist, follows any redirects, and tells you whether you get a real 404 or 410, a soft 404 returning 200, or a redirect to your home page. It shows the final status code and page title, and flags when bot protection blocked the request, so an inconclusive result isn't mistaken for a pass or a fail.
Frequently asked questions
How do I create a custom 404 page?
Build a normal HTML page with a clear message, your site header, a search box and links to key pages. Then tell the server to use it: error_page 404 /404.html; in Nginx, ErrorDocument 404 /404.html in Apache, or app/not-found.tsx in Next.js. Finally, confirm a made-up URL still returns a 404 status.
What is a soft 404?
A soft 404 is a URL that tells visitors the page doesn't exist, or shows an empty page, while returning a 200 success status. Google excludes these pages from search and lists them as Soft 404 in Search Console's Page indexing report. The fix is to return a real 404 or 410.
Should I redirect 404 pages to the home page?
No. Google warns that redirecting many old URLs to one irrelevant page such as the home page confuses users and may be treated as a soft 404. Redirect with a 301 only when a genuine replacement exists; otherwise let the URL return a 404 with a helpful custom page.
Do 404 errors hurt SEO?
Not by themselves. Google has said that URLs returning 404 don't affect how the rest of your site performs in search. Fix the ones that matter: deleted pages that still get traffic or links, and broken internal links, which strand visitors and send crawlers to pages that no longer exist.
Should a deleted page return 404 or 410?
Either works. A 410 says the removal is permanent, while a 404 only says nothing is there. Google's crawling documentation treats all 4xx codes except 429 the same way, dropping the URL from the index over time, so choose whichever describes your situation more accurately.
Check your own site with the Custom 404 Page Checker.
Open Custom 404 Page CheckerMore from the blog
"Alternate Page With Proper Canonical Tag" in Search Console: What It Means and When to Fix It
Alternate page with proper canonical tag in Search Console usually needs no fix. Learn to read it, spot a wrong canonical, and check the canonical chain.
Hreflang Tags: The Complete Setup Guide (With the Return-Link Mistake Everyone Makes)
Hreflang tags explained: syntax, x-default, language and region codes, sitemap and HTTP header setup, and the missing return link that makes Google ignore them.