Todo scraper que establece una cabecera User-Agent elige una versión de navegador, y casi ninguno la cambia nunca. La cadena entra en un archivo de configuración el día en que empieza el proyecto, y el proyecto sigue anunciándose como ese navegador durante años. Mientras tanto, los navegadores reales avanzan: Chrome publicó 13 versiones principales entre finales de septiembre de 2025 y finales de septiembre de 2026.
¿Importa esa desviación? Los sistemas anti-bot saben qué versiones de navegador usan los visitantes reales, así que una versión que nadie ha usado en años destaca. Medimos cuánto, solicitando las páginas de inicio de 397 sitios principales mientras declarábamos cinco versiones distintas de Chrome, desde la versión actual hasta una con seis años y medio de antigüedad.
Conclusiones clave
- Las versiones declaradas más antiguas fueron rechazadas con más frecuencia, siempre. El 17,1% de las páginas de inicio desafió o bloqueó la versión actual de Chrome; el 19,9% rechazó una versión con un año de antigüedad y el 22,7% una con seis años y medio.
- El efecto solo fue en un sentido. 22 sitios que sirvieron la versión actual rechazaron la más antigua; ningún sitio rechazó la versión actual y sirvió una antigua.
- Dos solicitudes idénticas para la versión actual produjeron resultados idénticos en los 397 sitios, por lo que las diferencias no son ruido.
- Los sitios protegidos por Akamai reaccionaron primero: 9 de los 11 sitios que rechazaron una versión con solo un año de antigüedad estaban protegidos por Akamai. Los sitios protegidos por Cloudflare en su mayoría solo reaccionaron ante la versión más antigua.
- Mantén la versión actualizada, mantenla coherente con el resto de la solicitud y revísala periódicamente, como harías con cualquier dependencia.
Cómo medimos
Tomamos 400 sitios al azar de las páginas de inicio de nuestra búsqueda anterior de pilas anti-bot de los 1.000 dominios principales en el ranking Tranco. El 5 de octubre de 2026 solicitamos cada página de inicio seis veces, con un segundo de diferencia y en un orden aleatorio por sitio, con una cadena User-Agent estándar de Chrome en Windows que declaraba estas versiones:
| Versión declarada | Lanzamiento estable | Antigüedad en la prueba |
|---|---|---|
| Chrome 154, solicitada dos veces | 22 de septiembre de 2026 | Actual |
| Chrome 141 | 30 de septiembre de 2025 | Aproximadamente 1 año |
| Chrome 129 | 17 de septiembre de 2024 | Aproximadamente 2 años |
| Chrome 110 | 7 de febrero de 2023 | Aproximadamente 3,5 años |
| Chrome 80 | 4 de febrero de 2020 | Aproximadamente 6,5 años |
La solicitud repetida para la versión actual es el control: si un sitio varía por sí mismo, se manifiesta como una diferencia entre esas dos. Todas las solicitudes procedían del mismo cliente HTTP de Python y la misma conexión; solo cambió el número de versión en el User-Agent. Tres sitios no respondieron a al menos una solicitud y fueron excluidos, quedando 397.
Lo que encontramos
| Versión declarada | Servida | Desafiada | Bloqueada | Desafiada o bloqueada |
|---|---|---|---|---|
| Chrome 154, primera solicitud | 329 | 42 | 26 | 17,1% |
| Chrome 154, repetición | 329 | 42 | 26 | 17,1% |
| Chrome 141 | 318 | 43 | 36 | 19,9% |
| Chrome 129 | 315 | 43 | 39 | 20,7% |
| Chrome 110 | 314 | 43 | 40 | 20,9% |
| Chrome 80 | 307 | 52 | 38 | 22,7% |
Las dos solicitudes para la versión actual coincidieron en todos y cada uno de los sitios, lo que facilita la lectura del resto de la tabla: cada diferencia es el número de versión.
Contando solo los sitios que sirvieron la versión actual ambas veces, el número que rechazó la versión más antigua creció de forma constante con su antigüedad:
| Versión declarada | Sitios que sirvieron la versión actual pero rechazaron esta |
|---|---|
| Chrome 141, 1 año de antigüedad | 11 |
| Chrome 129, 2 años de antigüedad | 14 |
| Chrome 110, 3,5 años de antigüedad | 15 |
| Chrome 80, 6,5 años de antigüedad | 22 |
Ningún sitio hizo lo contrario. Una versión obsoleta nunca ayudó.
Quién reacciona, y cómo
Al cruzar los sitios con la protección detectada en la búsqueda anterior se observa que los proveedores trazan la línea en lugares diferentes:
- Un año fue suficiente para Akamai. De los 11 sitios que rechazaron Chrome 141, 9 estaban protegidos por Akamai; los 11 respondieron con HTTP 403, y 10 de ellos fueron bloqueos directos en lugar de desafíos.
- Cloudflare reaccionó ante la versión muy antigua. De los 22 sitios que rechazaron Chrome 80, 10 estaban protegidos por Cloudflare y devolvieron un desafío; 9 más eran de Akamai.
- Las páginas rara vez informaron al visitante. Solo dos sitios mostraron un mensaje de tipo “actualiza tu navegador” a Chrome 80 que no mostraban a la versión actual. La mayoría simplemente rechazó la solicitud.
Esto es coherente con el funcionamiento de la gestión de bots. Un visitante real con un navegador de un año de antigüedad es poco común, y con uno de seis años, raro, por lo que una versión antigua es una señal débil por sí sola y una señal más fuerte combinada con cualquier otra cosa inusual en la solicitud.
El código
La función a continuación ejecuta la misma comparación contra cualquier URL: solicita la página declarando cada versión, en orden aleatorio, y devuelve el estado, el resultado y el tamaño de cada una, además de si la página indica al visitante que su navegador está desactualizado. Incluye una versión dos veces para obtener un control de ruido.
import random
import re
import time
import requests
CHROME = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{v}.0.0.0 Safari/537.36"
OUTDATED = re.compile(r"(browser (is|you are using is) (not supported|out of date|outdated|no longer supported)"
r"|update your browser|upgrade your browser|unsupported browser|outdated browser)", re.I)
def classify(response):
"""served, challenged or blocked, from the status and well-known challenge markers."""
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:
return "blocked"
return "served"
def ua_drift_check(url, versions, pause=1.0, seed=None):
"""Request the same URL claiming each Chrome version, in random order, and compare what comes back.
A version may be listed twice, as a control for how much the site varies on its own."""
order = list(enumerate(versions))
random.Random(seed).shuffle(order)
results = [None] * len(versions)
for i, v in order:
headers = {"User-Agent": CHROME.format(v=v), "Accept": "text/html,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.9"}
try:
r = requests.get(url, headers=headers, timeout=20)
results[i] = {"version": v, "status": r.status_code, "outcome": classify(r), "bytes": len(r.content),
"outdated_notice": bool(OUTDATED.search(r.text))}
except requests.RequestException as e:
results[i] = {"version": v, "error": type(e).__name__}
time.sleep(pause)
return results
Ejecútalo contra los sitios de los que dependes antes y después de un cambio de User-Agent, y conserva los resultados: si un objetivo empieza a rechazar la versión que envías, sabrás si la versión es la razón.
Límites de la medición
- Páginas de inicio, una red, un momento. Páginas más profundas, otros países y otros momentos pueden comportarse de forma diferente.
- No es un navegador. Nuestro cliente envió un User-Agent de Chrome desde una biblioteca HTTP de Python, así que cada solicitud ya tenía una huella de red que no coincidía con Chrome, como se explica en huella digital de TLS y HTTP/2. La comparación aísla el efecto del número de versión; no muestra cómo se comportaría un navegador real de cada versión.
- La base no es cero. El 17% de las páginas de inicio rechazó incluso la versión actual de este cliente, lo cual recuerda que un User-Agent correcto es necesario, pero no suficiente.
También debemos reconocer un hallazgo sobre nosotros mismos. Nuestra búsqueda de anti-bot de principios de esta semana usó un User-Agent de Chrome 129: una cadena con dos años de antigüedad, copiada de un script más antiguo. Según esta medición, costó unos pocos puntos porcentuales de páginas de inicio.
Mantener tu User-Agent actualizado
- Trátalo como una dependencia. Pon la versión del navegador en un único lugar y actualízala según un calendario; Chrome lanza una nueva versión principal aproximadamente cada cuatro semanas.
- Mantente dentro de pocas versiones de la actual. En nuestros datos, una versión con un año de antigüedad ya era rechazada con más frecuencia que la actual.
- Mantén todo coherente. Una versión actual de Chrome con un orden de cabeceras antiguo, client hints ausentes o una huella de red que no es de navegador sigue siendo incoherente; establecer las cabeceras y el User-Agent correctos cubre el conjunto completo.
- Usa una identidad por sesión. Rotar versiones dentro de una misma sesión resulta más sospechoso que cualquier versión individual.
- Prueba en CI. Una revisión programada de los objetivos clave con la configuración actual y la anterior detecta la desviación antes de que aparezca en tus datos; ejecutar scrapers en CI/CD muestra cómo configurarlo.
- Vigila la tasa de rechazo. Un aumento lento de los 403 y de los desafíos es el síntoma típico de la desviación; pertenece a una puntuación de salud del objetivo.
Conclusión
Una versión de navegador no es un ajuste que se elige una sola vez. En nuestra medición de 397 sitios principales, cada año de desviación en la versión de Chrome declarada añadió rechazos, el efecto nunca fue en sentido contrario, y algunos servicios de protección reaccionaron ante una versión con solo un año de desfase.
Mantén la versión actualizada, mantén el resto de la solicitud coherente con ella, y mide el efecto en los objetivos que te importan. Es una de las mejoras de fiabilidad más baratas que puede hacer un proyecto de scraping.
Fuentes y referencias
- Chromium Dash, calendario de lanzamientos, para las fechas de lanzamiento estable y la versión actual.
- Tranco, lista Q2K34.
- Solicitudes realizadas por Shifter el 5 de octubre de 2026 usando el código anterior.