Introducing Highlights: the context that matters

HTTP 410 Gone: What It Means and How to Fix It

HTTP 410 Gone is a status code meaning the resource is no longer available at the origin server and the condition is likely permanent. Unlike 404, it states that the removal is deliberate. Search engines and crawlers treat 410 as a strong signal to drop the URL, and caches may store the response by default.

Code
410
Name
Gone
Class
4xx client error
Retry?
No, fix the cause first

What causes a 410 error?

  • →A product, listing, or post that was removed deliberately.
  • →An expired promotion or event page.
  • →An API version that was retired.

How do you fix a 410 error when web scraping?

  • →Remove the URL from your queue and from any stored dataset that should reflect what is live.
  • →Do not retry. A 410 is meant to be permanent.
  • →Refresh your URL list from the site’s current sitemap so removed pages stop entering the queue.

How do you fix a 410 error on your own server?

  • →Use 410 only when the removal is intentional and permanent. If the page moved, use a 301 redirect instead.
  • →Remove the URL from your sitemap and internal links at the same time.

How do you handle a 410 error in a retry loop?

410 is not in RETRYABLE, so raise_for_status() raises on the first response instead of spending retries on a request that will fail the same way. Fix the cause, then send the request again.

import random
import time

import requests

RETRYABLE = {408, 429, 500, 502, 503, 504, 520, 521, 522, 523, 524}


def fetch(url: str, max_attempts: int = 5) -> requests.Response:
    for attempt in range(max_attempts):
        try:
            response = requests.get(url, timeout=(10, 60))
        except requests.Timeout:
            time.sleep(2**attempt + random.uniform(0, 1))
            continue
        if response.status_code not in RETRYABLE:
            response.raise_for_status()
            return response
        retry_after = response.headers.get("Retry-After", "")
        backoff = 2**attempt + random.uniform(0, 1)
        time.sleep(min(int(retry_after) if retry_after.isdigit() else backoff, 60))
    raise RuntimeError(f"Gave up on {url} after {max_attempts} attempts")

How does Context.dev handle a 410 error?

Use Map URLs to rebuild a URL list from the sitemaps a site currently publishes, and Monitors to watch a sitemap and get a webhook when it changes, so removed pages drop out of your jobs.

See what the web scraping API does on every request, or read how to fix HTTP errors in web scraping for a longer walkthrough.

Frequently asked questions about a 410 error

Is 410 better than 404 for SEO?

For pages removed on purpose, a 410 is the clearer signal and search engines tend to drop the URL sooner. For pages that might return, keep a 404.

Should a crawler ever retry a 410?

No. Treat it as final for that URL. If the site republishes the page, it will appear in the sitemap again.

Can a 410 be cached?

Yes. RFC 9110 makes 410 heuristically cacheable, so caches can store it without explicit freshness headers.

Which status codes are related to 410?

Sources

Last reviewed

Ship an agent that actually knows things.

Free tier, 10-minute integration, and the same API powering agents at Mintlify, daily.dev, and Propane. No credit card to start.