Pages returning 4xx or 5xx status codes are invisible to search engines. Google's documentation is explicit: pages with unsuccessful HTTP status codes "may not be indexed properly"—and in practice, they almost never are.
Lighthouse flags "Page has unsuccessful HTTP status code" when your page returns any status code between 400-599. These codes signal to search engines that the page is either unavailable (4xx client errors) or broken (5xx server errors). Googlebot treats both the same way: it won't index the content.
The 4xx range indicates the request was invalid—the page doesn't exist (404), requires authentication (401/403), or the request was malformed. The 5xx range indicates server failures—your code crashed (500), a downstream service failed (502), or the server is overloaded (503). From an SEO perspective, both are equally damaging.
The impact extends beyond the single page. When Googlebot encounters many error responses on your site, it reduces crawl rate, assuming your server can't handle the load. This means even your healthy pages get crawled less frequently, delaying index updates and hurting fresh content discovery.
Run a Lighthouse SEO audit. The "Page has unsuccessful HTTP status code" audit fails and displays the specific status code (e.g., "404", "500", "503"). This tells you exactly what category of problem you're dealing with.
404s mean the requested URL doesn't map to any content. Common causes:
Deleted or moved content without redirects:
location /old-page {
return 301 /new-page;
}
location /blog/ {
rewrite ^/blog/(.*)$ /articles/$1 permanent;
}
// Next.js - next.config.js
module.exports = {
async redirects() {
return [
{
source: '/old-page',
destination: '/new-page',
permanent: true,
},
]
},
}
Dynamic routes not handling all cases:
// Ensure your dynamic route handler validates the ID exists
export async function GET(request, { params }) {
const post = await getPost(params.id)
if (!post) {
// Return 404 with proper status - don't return 200 with error message
return new Response('Not Found', { status: 404 })
}
return Response.json(post)
}
500 errors indicate unhandled exceptions in your code. Find and fix the root cause:
Check server logs for stack traces:
tail -100 /var/log/nginx/error.log
tail -100 /var/log/your-app/error.log
grep '" 500 ' /var/log/nginx/access.log
Add error boundaries and fallbacks:
// API route with proper error handling
export async function GET(request) {
const data = await fetchExternalAPI()
.catch((err) => {
console.error('External API failed:', err)
return null
})
if (!data) {
// Return graceful degradation, not a 500
return Response.json({ items: [], cached: true })
}
return Response.json(data)
}
These indicate infrastructure problems—your app server crashed, is overloaded, or a reverse proxy can't reach the backend.
Check upstream service health:
upstream backend {
server 127.0.0.1:3000 max_fails=3 fail_timeout=30s;
keepalive 32;
}
server {
location / {
proxy_pass http://backend;
proxy_connect_timeout 5s;
proxy_read_timeout 60s;
proxy_next_upstream error timeout http_502 http_503;
}
}
Implement retry logic for transient failures:
async function fetchWithRetry(url, retries = 3) {
for (let i = 0; i < retries; i++) {
const response = await fetch(url)
.catch(() => null)
if (response?.ok)
return response
// Exponential backoff
await new Promise(r => setTimeout(r, 2 ** i * 100))
}
return null
}
If pages require authentication, don't serve them at public URLs:
// Middleware to check auth before serving protected routes
export function middleware(request) {
const isProtectedRoute = request.nextUrl.pathname.startsWith('/dashboard')
const hasSession = request.cookies.get('session')
if (isProtectedRoute && !hasSession) {
// Redirect to login instead of returning 403
return Response.redirect(new URL('/login', request.url))
}
}
notFound() from next/navigation to properly return 404s in App Router. For API routes, always return explicit status codes. Configure redirects in next.config.js for moved content. Use error boundaries (error.tsx) to catch and handle errors gracefully.createError({ statusCode: 404 }) or showError() for proper error responses. Configure redirects in nuxt.config.ts under routeRules. Create error.vue at the root for custom error pages. Use $fetch with error handling instead of raw fetch.curl -I https://your-site.com/page to verify status code from command lineHTTP status code issues often appear alongside:
One broken page is annoying. Fifty broken pages across your site is an SEO disaster. Scan your entire site to find all pages returning error status codes before search engines discover them.
Scan Your Site with Unlighthouse