La mayoría de los proyectos de scraping descubren qué protege un sitio a las malas: el prototipo funciona el lunes, aparece una página de desafío el martes y para el viernes el equipo está reconstruyendo todo en torno a un navegador headless. Gran parte de eso podría saberse desde el primer día. Los productos de gestión de bots dejan rastros visibles en los encabezados de respuesta y las cookies de un sitio, y una sola solicitud ordinaria basta para leerlos.
Hemos construido una pequeña herramienta de consulta que hace exactamente eso, la hemos ejecutado contra las páginas de inicio de los 1.000 dominios principales y hemos registrado qué recibía un cliente HTTP sencillo. Esta guía comparte los resultados, el código y cómo usar la respuesta al planificar un proyecto.
Conclusiones clave
- Una sola solicitud revela mucho. Las cookies y encabezados de proveedores identificaron un proveedor de protección contra bots o seguridad perimetral en el 37% de las 653 páginas de inicio de sitios principales que pudimos cargar, y un producto de gestión de bots activamente en funcionamiento en el 16%.
- Cloudflare fue, con diferencia, el más común, presente en una cuarta parte de las páginas de inicio, seguido de Akamai. DataDome, AWS WAF, Imperva y HUMAN aparecieron con mucha menos frecuencia, y DataDome y HUMAN desafiaron o bloquearon todas las solicitudes que les enviamos.
- A un cliente HTTP sencillo que se hacía pasar por Chrome se le sirvió el 81% de las páginas de inicio, fue desafiado en el 10% y bloqueado en el 9%. Con el User-Agent predeterminado de la librería, los bloqueos aumentaron al 16%.
- Hacerse pasar por un navegador puede ser contraproducente. Las diez tiendas por país de un gran minorista sirvieron páginas de inicio completas al User-Agent honesto de la librería y una página de desafío de uno a dos kilobytes a la solicitud que se hacía pasar por Chrome.
- Trata la consulta como un dato de planificación: te dice qué esperar, si una API oficial o un permiso es la mejor vía, y cómo presupuestar el proyecto.
Qué puede revelar una sola solicitud
Los productos de gestión de bots y seguridad perimetral funcionan situándose delante de un sitio web e inspeccionando cada solicitud. Para ello, la mayoría establece cookies en el navegador del visitante o añade encabezados de respuesta, y esos nombres son estables y a menudo están documentados:
| Proveedor | Evidencia típica | De dónde procede |
|---|---|---|
| Cloudflare | Encabezado cf-ray en todo lo que sirve; cookie __cf_bm cuando Bot Management o Bot Fight Mode está activado; cf-mitigated: challenge en una página de desafío | Documentación de Cloudflare |
| Akamai | Encabezado de número de solicitud Akamai-GRN; cookies _abck, ak_bmsc, bm_sz de Bot Manager | Documentación de Akamai para el encabezado; políticas de cookies del sitio para las cookies |
| DataDome | Cookie datadome; encabezado x-datadome | Documentación de DataDome |
| HUMAN | Cookies _px3, _pxhd, _pxvid | Documentación de HUMAN |
| Imperva | Cookies visid_incap_, incap_ses_, nlbi_ | Políticas de cookies del sitio |
| AWS WAF | x-amzn-waf-action: challenge con HTTP 202 en un desafío; cookie aws-waf-token | Documentación de AWS |
Dos distinciones importan a la hora de leer los resultados. Estar detrás de una red de distribución de contenidos no es lo mismo que ejecutar gestión de bots: un encabezado cf-ray significa que el sitio usa Cloudflare, mientras que una cookie __cf_bm significa que un producto de bots de Cloudflare está puntuando activamente a los visitantes. Y una firma ausente no demuestra nada; muchos sitios ejecutan su propia detección o un producto que no deja rastro en la primera respuesta.
El código
El módulo siguiente lee una respuesta y devuelve los proveedores que detecta junto con la evidencia, si un producto de gestión de bots está activo, y qué recibió la solicitud: servida, desafiada o bloqueada.
import re
# Cookies that each vendor's bot or WAF product sets, and headers it adds. Cookies are the strongest evidence.
SIGNATURES = {
"Cloudflare": {"headers": ["cf-ray"], "cookies": [r"^__cf_bm$", r"^cf_clearance$"]},
"Akamai": {"headers": ["akamai-grn"], "cookies": [r"^_abck$", r"^ak_bmsc$", r"^bm_sz$", r"^bm_sv$"]},
"DataDome": {"headers": ["x-datadome"], "cookies": [r"^datadome$"]},
"HUMAN": {"headers": [], "cookies": [r"^_px(3|hd|vid|cvid|de)$"]},
"Imperva": {"headers": [], "cookies": [r"^visid_incap_\d+$", r"^incap_ses_", r"^nlbi_\d+$", r"^reese84$"]},
"AWS WAF": {"headers": ["x-amzn-waf-action"], "cookies": [r"^aws-waf-token$"]},
}
# Evidence of an active bot-management product, as opposed to only the CDN in front of the site.
BOT_PRODUCT_COOKIES = [r"^__cf_bm$", r"^cf_clearance$", r"^_abck$", r"^ak_bmsc$", r"^bm_sz$", r"^datadome$", r"^_px", r"^reese84$"]
def cookie_names(response):
"""Names of every cookie the response tried to set."""
return {c.split("=", 1)[0].strip() for c in response.raw.headers.getlist("Set-Cookie")}
def detect_stack(response):
"""Return {vendor: [evidence]} from one response's headers and cookies."""
headers = {k.lower() for k in response.headers}
cookies = cookie_names(response)
found = {}
for vendor, sig in SIGNATURES.items():
evidence = [f"header {h}" for h in sig["headers"] if h in headers]
evidence += [f"cookie {c}" for c in sorted(cookies) if any(re.match(p, c) for p in sig["cookies"])]
if evidence:
found[vendor] = evidence
server = response.headers.get("server", "").lower()
if server == "cloudflare":
found.setdefault("Cloudflare", []).append("server header")
if "akamaighost" in server:
found.setdefault("Akamai", []).append("server header")
return found
def bot_product_active(response):
"""True when a cookie shows a bot-management product, not just a CDN, handled the request."""
return any(re.match(p, c) for c in cookie_names(response) for p in BOT_PRODUCT_COOKIES)
def outcome(response):
"""Classify what a request got: served, challenged or blocked."""
body = response.text[:20000].lower()
if (response.headers.get("cf-mitigated", "").lower() == "challenge"
or response.headers.get("x-amzn-waf-action", "").lower() == "challenge"
or "captcha-delivery.com" in body):
return "challenged"
if response.status_code in (401, 403, 405, 429) or response.status_code >= 500 or "incapsula incident id" in body:
return "blocked"
return "served"
Funciona sobre una respuesta de la librería requests y lee las cookies de los encabezados Set-Cookie en bruto, por lo que ve cookies que el cliente de otro modo no conservaría. Observa qué significa “servida” aquí: no se encontró ninguna señal de desafío o bloqueo. No demuestra que la página contuviera el contenido real, una carencia a la que volvemos más abajo.
Lo que encontramos en los 1.000 dominios principales
El 3 de octubre de 2026 solicitamos la página de inicio de cada uno de los 1.000 dominios principales del ranking Tranco, una vez con una cadena User-Agent de Chrome y otra con el valor predeterminado de la librería requests, desde una única conexión en Rumanía. Ambas solicitudes procedían del mismo cliente HTTP en Python, que no ejecuta JavaScript y no tiene la huella de red de un navegador. 653 sitios distintos devolvieron una página de inicio HTML; el resto eran redes de contenido, hosts de API y otros dominios sin una.
| Proveedor detectado | Páginas de inicio | Con cookie activa de gestión de bots |
|---|---|---|
| Cloudflare | 162 (24,8%) | 79 |
| Akamai | 55 (8,4%) | 16 |
| AWS WAF | 14 (2,1%) | 0 |
| DataDome | 8 (1,2%) | 8 |
| HUMAN | 2 | 2 |
| Imperva | 2 | 0 |
| Cualquiera de los anteriores | 241 (36,9%) | 105 (16,1%) |
| Ninguno detectado | 412 (63,1%) | 0 |
Solo dos páginas de inicio mostraron dos proveedores a la vez. Diez de los 14 sitios con AWS WAF eran tiendas por país del mismo minorista.
Lo que recibieron las solicitudes:
| Solicitud | Servida | Desafiada | Bloqueada |
|---|---|---|---|
| User-Agent de Chrome, 653 páginas de inicio | 530 (81,2%) | 64 (9,8%) | 59 (9,0%) |
| User-Agent predeterminado de la librería, 650 páginas de inicio | 500 (76,9%) | 49 (7,5%) | 101 (15,5%) |
Y desglosado por lo que protegía el sitio, contando los sitios en los que ambas solicitudes se completaron:
| Protección detectada | Sitios | User-Agent de Chrome: desafiada o bloqueada | Predeterminado de la librería: desafiada o bloqueada |
|---|---|---|---|
| Cloudflare | 162 | 54 | 63 |
| Akamai | 54 | 26 | 22 |
| DataDome | 7 | 7 | 7 |
| Ninguno detectado | 411 | 19 | 53 |
Lo que dicen los resultados
La mayor parte de la web principal responde a una solicitud sencilla. Cuatro de cada cinco páginas de inicio sirvieron a un cliente HTTP básico que se hacía pasar por Chrome sin un desafío visible. Sin embargo, una página de inicio es la página más fácil de un sitio; los resultados de búsqueda, los precios y los flujos de compra suelen estar protegidos con más rigor que la puerta de entrada.
Los filtros sencillos y los productos serios se comportan de forma distinta. En los sitios sin proveedor detectable, el User-Agent predeterminado de la librería fue desafiado o bloqueado casi tres veces más a menudo que la cadena de Chrome, 53 frente a 19. Esa es la firma de un filtrado sencillo por User-Agent. En los sitios que ejecutan DataDome, ambas solicitudes fueron desafiadas o bloqueadas en todos los casos; el User-Agent no supuso ninguna diferencia.
Una identidad que no encaja puede ser peor que una honesta. Las diez tiendas por país del minorista respondieron a la solicitud que se hacía pasar por Chrome con una página de desafío o marcador de posición de uno a dos kilobytes, y al User-Agent honesto de la librería con la página de inicio completa, de entre 678 KB y 1,4 MB. Repetimos la comprobación para las diez y el patrón se mantuvo. Una cadena User-Agent de Chrome que llega en una conexión que no parece de Chrome, como se explica en la huella digital de TLS y HTTP/2, es en sí misma una señal.
Un estado exitoso no es una página exitosa. Tres de esas páginas marcador de posición volvieron con HTTP 200 y sin encabezado de desafío, de modo que una comprobación basada solo en el estado las cuenta como servidas. Valida el contenido, no solo los códigos de estado, como se trata en la tasa de fallo silencioso y en cómo saber cuándo un sitio te está sirviendo contenido falso o bloqueado.
Usar la consulta para planificar un proyecto
Ejecuta la consulta en las páginas que realmente necesitas, no solo en la página de inicio, y deja que la respuesta dé forma al plan:
| Lo que muestra la consulta | Lo que suele significar | Siguiente paso razonable |
|---|---|---|
| Sin proveedor, solicitud sencilla servida | Poca o ninguna gestión de bots en esa página | HTTP sencillo con identificación honesta, ritmo moderado y los encabezados adecuados |
| Solo CDN, sin cookie de bots | Seguridad perimetral sin puntuación activa de bots | HTTP sencillo, pero vigila los desafíos a medida que aumenta el volumen |
| Cookie de gestión de bots, solicitud servida | Puntuación activa que permitió esta solicitud | Espera desafíos a escala; supervisa con una puntuación de salud del objetivo |
| Desafiada en la primera solicitud | Una decisión deliberada de filtrar clientes automatizados | Busca primero una API oficial o un feed de datos, y luego considera si un navegador está justificado, según cuándo necesitas un navegador headless |
| Bloqueada en la primera solicitud | Reglas estrictas, a menudo por red o región | Comprueba si los datos están disponibles de otra forma, incluyendo la API detrás de la página, y si el bloqueo es regional |
La consulta también dice algo sobre la intención. Un sitio que ejecuta un producto activo de gestión de bots ha decidido controlar el acceso automatizado, y eso merece sopesarse junto con sus términos y su robots.txt, como se trata en robots.txt, exclusiones de IA y señales de reserva. Para muchos proyectos, la respuesta correcta ante un objetivo muy protegido es una licencia, una colaboración o una API oficial en lugar de una escalada. Cuando la recopilación es apropiada, la escalera de escalada para sitios protegidos explica las opciones por orden de coste.
Límites de la medición
- Solo páginas de inicio. Las páginas más profundas a menudo están protegidas de forma distinta.
- Una solicitud de cada, desde una sola red. Los resultados pueden variar según el país, la reputación de la red, la hora del día y el historial de solicitudes; cubrimos las diferencias regionales en qué países sufren más bloqueos geográficos.
- Sin navegador. Muchos desafíos están diseñados para ser superados por un navegador real que ejecuta JavaScript; nuestro cliente no podía, por diseño.
- Las firmas se les escapan cosas. La detección propia y los productos que no dejan rastro en la primera solicitud se cuentan como “ninguno detectado”, por lo que la proporción real de sitios protegidos es mayor.
Conclusión
Una sola solicitud ordinaria te dice la mayor parte de lo que necesitas para planificar un proyecto de scraping: quién protege el sitio, si la puntuación de bots está activa y cómo se trata a un cliente sencillo. En los 1.000 dominios principales, la mayoría de las páginas de inicio respondieron, una cuarta parte estaba detrás de Cloudflare, uno de cada seis ejecutaba un producto activo de gestión de bots, y los productos más estrictos desafiaron o bloquearon todas las solicitudes que les enviamos.
Ejecuta la consulta antes de escribir el scraper, en las páginas que necesitas. Deja que te diga cuándo mantener las cosas simples, cuándo planificar para un navegador, y cuándo buscar en su lugar una vía oficial hacia los datos.
Fuentes y referencias
- Cloudflare, Cookies de Cloudflare y detección de la respuesta de una página de desafío.
- Akamai, Número de solicitud global.
- DataDome, Cookies y datos almacenados.
- HUMAN, Uso de cookies y almacenamiento web.
- AWS, CAPTCHA y Challenge en AWS WAF.
- Tranco, lista Q2K34.
- Páginas de inicio solicitadas por Shifter el 3 de octubre de 2026, usando el código anterior.