HTTP status codes for SEO: what each one tells Google

Status codes are crawl signals. Google reads them on every fetch, then decides whether to crawl more, index or drop a page. Here is what each key code means for your site, how to pick the right redirect, and how to check your URLs fast.

By , founder of Porteur · Updated 14 September 2026 · Markdown

What Google does with status codes

Googlebot requests a URL, gets a status code, and acts. The code shapes crawl rate, canonical choice and index state. Get the code wrong and you send the wrong instruction.

  • 2xx: content is available. Google can index the content at the final URL.
  • 3xx: a redirect. Google follows, consolidates signals to the target when it trusts it, and may replace the old URL in the index.
  • 4xx: a client error. Google drops or avoids indexing. Some 4xx shrink crawl on that path.
  • 5xx: a server error. Google will retry, but persistent 5xx reduces crawl and can remove pages from the index.

Your aim: a clean 200 for every page that should rank. One hop 301 for every moved page. A clear 404 or 410 for pages that should not exist.

The status codes that matter for SEO

CodeNameWhat it tells GoogleCrawl and index behaviourNotes
200OKThe page is here and rendersIndexable if not blocked or noindexedUse for every live page like /pricing
301Moved PermanentlyThis URL moved to a new URLGoogle follows, consolidates signals to targetUse one hop to the exact new URL, not the home page
302FoundTemporary redirectGoogle often keeps the old URL indexed if change looks temporaryUse only for short tests or geolocation, not for site moves
307Temporary RedirectTemporary redirect with method preservedSame intent as 302, temporaryUse when you need a strict temporary redirect
308Permanent RedirectPermanent redirect with method preservedLike 301, treats move as permanentUse for permanent moves when method preservation matters
304Not ModifiedContent unchanged since last crawlSaves crawl budget, no index changeRequires proper caching headers
404Not FoundNo page at this pathGoogle removes or avoids indexingReturn 404 on dead URLs, not a 200 with error text
410GoneThe page was removed on purposeGoogle tends to drop faster than 404Use for removals like deleted blog posts with no replacement
401UnauthorisedAuth neededBlocked from crawling and indexingKeep private areas 401 or behind login, not indexable
403ForbiddenYou are not allowedGoogle cannot access, may keep old index for a whileFix if it should be public, else leave as is
429Too Many RequestsYou are rate limitingGoogle slows crawl for a timeTune to avoid throttling Googlebot under normal load
500Internal Server ErrorThe server failedGoogle retries, persistent errors harm crawling and indexingDebug and fix at source, watch logs for spikes
503Service UnavailableTemporary outage or maintenanceGoogle retries, does not assume removalUse for planned maintenance with a Retry-After header

These are the codes you will touch in practice. Learn them and you avoid most crawl and index headaches on a small site.

Soft 404s: when a 200 is treated like a 404

A soft 404 is a page that returns 200, but Google judges it empty or irrelevant to the URL. It treats it like a 404 and may exclude it.

  • Empty category pages that say “No products found” with thin content, but 200.
  • A site move that 301s many old URLs to the home page instead of their real matches.
  • Error templates that show as normal pages with a 200.

Fix by returning the right code or the right redirect. If the page is gone, use 404 or 410. If it moved, 301 to the exact new URL. If it is thin, add real content or noindex it until fixed.

301, 302, 307, 308: which redirect to use and why

Pick permanent for real moves, temporary for short tests. Google treats permanent redirects as a strong signal to index the target and shift signals over time.

  • Use 301 or 308 for permanent moves. Example: /guides/getting-started to /guides/start-here.
  • Use 302 or 307 for temporary states. Example: A short campaign URL that points to /pricing for a week.

On a site move with URL changes as of 2026, build a one to one redirect map. Every old URL 301s to the one new URL that replaces it. Do not 301 everything to the home page, that pattern is read as soft 404s. Test the map before the switch and keep it for at least a year, longer if you can. Update internal links, canonicals, hreflang, structured data and the sitemap to the new URLs and expect some fluctuation for weeks.

// next.config.js example
module.exports = {
  async redirects() {
    return [
      { source: '/guides/getting-started', destination: '/guides/start-here', permanent: true },
    ];
  },
};

HTTP to HTTPS, trailing slash, and www vs non-www

Google treats HTTP to HTTPS as a site move. Plan it and keep redirects simple. One hop from http to the exact https twin on every path.

  • 301 every HTTP URL to HTTPS in one hop.
  • Update internal links, canonicals, hreflang and sitemaps to HTTPS.
  • Avoid mixed content. Consider HSTS. Verify the HTTPS property in Search Console.

/page and /page/ are different. Pick one and redirect the other. Keep internal links consistent. In Next.js you can set trailingSlash to true or false and match your redirects to that choice.

www and non www are different hosts. Pick one, 301 the other for every path, and set canonicals to the chosen host. In Search Console, verify a Domain property so you see both variants in one view.

503 for maintenance, and 429 for crawl rate control

Use 503 for short downtime or deploy windows. It tells Google the outage is temporary and to retry. Add a Retry After header where you can.

Do not leave a 503 up for days. If Google only sees 503 for a long time it will drop pages. Keep maintenance tight, test on a staging host, and deploy fast.

429 tells Google you are rate limiting. Google will slow crawl when it sees many 429s. That can save your origin during a surge, but it will slow discovery too.

  • Serve 200 to Googlebot under normal load. Avoid blanket 429 on Googlebot.
  • Set sensible per IP or per token limits. Exempt your static assets when possible.
  • Watch your logs. If 429 appears for Googlebot, raise limits or add exceptions.

How to check a URL’s status code

  1. Use curl from your terminal

    Run curl -I https://yourproduct.com/pricing. Look at HTTP/2 200 or the redirect chain. Follow with curl -I -L to see the final 200.

  2. Use your browser devtools

    Open the Network panel, load the page, and click the document request. Read the status and any redirects.

  3. Use a redirect checker

    Enter https://yourproduct.com/guides/getting-started and see the hop chain and final code. Save the result for your migration test notes.

  4. Use Search Console’s URL Inspection

    Inspect the URL to see the URL Google considers canonical and the crawl status. Fetch the page to confirm what Googlebot sees.

For bulk checks, crawl your site. Export all non 200s and review them by type and template. Fix templates before isolated cases.

Build and test a redirect map for a site move

A redirect map is a two column table, old URL and new URL. Keep it in your repo. Apply it at the edge or the server. Test it before launch.

  1. Crawl the old site and export URLs

    Include the old sitemap and Search Console’s known pages. Add your top landing pages from analytics if you have them.

  2. Map each old URL to one new URL

    Use exact matches where possible. If content is merged, choose the closest target and update internal links.

  3. Implement one hop 301s

    Use an nginx map or framework redirects. Avoid rewrite loops and multiple hops.

  4. Test every old URL

    Write a script to request every old URL and confirm the final status is 200 and the hop count is one.

  5. Tell Google about a domain move

    For a domain change, verify both domains in Search Console and use Settings, Change of address. This does not cover path only or HTTPS only moves.

  6. Keep the old domain live

    Keep redirects for at least a year, longer if possible. Keep the old sitemap listed for a while so Google recrawls and finds redirects.

# Simple check: final status and hops
urls_old='old-urls.txt'
while read -r u; do
  final=$(curl -s -o /dev/null -w "%{http_code} %{url_effective} %{redirect_url} %{num_redirects}\n" -L "$u")
  echo "$u -> $final"
done < "$urls_old"

A clean run shows each old URL, the final 200 and zero or one redirect. Example: /blog/how-we-built-x to /blog/how-we-built-y, 301 then 200. No chains.

Fixing common status code problems

  • 200 on error pages: return 404 or 410. Update templates to set the right header and a clear message.
  • Looping redirects: fix regex or order. Test sample URLs from every template, like /pricing and /pricing/.
  • Multiple hops: collapse to one hop. For http to https and non www to www, combine rules to reach the final URL in one step.
  • Wrong use of 302 for moves: switch to 301. Update canonicals and sitemaps at the same time.
  • Mixed slash variants: choose with or without trailing slash. Redirect the other and fix internal links.
  • Blocked HTTPS: fix certificates and HSTS order. Only HSTS after a working HTTPS setup everywhere.
  • 403 or 401 on public content: check firewalls, allow Googlebot, and confirm no country blocks on core paths.
  • Persistent 5xx on a template: roll back the deploy. Add health checks. Watch error rates in logs.

After changes, check Search Console’s Page indexing and Crawl stats reports. Look for drops in server errors and a rise in crawled pages at 200.

Questions

Check my site, free

Paste your URL and get a free check in about thirty seconds: it reads your site, the searches around it and the rivals on them, and shows three findings whole.

  • Free check, no card
  • Read-only, your own accounts
  • Readable by your agent

Read next