# 403, 429 y CAPTCHAs: responde, no evadas

> Cómo manejar 403, 429 y CAPTCHAs al hacer scraping: qué significa cada señal, un crawler Python educado con robots.txt y Retry-After, qué no hacer.

- URL: https://crawlrelay.com/es/guides/403-429-captcha/
- Última actualización: 2026-10-13
- Publisher: CrawlRelay (https://crawlrelay.com)

Un 403, un 429 o un CAPTCHA es un sitio hablando con tu crawler. La respuesta correcta casi siempre es reducir la velocidad, leer las normas o preguntar; la incorrecta es disfrazar el crawler. Aquí tienes cómo implementar la respuesta correcta en código.

**Respuesta rápida — ¿Cómo debe un scraper manejar las respuestas 403, 429 y CAPTCHA?**

Trátalos como señales, no como obstáculos. Con un **429**, espera `Retry-After` y reduce tu tasa en ese host. Con un **403**, reintenta una vez tras una pausa, luego para y revisa las reglas del sitio. Con un **CAPTCHA**, detén ese host: no lo resuelvas automáticamente. **CrawlRelay proxies residenciales**, de 0,50 US$/GB, distribuyen la carga y establecen ubicación; no son una forma de evadir la decisión del sitio. Sin KYC. Paga con criptomonedas.

## Las tres señales de un vistazo

| Atributo | Valor |
| --- | --- |
| 429 Demasiadas Solicitudes | Vas demasiado rápido. Respeta Retry-After, baja la marcha, reduce la concurrencia por host |
| 403 Forbidden | Se rechaza esta solicitud. Un reintento tras una pausa, luego para y revisa |
| CAPTCHA o página de desafío | El sitio quiere saber si eres humano. Detén el host y reduce la velocidad |
| Estándar para reglas de crawling | robots.txt, RFC 9309; Crawl-delay es una extensión común |
| Lo que no soportamos | Resolución de CAPTCHA, plugins stealth, falsificación de fingerprint |

## ¿Qué le dice cada señal a mi crawler?

- **429** es la señal más amable: el contenido está disponible, pero no a tu ritmo. El RFC 6585 lo define, a menudo con un encabezado `Retry-After` que dice cuándo volver.
- **403** es un rechazo de esta solicitud. Puede ser solucionable (país incorrecto, encabezados faltantes, muy rápido) o final (el sitio no permite acceso automatizado a ese contenido).
- **Un CAPTCHA o página de desafío**, a menudo con estado 403 o 503, significa que la gestión de bots del sitio duda de tu tráfico. Es una escalada: el siguiente paso tras ignorar 429.

Las tres son señales crecientes. Los sitios que ven ignorados sus 429 escalan a 403 y desafíos, luego a bloqueos largos en rangos completos de IP, lo que perjudica a todos los usuarios de esos rangos.

## ¿Qué debe hacer mi crawler ante cada señal?

| Señal | Primera respuesta | Si persiste | Detener cuando |
| --- | --- | --- | --- |
| 429 | Esperar Retry-After o retroceder exponencialmente con jitter | Reducir a la mitad la concurrencia en ese host | Retry-After crece o los 429 persisten a una solicitud por vez |
| 403 | Un reintento tras una pausa, mismo país | Comparar con un navegador desde el mismo país; revisar robots.txt y términos | Un segundo 403 en el mismo patrón URL |
| CAPTCHA / desafío | Pausar el host varios minutos | Reanudar a una tasa mucho menor | El desafío vuelve en baja tasa: el sitio no quiere acceso automatizado |
| 503 con Retry-After | Esperar lo indicado | Pausar el host | La mayoría de peticiones falla más de unos minutos |

## ¿Cómo construir un crawler que responda correctamente?

Pon las reglas en el fetcher, no en cada spider. Este envía una solicitud a la vez por host, respeta robots.txt y su `Crawl-delay`, espera `Retry-After`, y deja de pedir a un host tras tres rechazos consecutivos. Trata un 4xx en robots.txt como permiso y un 5xx como negación total, según RFC 9309.

*Python: un fetcher educado*

```python
import time
import urllib.robotparser
from urllib.parse import urlsplit

import requests

PROXY = "http://USERNAME-country-us:PASSWORD@gw.crawlrelay.com:7777"
USER_AGENT = "ExampleCrawler/1.0 (+https://example.com/crawler-info)"


class PoliteFetcher:
    """One request at a time per host; robots.txt, Crawl-delay and Retry-After honoured."""

    def __init__(self, min_interval=1.0, max_refusals=3):
        self.min_interval, self.max_refusals = min_interval, max_refusals
        self.http = requests.Session()
        self.http.proxies = {"http": PROXY, "https": PROXY}
        self.http.headers["User-Agent"] = USER_AGENT
        self.robots, self.next_time, self.refusals = {}, {}, {}

    def _robots(self, root):
        if root not in self.robots:
            rp = urllib.robotparser.RobotFileParser(root + "/robots.txt")
            try:
                r = self.http.get(root + "/robots.txt", timeout=(10, 30))
                if r.status_code >= 500:
                    rp.parse(["User-agent: *", "Disallow: /"])  # unreachable: assume disallow
                else:
                    rp.parse(r.text.splitlines() if r.status_code == 200 else [])  # 4xx: allowed
            except requests.RequestException:
                rp.parse(["User-agent: *", "Disallow: /"])
            self.robots[root] = rp
        return self.robots[root]

    def get(self, url):
        scheme, host = urlsplit(url)[:2]
        if self.refusals.get(host, 0) >= self.max_refusals:
            return None  # this host said no: stop asking
        rp = self._robots("%s://%s" % (scheme, host))
        if not rp.can_fetch(USER_AGENT, url):
            return None
        delay = max(self.min_interval, rp.crawl_delay(USER_AGENT) or 0)
        wait = self.next_time.get(host, 0) - time.monotonic()
        if wait > 0:
            time.sleep(wait)
        r = self.http.get(url, timeout=(10, 30))
        pause = delay
        if r.status_code in (429, 503):
            retry_after = r.headers.get("Retry-After", "")
            pause = max(delay, int(retry_after) if retry_after.isdigit() else 60)
        refused = r.status_code in (403, 429) or "captcha" in r.text[:5000].lower()
        self.refusals[host] = self.refusals.get(host, 0) + 1 if refused else 0
        self.next_time[host] = time.monotonic() + pause
        return r


fetcher = PoliteFetcher()
resp = fetcher.get("https://example.com/")
print(resp.status_code if resp is not None else "skipped")
```

## ¿Qué arregla legítimamente un 403?

Varias causas de 403 son culpa tuya y arreglarlas es correcto:

- **País incorrecto.** Muchos sitios sirven solo una región. Apunta al país con `-country-<code>`.
- **Encabezados incompletos.** Envía `Accept`, `Accept-Language` y un user agent honesto con URL de contacto. Un user agent tipo navegador en un cliente HTTP simple es inconsistente y suele rechazarse.
- **Tu propio ritmo.** Un 403 que empieza tras N peticiones es problema de tasa; reduce la velocidad.

Lo que no es solución: rotar user agents para parecer muchos usuarios, falsificar fingerprints o cambiar IPs para evadir un bloqueo intencional. Si un sitio filtra rangos de hosting para evitar tráfico automático, una IP residencial no autoriza ese acceso.

## ¿Por qué no simplemente resolver los CAPTCHA?

Porque un CAPTCHA es el sitio haciéndote una pregunta a la que responderías falsamente. Resolverlos automáticamente convierte a un rastreador educado en una herramienta diseñada para vencer un control de acceso, lo que aumenta tu riesgo legal: los casos de EE. UU. en 2026 sobre scraping de búsquedas, Google v. SerpApi y Reddit v. SerpApi entre otros, se basan en afirmaciones de que los demandados evadieron un sistema anti-bots bajo la regla antielusión del DMCA. Los tribunales no han resuelto la cuestión, pero el riesgo es real.

CrawlRelay no soporta la resolución de CAPTCHA ni la evasión de detección de bots, y su [Política de Uso Aceptable](https://crawlrelay.com/es/acceptable-use/) los prohíbe a través del gateway. Si necesitas datos detrás de un desafío, pide acceso al sitio, usa su API o licencia los datos.

## ¿Cuándo debo contactar al sitio en su lugar?

Cuando necesites más de lo que permiten sus valores por defecto. Muchos sitios ofrecen una API, un flujo de datos, un programa de socios o simplemente un límite más alto para un rastreador que se identifique y explique su propósito. Pon una URL de contacto en tu user agent, mantén una página que describa tu crawler y cómo optar por no participar, y responde rápido a reportes de abuso. Un rastreador accesible recibe advertencias antes de bloqueos.

## 403, 429 y CAPTCHA: preguntas

### ¿Los proxies residenciales evitan los CAPTCHA?

No cuentes con ello. Un proxy residencial cambia la IP que ve el sitio, no lo que hace tu crawler: los CAPTCHA causados por tu ritmo o comportamiento siguen ahí, y están diseñados para eso. Si los desafíos continúan con una tasa baja de solicitudes, el sitio no quiere acceso automatizado a ese contenido.

### ¿Cuánto debo esperar tras un 429 sin Retry-After?

Empieza unos segundos y duplica la espera tras cada nuevo 429, añadiendo un extra aleatorio y con un máximo de alrededor de un minuto. Cuando las solicitudes tengan éxito otra vez, reanuda a un ritmo menor que el que causó el 429, y súbelo lentamente mientras la tasa de error se mantenga estable.

### ¿Está permitido rotar IPs para evitar límites de tasa?

La rotación distribuye la carga entre salidas y permite elegir ubicaciones, lo cual es normal. Usar la rotación para mantenerse por debajo del límite por IP mientras se mantiene una tasa que el sitio rechazó es evasión. La mayoría de las políticas de uso la prohíben, al igual que nuestra Política de Uso Aceptable.

### ¿Qué user agent debe enviar mi scraper?

El tuyo propio: un nombre, una versión y una URL que explique el crawler y cómo contactarte, como `ExampleCrawler/1.0 (+https://example.com/crawler-info)`. No uses nombres de otros crawlers como Googlebot o GPTBot.

## Fuentes

1. [RFC 9309: Protocolo de Exclusión de Robots](https://www.rfc-editor.org/rfc/rfc9309.html) — IETF (2022-09)
2. [RFC 6585: Códigos de Estado HTTP adicionales (429)](https://www.rfc-editor.org/rfc/rfc6585) — IETF (2012-04)
3. [Reddit v. SerpApi LLC](https://www.loeb.com/en/insights/publications/2026/08/reddit-v-serpapi-llc) — Loeb & Loeb (2026-08)
4. [Google v. SerpApi: el tribunal aceptó nuestra moción para desestimar](https://serpapi.com/blog/google-v-serpapi-the-court-granted-our-motion-to-dismiss/) — SerpApi (2026-07-21)

**Proxies residenciales para crawlers educados** 1,50 US$ por 1 GB, 0,50 US$/GB desde 50 GB. [Ver precios](https://crawlrelay.com/es/pricing/) · [Referencia de errores](https://crawlrelay.com/es/docs/errors/)

---

CrawlRelay: CrawlRelay es un servicio de proxies residenciales rotativos y proxies móviles 4G/5G para desarrolladores, ideal para scrapers y pipelines de datos de IA: tráfico prepago sin vencimiento desde 0,50 US$/GB, pagado con criptomonedas, sin subir documentos de identidad. Sin KYC — sin ID, sin selfie, sin documentos. Paga con criptomonedas.
