Un script de seguimiento de precios funciona bien el primer día, devuelve páginas medio vacías el segundo y recibe un 403 en todas las peticiones el tercero. Casi todo el que escribe scrapers pasa por esto, y la primera reacción suele ser buscar «más IP» o «esconderse mejor». La mayoría de los bloqueos tienen una causa más corriente: decenas de peticiones por segundo, cabeceras que nunca coinciden con un navegador real, toda la carga concentrada en una sola dirección IP y reglas que el sitio publica abiertamente y que nadie leyó.
En este artículo explicamos por qué se bloquean las herramientas de web scraping, los síntomas de un bloqueo y las causas que hay detrás. Después vemos cómo ajustar la velocidad de las peticiones, mantener coherentes las cabeceras, cuándo hace falta realmente rotar la IP, usar una IP fija donde se necesita sesión, y robots.txt y las condiciones del sitio. No es una guía para «esquivar la protección»: «sin que te bloqueen» significa aquí no toparse con bloqueos porque no perjudicas al sitio y sigues sus reglas.
¿Por qué los sitios bloquean los scrapers?
Detrás de que un sitio limite el tráfico automatizado suele haber costos concretos más que una suposición de mala fe:
- Carga del servidor. Un solo script que envía cientos de peticiones por segundo puede consumir los recursos que una tienda online pequeña reserva para sus visitantes reales. En páginas de búsqueda y filtros que consultan la base de datos, el efecto se multiplica.
- Ancho de banda y costo de infraestructura. Cada petición aparece en la factura del servidor y de la CDN del sitio.
- Protección del contenido y de los datos comerciales. Cuando la competencia extrae en masa precios, stock y datos de anuncios, el propietario del sitio puede querer restringirlo.
- Seguridad. Los inicios de sesión por fuerza bruta, las pruebas de tarjetas y el acaparamiento de inventario también se hacen con tráfico automatizado. A primera vista, los sistemas de protección no pueden distinguir ese tráfico de un scraper legítimo.
La mayoría de estas decisiones no se toman en el propio código del sitio, sino en la capa de gestión de bots que tiene delante. Las CDN y los servicios de seguridad puntúan cada petición con señales como la velocidad, la reputación de la IP, la coherencia de las cabeceras y el comportamiento. Para un ejemplo de cómo esa capa clasifica el tráfico de bots, consulta Cloudflare Precursor.
¿Cuáles son los síntomas de un bloqueo?
Los bloqueos no siempre llegan con un mensaje de error claro. Si ves uno de estos síntomas en los datos que produce tu scraper, la causa probable es un bloqueo:
403 Forbidden: la petición se entendió pero se rechazó. Puede deberse a la reputación de la IP, a cabeceras ausentes o a una restricción geográfica.429 Too Many Requests: superaste el límite de velocidad. A menudo una cabeceraRetry-Afterindica cuánto esperar.503 Service Unavailable: el servidor puede estar realmente ocupado, o un sistema de protección de bots puede estar devolviendo esta respuesta temporalmente.200pero con página de verificación: el código de estado parece correcto, pero el contenido es una pantalla de verificación en lugar de una lista de productos.200pero con contenido vacío o incompleto: tus selectores no encuentran nada. Puede deberse a un bloqueo o a que la página carga su contenido con JavaScript.- Redirecciones a una página de inicio de sesión: tu sesión se ha cerrado, a menudo por un cambio de IP en mitad de la sesión.
- Respuestas cada vez más lentas: algunos sistemas retrasan la respuesta a propósito en lugar de rechazar la petición.
Explicamos cada código de estado HTTP y cuáles conviene reintentar en Códigos de estado HTTP en web scraping. Para saber si un contenido vacío es un bloqueo o una página dinámica, consulta Páginas estáticas y dinámicas.
| Síntoma | Causa probable | Solución legítima |
|---|---|---|
Muchos 429 en poco tiempo | La velocidad supera el límite del sitio | Bajar la concurrencia, esperar lo que indique Retry-After |
403 desde la primera petición | Cabeceras ausentes, una IP de centro de datos o una restricción regional | Usar cabeceras coherentes; elegir un tipo de IP y una ubicación acordes con el público del sitio |
403 que empieza al cabo de un rato | Se marcó el tráfico intenso desde una sola IP | Ir más despacio y repartir la carga en el tiempo y, si hace falta, entre IP |
| Página de verificación | Comportamiento o reputación sospechosos de la IP | Parar, revisar velocidad y alcance; buscar una API o un permiso |
200 pero contenido vacío | La página carga con JavaScript o el contenido se ocultó | Encontrar la petición de API en segundo plano; un navegador headless si hace falta |
| La sesión se cierra de golpe | La IP cambió en mitad de la sesión | Usar una IP fija para la sesión |
| Las respuestas se ralentizan con el tiempo | Carga del servidor o retraso deliberado | Bajar la velocidad, evitar las horas punta |
| El contenido difiere del de un navegador real | Contenido específico para bots o diferencia de ubicación | Revisar la ubicación; usar una identidad de cliente que te presente |
Velocidad de las peticiones: ¿cómo se respetan los límites?
La causa de bloqueo más común y más fácil de evitar es la velocidad. Una persona en una tienda online abre una página cada pocos segundos; un scraper escrito con asyncio puede enviar cientos de peticiones en el mismo tiempo. RFC 6585 define el código 429 Too Many Requests exactamente para esta situación y dice que el servidor puede indicar cuánto esperar con una cabecera Retry-After.
Las reglas básicas para mantener la velocidad bajo control:
- Fija un límite de concurrencia por sitio. Mantén pequeño el número de peticiones abiertas al mismo dominio. La concurrencia total puede ser alta, pero la parte que recae en un solo sitio debe ser baja.
- Añade pausas aleatorias entre peticiones. Una petición cada 2 segundos exactos llama más la atención que intervalos irregulares y no evita picos momentáneos.
- Ve más despacio, no más rápido, cuando recibas
429y503. Reenviar de inmediato una petición fallida empeora el problema. Usa backoff exponencial. - Respeta la cabecera
Retry-After. El valor puede ser un número de segundos o una fecha HTTP; la explicación de MDN muestra ambas formas. - No envíes peticiones innecesarias. Para no volver a descargar páginas que no han cambiado, guarda los valores
ETagyLast-Modifiedy envía peticiones condicionales conIf-None-MatcheIf-Modified-Since; si la página no ha cambiado, el servidor devuelve un304sin cuerpo. - Usa el sitemap. Empieza por las direcciones del
sitemap.xmldel sitio en lugar de rastrear todo el sitio enlace a enlace. - Evita las horas punta. No hagas recogidas masivas cuando el público del sitio está más activo.
La función de Python siguiente respeta la cabecera Retry-After en las respuestas 429, 502, 503 y 504; si no hay cabecera, aplica backoff exponencial con un componente aleatorio. No reintenta respuestas como 403 y 404, porque reenviarlas no cambia el resultado:
import random
import time
from datetime import datetime, timezone
from email.utils import parsedate_to_datetime
import requests
RETRY_STATUS = {429, 502, 503, 504}
def retry_after_seconds(value):
"""Retry-After puede ser segundos o una fecha HTTP."""
if not value:
return None
if value.isdigit():
return int(value)
try:
when = parsedate_to_datetime(value)
except (TypeError, ValueError):
return None
return max(0.0, (when - datetime.now(timezone.utc)).total_seconds())
def polite_get(session, url, max_attempts=5, base=1.0, cap=60.0):
for attempt in range(max_attempts):
try:
response = session.get(url, timeout=20)
except (requests.ConnectionError, requests.Timeout):
response = None
if response is not None and response.status_code not in RETRY_STATUS:
return response # respuestas como 200, 404 y 403 no se reintentan
wait = None
if response is not None:
wait = retry_after_seconds(response.headers.get("Retry-After"))
if wait is None:
wait = min(cap, base * 2**attempt) * random.uniform(0.5, 1.0)
time.sleep(min(wait, cap))
raise RuntimeError(f"{url}: sin respuesta tras {max_attempts} intentos")Basta con usar esta función sobre una lista de páginas con una pausa entre peticiones:
session = requests.Session()
session.headers.update({
"User-Agent": "ExamplePriceBot/1.0 (+https://example.com/about-our-bot)",
"Accept-Language": "es-ES,es;q=0.9",
})
for url in urls:
response = polite_get(session, url)
if response.status_code == 403:
print("Acceso denegado, parar e investigar:", url)
break
process(response.text)
time.sleep(random.uniform(2, 5))Cómo ajustar la concurrencia y qué limita realmente la velocidad se explica en Concurrencia y paralelismo.
Cabeceras y una identidad de cliente coherente
Las cabeceras de una petición HTTP dicen quién es el cliente y qué acepta. Las cabeceras por defecto de las librerías son muy distintas de las de un navegador. Python Requests envía por defecto un User-Agent como python-requests/2.x; muchos sitios rechazan ese valor directamente.
Aquí hay dos enfoques, y sirven a fines distintos:
Presentarte. Los crawlers legítimos ponen en el User-Agent el nombre del bot y una dirección con información sobre él: ExamplePriceBot/1.0 (+https://example.com/about-our-bot). Cuando el administrador del sitio ve el tráfico, sabe quién lo envía y cómo contactarte; si hay un problema, puede escribirte en lugar de bloquearte. También puede escribir reglas de robots.txt específicas para ese nombre.
Coherencia. Uses la identidad que uses, debe ser coherente en toda la petición. Ejemplos de incoherencia:
- Un
User-Agentque cambia al azar en cada petición, pero con las mismas cookies y la misma IP. - Un
User-Agentque dice ser Chrome, pero sin ninguna de las cabecerasAccept,Accept-LanguageySec-CH-UAque Chrome envía en cada petición. - Visitar un sitio de Türkiye con
Accept-Language: en-USy una IP que sale en EE. UU. esperando precios en liras turcas.
Explicamos qué señales, además de las cabeceras, identifican a los navegadores en Browser fingerprinting. Falsificar estas señales para esquivar la protección de bots no es lo que recomienda este artículo; el objetivo es que tu cliente diga de forma coherente lo que es.
Diversidad de IP: ¿cuándo hace falta rotar?
El tráfico intenso desde una sola dirección IP es la unidad a la que más fácil resulta aplicar límites de velocidad. Por eso «me han bloqueado, cambio de IP» es un reflejo tan común. Pero la rotación tiene dos fines legítimos y un uso equivocado.
Fin legítimo 1: repartir la carga. Un trabajo que recoge páginas públicas de precios de cientos de sitios distintos y envía todo el tráfico desde una sola IP da a esa IP mala reputación enseguida, y puede hacer que la marquen en listas de reputación generales aunque no supere el límite de ningún sitio concreto. Repartir el tráfico entre distintas direcciones mantiene en un nivel realista la carga de cada dirección.
Fin legítimo 2: ver contenido según la ubicación. Los precios, el stock y los resultados de búsqueda cambian según el país y la ciudad del visitante. Salir desde distintas ubicaciones es la única forma de recoger la vista real de cada mercado.
Uso equivocado: esquivar un bloqueo explícito. Si el sitio te ha avisado con un límite de velocidad, ha cerrado esa ruta en robots.txt o prohíbe expresamente el acceso automatizado en sus condiciones, cambiar de IP y seguir a la misma velocidad no resuelve nada; significa ignorar una preferencia que el propietario del sitio ha expresado con claridad.
La rotación puede configurarse con un Proxies rotativos, que da una IP de salida distinta en cada conexión a través de una sola dirección. Para trabajos que necesitan direcciones de conexiones domésticas reales, se prefiere un Proxies residenciales. Mostramos un esquema rotativo en Python en Cómo rotar proxies en Python.
Una IP fija donde se necesita sesión
Cambiar de IP en cada petición no conviene para todos los trabajos. En estos, la dirección IP debe mantenerse fija durante un tiempo:
- Páginas con sesión iniciada. Si extraes informes del panel de tu propia cuenta, un cambio de IP en mitad de la sesión activa controles de seguridad y la sesión se cierra.
- Flujos de varios pasos. Flujos que guardan estado en el servidor, como añadir al carrito, seleccionar filtros o paginar.
- Visitas ligadas a cookies. Peticiones con la misma cookie que llegan desde países distintos crean una imagen de visitante incoherente.
Para estos trabajos, un Proxies de sesión fija mantiene la misma IP de salida durante un periodo definido. La regla general: una sesión = una IP; la IP puede cambiar cuando termina la sesión.
robots.txt y condiciones del sitio
Antes de recoger datos de un sitio, hay que revisar dos documentos.
robots.txt es el archivo en el que un sitio indica qué rutas no quiere que rastreen los bots, y su formato está estandarizado en RFC 9309. No rastrear las rutas cerradas con Disallow significa respetar la preferencia que el sitio ha expresado explícitamente. Explicamos cómo leer el archivo y comprobarlo con Python en Qué es robots.txt y cómo leerlo.
Las condiciones de uso pueden contener cláusulas sobre el acceso automatizado. Algunos sitios prohíben por completo el scraping, otros lo limitan a cierta velocidad y otros ofrecen una API oficial para los datos. Si hay una API oficial, casi siempre es la vía más sólida: los datos llegan estructurados, tu código no se rompe cuando cambia el diseño de la página y tu acceso se basa en un acuerdo.
Las páginas con datos personales requieren un cuidado adicional; las obligaciones de la KVKK en Türkiye y del RGPD en Europa se aplican con independencia de cómo recojas los datos. Tratamos el marco legal en ¿Es legal el web scraping?.
Algunos sitios también colocan enlaces ocultos que los visitantes no ven pero en los que caen los bots. Un crawler que sigue enlaces visibles y mantiene un alcance acotado se mantiene lejos de estas trampas de forma natural; explicamos el mecanismo en Trampas honeypot.
¿Qué hacer cuando aparece un CAPTCHA?
Una pantalla de verificación ante un scraper significa que el sitio considera sospechoso tu tráfico. En este punto no se recomiendan servicios de resolución de CAPTCHA ni plugins para evadir la detección; suponen intentar esquivar un control explícito del sitio y suelen ocultar el origen del problema. En su lugar, sigue este orden:
- Detén el scraper. Seguir enviando peticiones a la pantalla de verificación baja aún más la reputación de la IP y de la sesión.
- Mide la velocidad. Comprueba cuántas peticiones enviaste al mismo sitio en el último minuto.
- Compara las cabeceras con un navegador real. ¿Falta alguna cabecera o hay alguna contradictoria?
- Revisa el alcance. ¿Estás rastreando rutas cerradas por robots.txt o páginas que no necesitas?
- Busca alternativas. Una API oficial, una opción de exportación de datos o el contacto directo con el propietario del sitio.
- Solo entonces vuelve a intentarlo a menor velocidad con una identidad de cliente coherente.
Qué hacer si te bloquean: lista de diagnóstico
- ¿Sabes cuándo empezó el bloqueo y la velocidad de peticiones en ese momento?
- ¿Cuál es el código de respuesta:
403,429,503o200con una página de verificación? - ¿Llegó una cabecera
Retry-Aftery la respetaste? - ¿La misma dirección se abre en un navegador real con la misma IP?
- ¿Tus cabeceras son coherentes, o el
User-Agentes el predeterminado de la librería? - ¿Las rutas que rastreas están cerradas en robots.txt?
- ¿Qué dicen las condiciones del sitio sobre el acceso automatizado?
- ¿Cambia la IP en un flujo que necesita sesión?
- ¿El contenido vacío viene de una página que carga con JavaScript?
- ¿Hay una API oficial que ofrezca los mismos datos?
Casos de uso
- Seguimiento de precios: unas pocas veces al día, direcciones de producto tomadas del sitemap, solo las páginas que han cambiado mediante peticiones condicionales. La configuración está en nuestra página de solución de seguimiento de precios.
- Investigación de mercado y recogida de catálogos: páginas públicas de muchos sitios distintos, concurrencia baja por sitio y rotación para repartir la carga. La configuración general está en nuestra página de solución de extracción de datos.
- Rastreo amplio: un crawler que sigue enlaces, respeta robots.txt y mantiene una cola por dominio. La parte del escalado está en nuestra página de solución de web crawler.
- Seguimiento de resultados de búsqueda por ubicación: primero la API oficial y después puntos de salida por ciudad. Los detalles están en Cómo automatizar el seguimiento de posiciones SEO.
- Selectores robustos: aunque no te bloqueen, los datos llegan vacíos cuando cambia la estructura de la página. Explicamos cómo escribir selectores que no se rompan en Selector CSS o XPath.
Errores comunes
- Iniciar cientos de peticiones a la vez con
Promise.alloasyncio.gather. La velocidad total parece alta, pero la carga en cada sitio se vuelve inaceptable. - Reintentar de inmediato ante un
429. Los reintentos sin backoff prolongan el límite de velocidad. - Usar el
User-Agentpredeterminado de la librería. Muchos sitios bloquean ese valor directamente. - Generar un
User-Agentaleatorio en cada petición. Una identidad cambiante con la misma IP y las mismas cookies es una señal de incoherencia. - Cambiar de IP en cada petición en un trabajo que necesita sesión. La sesión se cierra y te redirigen a la página de inicio de sesión.
- Confundir un código de estado correcto con datos correctos. Una página de verificación devuelta con
200produce datos rotos en silencio porque los selectores vuelven vacíos. Comprueba que existe un elemento esperado en el contenido de la respuesta. - No leer robots.txt. Rastrear sin conocer la preferencia del sitio es un mal comienzo tanto ético como legal.
Guía de decisión
| Tu situación | Recomendación |
|---|---|
| Hay una API oficial | Primero la API |
| Pocas páginas de un solo sitio | Una sola IP, velocidad baja, cabeceras coherentes |
| Páginas públicas de muchos sitios | Concurrencia baja por sitio + proxy rotativo |
| Contenido de otro país o ciudad | Proxy residencial con selección de ubicación |
| Tu propia cuenta con sesión iniciada | IP de sesión fija o estática, la misma dirección durante la sesión |
Recibes 429 | Espera lo que indique Retry-After, baja la concurrencia |
| Aparece una pantalla de verificación | Para, sigue la lista de diagnóstico, busca alternativas |
| La página vuelve vacía | Comprueba primero si carga de forma dinámica |
| La ruta está cerrada en robots.txt | No la rastrees |
Preguntas frecuentes
¿Usar un proxy evita los bloqueos por completo?
No. Un proxy reparte el tráfico entre distintas direcciones IP y permite ver contenido según la ubicación, pero las peticiones que se envían demasiado rápido, llevan cabeceras incoherentes o van a rutas que el sitio ha cerrado se bloquean vengan de la IP que vengan. Un proxy funciona junto con la velocidad adecuada y un cliente coherente.
¿Cuántas peticiones por segundo son seguras?
No hay un valor seguro único para todos los sitios; depende de la infraestructura del sitio, del peso de la página y de la hora. Si robots.txt indica un Crawl-delay, respétalo. Si no, empieza a baja velocidad, sube poco a poco vigilando los 429 y los tiempos de respuesta, y retrocede en cuanto veas que el servidor se ralentiza.
¿El User-Agent debe ser un valor de navegador o un nombre de bot?
Para un crawler legítimo, lo recomendable es poner el nombre de tu bot y una dirección de contacto. El administrador del sitio ve quién eres y puede contactarte si hay un problema. Algunos sitios bloquean por defecto a los bots desconocidos; en ese caso, pedir permiso o buscar una API oficial es una vía más sólida que intentar parecer un navegador.
¿Usar un navegador headless reduce el riesgo de bloqueo?
Te permite ver datos en páginas que cargan con JavaScript, pero por sí solo no reduce el riesgo de bloqueo. Al contrario, cada página genera decenas de peticiones adicionales (imágenes, scripts, hojas de estilo) y carga más el sitio. Encontrar la petición de API que la página hace en segundo plano suele ser más eficiente.
Han bloqueado mi IP. ¿Cuánto durará?
Depende del sitio: desde un límite de velocidad de unos minutos hasta una lista negra de días. Si hay una cabecera Retry-After, indica la duración. Si no, espera un tiempo y envía una sola petición a muy baja velocidad para comprobarlo; no sigas a la misma velocidad antes de que se levante el bloqueo.
¿Necesito todas estas precauciones para un trabajo pequeño y puntual?
Para un trabajo puntual de unas decenas de páginas, poner unos segundos entre peticiones, usar un User-Agent con sentido y revisar robots.txt suele bastar. Las demás precauciones cobran importancia cuando el trabajo se vuelve regular y a gran escala.
En resumen
La mayoría de los scrapers no se bloquean por no saber esconderse, sino porque saturan el sitio y parecen incoherentes. Limita la velocidad de las peticiones por sitio, respeta las respuestas 429 y Retry-After, no vuelvas a descargar páginas que no han cambiado, usa una identidad de cliente coherente que te presente y lee robots.txt y las condiciones del sitio. La rotación de IP sirve para repartir la carga y ver contenido según la ubicación, y una IP de sesión fija, para trabajos que necesitan sesión; ninguna de las dos es una herramienta para esquivar un bloqueo explícito. Encontrarás tipos de proxy adecuados para tu trabajo de recogida de datos en nuestros servicios de proxy.




