Fix Unsuccessful HTTP Status Code for Better SEO
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.
What's the Problem?
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.
Redirect limits: Google follows maximum 10 redirect hops before giving up. Recommend keeping chains to 3-5 hops max. Good news: 301 redirects no longer lose PageRank (changed ~2016), but chains still waste crawl budget.
How to Identify This Issue
Chrome DevTools
- Open DevTools (F12) and go to the Network tab
- Reload the page and click on the main document request
- Check the Status column—anything 400-599 is a problem
- For 5xx errors, check the Response tab for error messages
- For 4xx errors, verify the URL is correct and the resource exists
Lighthouse
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.
The Fix
1. Fix 404 Not Found Errors
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)
}
2. Fix 500 Internal Server Errors
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)
}
3. Fix 502/503 Gateway Errors
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
}
4. Handle 403 Forbidden Appropriately
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))
}
}
Framework-Specific Solutions
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.Verify the Fix
- Clear any CDN or server caches that might serve stale error responses
- Request the page directly and check the HTTP status code in DevTools
- Run Lighthouse SEO audit and confirm the status code audit passes
- Use
curl -I https://your-site.com/pageto verify status code from command line - Check Google Search Console's Page Indexing report for coverage issues
- Request re-indexing in Search Console after fixing persistent errors
Common Mistakes
- Soft 404s — Returning 200 OK with "Page not found" content. Search engines may still try to index this garbage. Return actual 404 status codes.
- Custom error pages returning 200 — Your pretty 404 page must still return a 404 status code, not 200. Check your framework's error page configuration.
- Ignoring intermittent 5xx errors — Just because a page "usually" works doesn't mean Googlebot will catch it on a good day. Monitor error rates and fix flaky endpoints.
- Blocking Googlebot then wondering why pages aren't indexed — 403 errors from WAF rules, rate limiting, or geo-blocking prevent indexing. Whitelist known crawler IPs or user agents.
- Soft 404s — Returning 200 OK with "Page not found" content. Google deindexes pages that return 200 but appear to have no value. Return actual 404 status codes.
- Using 302/307 for permanent moves — These provide weak canonicalization signals. Use 301 for permanent redirects to properly consolidate SEO equity.
- 404 for temporarily removed content — 404 is a strong "don't recrawl" signal. Use 503 with Retry-After header for temporary removals.
Related Issues
HTTP status code issues often appear alongside:
- Is Crawlable — Both block indexing, but for different reasons
- Robots.txt — Check robots isn't blocking before checking status codes
- Redirects — Redirect chains can end in error codes
Test Your Entire Site
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