HTTP Status Codes for SEO: The Complete Guide (2026)

Saar Twito8 min read
Saar Twito
Saar TwitoFounder & SEO Engineer

Hi, I'm Saar - a software engineer, SEO specialist, and lecturer who loves building tools and teaching tech.

View author profile →

What Is an HTTP Status Code?

An HTTP status code is a three-digit number a web server returns with every response — 200, 301, 404, 503, and so on. It tells the client (a browser, Googlebot, or an AI crawler) the state of the requested URL: available, moved, missing, broken, or temporarily unavailable. For SEO, status codes are how Google decides whether to index a page, follow a redirect, drop a URL from its index, or back off and try again later. Wrong codes lead to wrong indexing decisions.

Key Facts (TL;DR)

  • 301 redirects pass full PageRank. Google has confirmed that 301, 302, 307, and 308 redirects all pass ranking signals — but use 301 for permanent moves so the new URL replaces the old in the index.
  • 410 removes URLs faster than 404. Google's John Mueller has stated that 410 Gone is processed slightly faster than 404 Not Found when removing pages from the index.
  • Soft 404s are an SEO bug. A page that returns 200 OK but contains "page not found" content is flagged as a soft 404 in Search Console and de-indexed.
  • 503 + Retry-After is the right way to handle maintenance. Returning 503 with a Retry-After header tells Googlebot to come back later instead of de-indexing the URL.
  • Persistent 5xx errors lead to de-indexing. Google retries 5xx URLs, but if errors continue for days the URL is dropped from the index.
  • 429 makes Googlebot back off. Returning 429 Too Many Requests reduces Google's crawl rate — useful for protecting servers, dangerous if returned by accident.

The Status Codes That Actually Matter for SEO

Most of the HTTP spec is irrelevant to SEO. These are the codes Googlebot acts on:

CodeMeaningSEO impactWhen to use
200 OKPage loaded successfullyIndexableEvery live, public page
301 Moved PermanentlyURL has permanently changedPasses ranking signals; old URL replaced in indexPermanent moves, HTTPS migration, domain change
302 FoundTemporary redirectPasses signals; old URL stays in indexShort-term redirects (A/B test, geo-routing)
304 Not ModifiedContent unchanged since last visitNeutral; saves crawl budgetConditional requests with ETag / If-Modified-Since
307 / 308Temporary / permanent redirect (preserve method)Same as 302 / 301HSTS, modern redirects
404 Not FoundURL does not existRemoved from index after repeated 404sGenuinely missing pages
410 GoneURL is permanently removedRemoved from index slightly faster than 404Deleted content with no replacement
429 Too Many RequestsRate-limitedGooglebot reduces crawl rateReal rate-limit responses only
500 Internal Server ErrorGeneric server failureRetried; persistent 500s = de-indexingNever deliberately
502 Bad GatewayUpstream server failedRetried; persistent = de-indexingNever deliberately
503 Service UnavailableServer overloaded or in maintenanceGooglebot waits and retriesPlanned maintenance, with Retry-After
Soft 404200 OK but content says "not found"De-indexed; reported in Search ConsoleNever — fix to a real 404 or 410

301 vs 302: When Each Is Correct

Google has stated that 301 and 302 redirects now pass ranking signals similarly. The difference is which URL ends up in the index:

  • 301 (permanent): Google replaces the old URL with the new one in its index. Use for permanent URL changes — HTTPS migration, domain change, restructured slugs.
  • 302 (temporary): Google keeps the old URL indexed and assumes you'll switch back. Use for genuinely temporary redirects: A/B tests, country routing, short-term promos.

Misusing 302 for permanent moves is one of the most common SEO bugs — the old URL stays in Google's index for months, and the new URL never gets the credit.

# Apache (.htaccess) — permanent redirect
Redirect 301 /old-page https://example.com/new-page

# Nginx
location = /old-page {
    return 301 https://example.com/new-page;
}

# Next.js (next.config.js)
async redirects() {
  return [
    { source: '/old-page', destination: '/new-page', permanent: true }
  ];
}

404 vs 410: The Difference Matters

Both tell crawlers the page is missing, but the signal is different:

  • 404 Not Found: "The page is missing — maybe temporarily, maybe forever." Google retries before removing the URL from the index.
  • 410 Gone: "The page is permanently gone, do not check back." Google removes the URL from the index slightly faster.

In practice the difference is small — both end up de-indexed if the response is consistent. Use 410 when you're certain the page will never return (deleted product, retired campaign). Use 404 as the default. If you have a relevant replacement, prefer a 301 redirect instead — it preserves the link equity.

The Soft 404 Problem

A "soft 404" is a page that returns 200 OKat the HTTP level, but the visible content says the page wasn't found, is empty, or is otherwise non-useful. Google's rendering pipeline detects this and treats the URL as a 404 anyway — but worse, because Google wasted crawl budget figuring it out.

Common soft 404 patterns:

  • A custom "Sorry, this product is no longer available" page returning 200.
  • An empty category page (no products, but the template still loads).
  • A SPA route that renders "Page not found" client-side without changing the HTTP status.
  • A homepage that redirects all unknown URLs back to itself with 200.

Fix: return a real 404 or 410at the HTTP layer, even if you also render a friendly "page not found" page in HTML.

// Next.js App Router — return a real 404
import { notFound } from 'next/navigation';

export default async function ProductPage({ params }) {
  const product = await getProduct(params.id);
  if (!product) {
    notFound(); // renders not-found.tsx with a real 404 status
  }
  return <ProductView product={product} />;
}

Maintenance Windows: 503 + Retry-After

When you take a site down for an hour for maintenance, returning 200 OK on a "we'll be back soon" page is a soft 404. Returning a generic 500 risks de-indexing. The right answer is 503 Service Unavailable with a Retry-After header.

HTTP/1.1 503 Service Unavailable
Retry-After: 3600
Content-Type: text/html

<html><body>We're back in an hour.</body></html>

Googlebot reads Retry-After (in seconds, or as an HTTP date) and pauses crawling instead of treating the outage as content loss.

Persistent 5xx Errors and De-indexing

Google retries 5xx URLs because servers genuinely fail sometimes. But if a URL keeps returning 500 / 502 / 503 for days, Google assumes the page is gone and drops it from the index. Recovery after a long outage takes weeks — Google has to re-crawl, re-render, and re-rank the URL.

Monitor your 5xx rate in server logs and Search Console's "Crawl stats" report. A spike in 5xx responses to Googlebot is one of the fastest ways to lose organic traffic.

How to Audit Status Codes on Your Site

  1. Search Console → Pages report.Look at "Not indexed" → "Not found (404)", "Soft 404", "Server error (5xx)", and "Page with redirect". Each is a bucket of URLs with a status-code problem.
  2. Crawl with Screaming Frog or Sitebulb.Filter the "Response Codes" tab for non-200 responses. Pay attention to redirect chains (3xx → 3xx → 200) — flatten them.
  3. Check server logs for Googlebot. Filter by user-agent Googlebot and group by status code. The 5xx rate to Googlebot is the metric that matters.
  4. Test maintenance pages. Run curl -I https://yoursite.com/anything-broken and verify the actual HTTP status, not just the rendered HTML.
  5. Verify redirects with curl. Use curl -IL https://example.com/old-page to see the full redirect chain and final status.

Common Mistakes (Bad vs Good)

Mistake: Using 302 for a permanent move

Bad: Site migrates to HTTPS using 302 redirects. The HTTP URLs stay indexed, the HTTPS URLs are treated as duplicates.

Good: Use 301 (or 308 if you need to preserve the HTTP method). The new URL replaces the old one in the index.

Mistake: Redirect chains

Bad: /old/older/newest. Each hop costs crawl budget and slows users.

Good: Update every link and redirect to point directly at /newest.

Mistake: Returning 200 for missing pages

Bad:A SPA renders "Sorry, not found" in the DOM but the HTTP response is 200. Google calls this a soft 404 and de-indexes.

Good: Return a real 404 or 410 at the HTTP layer.

Mistake: 500 during maintenance

Bad: Maintenance page returns 500. Googlebot interprets it as broken.

Good: Return 503 Service Unavailable with a Retry-After header.

Mistake: Canonical pointing to a redirect

Bad: Canonical http://example.com/page when that URL 301s to https://example.com/page.

Good: Always canonicalize to the final 200 URL. See our canonical tag guide.

FAQ

Do 301 redirects still lose link equity?

No. Google has confirmed that 301, 302, 307, and 308 redirects pass full ranking signals. The old "15% PageRank loss" rule is no longer accurate. Use 301 for permanent moves so the new URL replaces the old in the index.

Should I use 404 or 410 for deleted pages?

Either works. 410 signals the removal as permanent and is processed marginally faster. 404 is a safer default if you might restore the page. If a relevant replacement exists, a 301 to that replacement is better than either.

What is a soft 404?

A page that returns HTTP 200 OK but whose content indicates the page is missing or empty. Google detects this during rendering and de-indexes the URL. Always return a real 404 / 410 at the HTTP layer for missing content.

How long does Google retry 5xx errors before de-indexing?

Several days, depending on the URL's importance and crawl frequency. Important URLs are retried longer. Persistent 5xx for a week or more is enough to drop URLs from the index.

Does 304 Not Modified hurt SEO?

No. 304is a caching response: "your cached copy is still current." Google treats the page as unchanged and saves crawl budget. It's a positive signal for large sites.

Should I use 307 / 308 instead of 302 / 301?

For SEO they behave the same. The difference is that 307 / 308 require the HTTP method (POST, PUT) to be preserved, while 302 / 301 allow it to change. For static page redirects either is fine.

What does "crawled — currently not indexed" in Search Console mean?

The URL returned 200 and Google read it, but chose not to index it — usually due to thin content, near-duplicate content, or low quality signals. It's not a status-code problem; it's a content-quality problem.

How do I check my own status codes?

Run curl -I https://example.com/your-page from the terminal. The first line shows the actual HTTP status. Add -L to follow redirects and see every hop in the chain.

Conclusion

Status codes are how your server talks to Google. Get them right and Google indexes the right URLs, removes the right ones, and waits patiently when you're down. Get them wrong — soft 404s, 302s on permanent moves, redirect chains, 500s during maintenance — and Google makes the wrong indexing decision based on bad signals. Audit Search Console's Pages report monthly, watch your Googlebot 5xx rate, and use curl -I to verify before you ship.