Scarnox · Blog

Scrapea sin que te bloqueen: guía práctica con código

Que te bloqueen mientras haces scraping suele significar una de tres cosas: enviaste demasiadas peticiones demasiado rápido, tu cliente no se parecía en nada a un navegador o a un bot conocido, o tu dirección IP está en una lista en la que el sitio confía menos. Puedes reducir las tres con unos pocos hábitos: detectar el bloqueo pronto, ir más despacio cuando el sitio te presiona, mantener una identidad coherente y honesta, y usar proxies solo cuando sea apropiado. Esta guía recorre cada uno con código que funciona. Úsala para sitios que tienes permiso para scrapear.

Reconoce un bloqueo

Un bloqueo no siempre parece una página de error. Fíjate en:

Registra el código de estado y una muestra corta del cuerpo para cada fallo. Un bloqueo que no ves en tus registros es un bloqueo que no puedes arreglar.

Retrocede con reintentos

Cuando el sitio dice "ve más despacio", tu código debe ir más despacio que un poco. El retroceso exponencial, con un límite de intentos, es el enfoque estándar. También respeta Retry-After cuando el sitio lo envía:

import time
import requests

session = requests.Session()
session.headers.update({
    "User-Agent": "ExampleBot/1.0 (+https://example.com/bot)",
    "Accept-Language": "en-US,en;q=0.9",
})

def polite_get(url: str, max_attempts: int = 4) -> requests.Response:
    delay = 2.0
    resp = None
    for _ in range(max_attempts):
        resp = session.get(url, timeout=30)
        if resp.status_code not in (429, 503):
            return resp
        retry_after = resp.headers.get("Retry-After", "")
        wait = float(retry_after) if retry_after.isdigit() else delay
        time.sleep(wait)
        delay *= 2
    return resp  # sigue bloqueado: devuelve la última respuesta para que la gestione el llamador

resp = polite_get("https://example.com/products?page=1")
print(resp.status_code, len(resp.text))

Fíjate en lo que la función no hace. No reintenta un 403, y no rota identidades para saltarse un bloqueo. Un 403 es una decisión de parar, no un rompecabezas que resolver.

Diagnostica un bloqueo paso a paso

Cuando una ejecución empieza a fallar, revisa estos puntos antes de cambiar nada más:

  1. Mira la primera URL que falla y su código de estado. Un bloqueo suele empezar en un punto concreto, no al azar.
  2. Compara el ritmo de peticiones en los minutos previos al primer fallo. Una ráfaga es la causa más común.
  3. Comprueba si el fallo está ligado a una ruta, a una sección o a una hora del día.
  4. Abre la misma URL a mano una vez en un navegador normal. Si el navegador la carga, la diferencia está en el patrón de tus peticiones. Si el navegador también está bloqueado, el sitio ha dejado de servirte la página por ahora.
  5. Solo entonces cambia el código. Primero ve más despacio, después añade retroceso, y por último revisa tu identidad.

Cambiar varias cosas a la vez hace imposible saber cuál ayudó.

Mantén una identidad coherente y honesta

Los scrapers se bloquean cuando su identidad cambia entre peticiones o cuando no coincide con el resto del tráfico. Una sola sesión con un User-Agent claro es la identidad estable más sencilla. Pon nombre a tu bot, añade un enlace de contacto y envía solo las cabeceras que enviaría un cliente normal. Cambiar los User-Agents para parecer muchos visitantes distintos es una forma de evasión, y tiende a hacer más probable un bloqueo, no menos.

Si un sitio sirve contenido distinto a los navegadores que a los clientes HTTP simples, usa un navegador real para esas páginas y mantén el mismo límite de ritmo. Es una ruta legítima, y mantiene el patrón de peticiones sensato.

Usa proxies con cuidado

Un proxy cambia la dirección desde la que sale una petición. Es una herramienta para necesidades legítimas, como probar desde una región concreta en un sitio que tienes permiso para probar, o repartir la carga entre tu propia infraestructura. No es una forma de escapar de un límite que el sitio te haya impuesto. El formato de un proxy es el que usan los tipos de tarea de proxy:

proxies = {
    "http": "http://user:pass@proxy.example.net:8000",
    "https": "http://user:pass@proxy.example.net:8000",
}
resp = session.get("https://example.com/products", proxies=proxies, timeout=30)

Elegir un tipo de proxy es una cuestión aparte, que se trata en proxies residenciales frente a datacenter y proxies rotatorios para scraping.

Cuando el bloqueo se convierte en captcha

Algunos sitios responden a un problema de ritmo con un captcha en lugar de un bloqueo duro. El orden sensato es: parar, ir más despacio, revisar las normas de nuevo y solo entonces considerar una resolución. Para los widgets de PopularCaptcha, la API activa de Scarnox devuelve un token que envías en el campo h-captcha-response. Para otros tipos de captcha, consulta la lista activa, porque el soporte de reCAPTCHA, Cloudflare Turnstile, GeeTest, AWS WAF y Arkose llegará pronto. La guía detallada es scraping de sitios web y captchas.

Si empiezas a ver bloqueos en un sitio, la causa casi siempre es el patrón de peticiones. Evitar captchas al hacer scraping cubre los hábitos que lo previenen.

Scrapea de forma responsable

Próximos pasos