Akamai Bot Manager es una de las soluciones anti-bot más comunes en el mercado. Se utiliza por muchos sitios web de alto perfil, desde sitios de comercio electrónico a sitios de viajes, y, dependiendo de su configuración, puede ser difícil de eludir. Basado en mi experiencia, el patrón típico que encuentro cuando un sitio web activa la protección de Akamai Bot Manager es que el rascador (normalmente un Scrapy en mi pila) se coloca y se apaga desde la primera solicitud. Pero ¿qué es Akamai Bot Manager, y cómo puedo ver si un sitio web lo está usando? Actualización de Akamai Bot Manager La detección de bot de Akamai, como cualquier otro software moderno de protección anti-bot, funciona en múltiples capas. Es uno de los primeros: Akamai analiza los detalles de la mano y la conexión de TLS (impresión digital de TLS de JA3, suites de cifrado, versión de TLS, etc.) para ver si coinciden con un navegador real o una herramienta de automatización conocida. cada navegador (Chrome, Firefox, Safari, etc.) tiene una huella digital TLS característica, y si el cliente de su cliente TLS Client Hello no coincide con ningún navegador común, Akamai sabe que algo está mal. Network fingerprinting También inspecciona – Los navegadores reales casi siempre usan HTTP/2+ estos días, y envían encabezados HTTP en un orden y formato específicos.Si un cliente todavía está utilizando HTTP/1.1 o tiene encabezados en un orden no navegador, es una bandera roja. Además, Akamai busca encabezados específicos del navegador o valores que los rascadores podrían omitir; asegurando sus encabezados (User-Agent, Accept-Language, etc.) El espejo de un verdadero navegador es crucial. HTTP/2 usage and header order and their order Otro lago es Akamai verifica si el IP del cliente proviene de una red residencial, de una red móvil o de un centro de datos. Los IP residenciales y móviles (el tipo de usuarios reales que tienen) obtienen altas puntuaciones de confianza, mientras que los rangos de IP del centro de datos conocidos son automáticamente sospechosos. - Siempre parecen venir de diferentes ubicaciones de usuarios reales, no de una granja de servidores en la nube. IP reputation and analysis residential proxies Por último, Un sensor JavaScript en la página web recopila una multitud de puntos de datos sobre el entorno y las interacciones del cliente (como el timing, los movimientos del ratón, o su ausencia, propiedades inusuales en el objeto del navegador, etc.).Los modelos de IA de Akamai recopilan estos datos para asignar una puntuación de probabilidad de bot a cada sesión.Este aspecto es el más difícil de eludir y a menudo requiere ejecutar un navegador sin cabeza o replicar la lógica del sensor. (Es más allá de nuestro alcance aquí - nuestro foco será pasar las comprobaciones a nivel de red, que es el caso más común para los sitios web de comercio electrónico, en mi experiencia.) Empleo de Akamai Análisis del comportamiento Uso de scripts del lado del cliente y modelos AI Empleo de Akamai Análisis del comportamiento Análisis del comportamiento Uso de scripts del lado del cliente y modelos AI Pero ¿cómo podemos detectar que un sitio web está utilizando Akamai Bot Manager? Aparte de Si notas el y Las cookies utilizadas en un sitio web, esta es la señal más clara de que está utilizando Akamai para protegerse. La extensión del navegador Wappalyzer habitual abc y bmsc La extensión del navegador Wappalyzer habitual abc abc y bmsc y bmsc Dadas estas defensas, muchos usuarios de Scrapy se han Descarga de la aplicación para el paso de Akamai. Este plugin integra la biblioteca para fingir firmas de red de navegadores reales. scrapy-impersonate curl_cffi En la práctica, Scrapy Impersonate hace que las solicitudes de tu araña de Scrapy "se parezcan" a un Chrome o Firefox: ofrece huellas dactilares TLS (JA3) que coinciden con esos navegadores, utiliza HTTP/2, e incluso ajusta los encabezados de cuadros HTTP/2 de bajo nivel para imitar los patrones del navegador. Al hacerlo, aborda el problema de huellas dactilares TLS y HTTP/2 - una araña de Scrapy con este manipulador puede agarrarse a un servidor protegido por Akamai de una manera que es casi indistinguible de un navegador normal de Chrome. Características de Scrapy Impersonate Si bien Scrapy Impersonate es una herramienta poderosa, viene con ciertas limitaciones: Scrapy Impersonate is designed as a Scrapy download handler, which means it only works within Scrapy’s asynchronous framework. If your project doesn’t use Scrapy or you want to switch to a different framework (like a simple script with / or an asyncio pipeline), you can’t directly carry over its capabilities. Migrating away from Scrapy often means a of your HTTP logic, and you’d lose the built-in TLS spoofing unless you implement a new solution from scratch. Locked into Scrapy: requests httpx complete rewrite Using Scrapy Impersonate alongside proxy rotation can be tricky. Under the hood, it replaces Scrapy’s default downloader with one based on , which doesn’t seamlessly integrate with Scrapy’s proxy middleware. Early adopters discovered that HTTPS proxy support was broken because the proxy handling code was bypassed. Although fixes and workarounds (like disabling Scrapy’s built-in proxy handling and configuring directly) exist, it’s harder to rotate proxies or handle proxy authentication with this setup. Robust error handling for proxy failures (e.g., detecting a dead proxy and retrying) is not as straightforward as with Scrapy’s standard downloader, because errors bubble up from the layer and may not trigger Scrapy’s usual retry logic. Proxy Rotation Challenges: curl_cffi curl_cffi curl Scrapy Impersonate currently supports a finite list of browser fingerprints (Chrome, Edge, Safari, etc., up to certain versions). This list can lag behind the latest browser releases. You might be stuck impersonating an older browser version, which could be a problem if a target site specifically requires the nuances of a newer TLS handshake (some advanced WAFs actually check minor details that change between Chrome versions). Maintenance and Flexibility: Perhaps most importantly, even with proper TLS and HTTP/2 impersonation, . For websites that have implemented a higher level of protection, checking also the browser fingerprint, any browserless configuration, including Scrapy Impersonate, isn’t sufficient for Akamai or similar top-tier bot defenses. You might get past the TLS handshake, but fail on other signals (like the absence of the expected sensor data or subtle discrepancies in headers/cookies). In other words, it’s a piece of the puzzle, not a complete solution. Not a Silver Bullet: Akamai Bot Manager can still detect and block you La solución que veremos hoy ayuda a resolver los dos primeros puntos: nos conectaremos juntos , para una huella digital óptima de TLS y un proxy residencial rotativo para rotar nuestros IPs y tener mejores puntuaciones de reputación. JA3Proxy JA3Proxy Comprensión de las huellas dactilares de TLS y JA3 Antes de sumergirse en la solución, es importante comprender qué exactamente estamos falsificando. Cada cliente HTTPS presenta un Esta huella es una combinación de la versión del protocolo TLS y un montón de opciones que el cliente dice que soporta – piense en ello como el “dialecto” del cliente de hablar TLS. Los componentes clave incluyen: TLS fingerprint e.g. TLS 1.2 vs TLS 1.3. Modern browsers will offer 1.3 (while still allowing 1.2 for compatibility). Older clients or some libraries might only do 1.2. Supported TLS Version: the list of cryptographic algorithms the client can use, in preferred order. Browsers tend to have long lists including ciphers like AES-GCM, ChaCha20, etc., plus some GREASE (randomized) values to prevent fingerprinting. Cipher Suites: extra features in TLS, like Server Name Indication (SNI), supported groups (elliptic curves), ALPN (which is used for HTTP/2 negotiation), etc. Both the presence of certain extensions and their order matter. Extensions: El concepto de es una forma estandarizada de grabar estos detalles de TLS Client Hello. JA3, nombrado después de las iniciales de sus creadores, compone una cadena de huellas dactilares concatenando los campos anteriores en un orden específico: JA3 fingerprinting JA3_string = TLSVersion,CipherSuiteIDs,ExtensionIDs,EllipticCurveIDs,EllipticCurveFormatIDs Cada lista (cifras, extensiones, etc.) está unida por y las secciones de Por ejemplo, un navegador de Chrome podría producir una cadena JA3 como: - , 771,4866-4867-4865-....-47-255,0-11-10-16-23-...-21,29-23-30-25-24,0-1-2 Esto representa TLS 1.2 (771 es 0x0303), un conjunto específico de suites de cifrado, extensiones, curvas soportadas y formatos de curva (los números son ID estandarizados). Las herramientas de seguridad a menudo registran o comparan el hash MD5 (ya que es más fácil de manejar que una larga cadena de números). MD5 hashed ¿Por qué es importante esto para la detección de bot? porque Chrome versión X en Windows Presenta la misma huella JA3 hasta el orden de la lista. Firefox tendrá su propio JA3 distinto. browser TLS stacks are fairly uniform siempre La biblioteca de solicitudes de Python (que utiliza OpenSSL bajo el capó) tiene un JA3 que es totalmente diferente de cualquier navegador principal, por lo que es fácilmente detectable. Los servicios anti-bot como Akamai mantienen bases de datos de hashes JA3: si su JA3 no está en la lista de "buenos conocidos" (browsers comunes) o si está en una lista de automatización conocida, se le marcará. En resumen, para pasar los controles de huellas dactilares TLS de Akamai, . we need our client’s JA3 to match a popular browser Esto suele significar imitar la última huella digital de Chrome o Firefox (ya que son los usuarios legítimos más comunes en la web). Simplemente cambiar la cadena User-Agent no es suficiente: debemos modificar el toque de mano de TLS de bajo nivel. (que en sí misma aprovecha una construcción especial de bibliotecas curl y TLS para imitar navegadores). pero fuera de Scrapy, necesitamos otra forma de lograr el mismo efecto. curl_cffi TLS Impersonation Proxy + cadena de proxy residencial Nuestra solución es a Para hacer que nuestro rascador sea prácticamente indistinguible de un usuario real del navegador: chain two proxies JA3Proxy is an open-source tool that acts as an HTTP(S) proxy that replays traffic with a chosen TLS fingerprint. In other words, you run JA3Proxy locally, configure it to imitate a specific browser’s TLS handshake, and then direct your scraper traffic through it. JA3Proxy will terminate your TLS connection and initiate a new TLS handshake to the target site using the impersonated fingerprint. From the target site’s perspective, it looks like, say, a Chrome browser connecting. The beauty of this approach is that – you can use Python , , cURL, or anything, by simply pointing it at JA3Proxy. You are no longer locked into Scrapy or any particular library to get browser-like TLS; the proxy takes care of it. JA3Proxy for TLS Impersonation: it’s client-agnostic requests httpx Under the hood, JA3Proxy uses (an advanced TLS library in Go) to customize the Client Hello. It supports a variety of client profiles (Chrome, Firefox, Safari, etc., across different versions). You can, for example, configure it to mimic the latest browsers available in the library. For our needs, we’d choose the latest available Chrome fingerprint, Chrome 133. As for Scrapy-Impersonate, the integration of the latest browsers in the library can take some time, but until this gets regularly updated, it’s not an issue. uTLS One thing to note: JA3Proxy focuses on TLS fingerprints (the JA3 part). It doesn’t inherently modify HTTP headers (other than those that relate to TLS, like ALPN for HTTP/2) or handle higher-level browser behaviors. It gets us past the network fingerprinting, which is the hardest to change, but we must still ensure our HTTP headers and usage patterns are correct. Luckily, we can manually set headers in our HTTP client to mimic a browser (User-Agent, etc.), and HTTP/2 can be achieved as long as the TLS negotiation allows it (Chrome’s Client Hello will advertise ALPN support for h2, so if the site supports it, JA3Proxy will negotiate HTTP/2). The second part of the chain is an upstream . This will take care of the IP reputation and distribution. Residential Proxy for IP Rotation: residential proxy The combined effect is powerful: to Akamai, your scraper now looks like Chrome 133 running on a residential IP. The TLS handshake matches Chrome’s JA3, the HTTP/2 and headers can be adjusted to match Chrome, and the source IP is a regular household. This addresses the major fingerprinting vectors at the network level. It doesn’t solve Akamai’s JavaScript-based challenges by itself, but this should be enough to bypass most of the websites you’ll encounter. Guía de configuración de JA3Proxy Vamos a configurar JA3Proxy y conectarlo con un proxy residencial. Instalación de JA3Proxy JA3Proxy está escrito en Go. Tienes dos opciones fáciles: compilar desde la fuente o usar un contenedor Docker. Para construir desde la fuente, necesitarás Go instalado. git clone https://github.com/LyleMi/ja3proxy.git cd ja3proxy make Esto debe producir a puede ejecutarse en la carpeta. (Alternativamente, puede manualmente ya que el proyecto está basado en Go.) ja3proxy go build Si prefiere Docker, hay una imagen pre-construida en el Registro de contenedores de GitHub. docker pull ghcr.io/lylemi/ja3proxy:latest Obtendrá la imagen más reciente.Puede ejecutarla con (Mostraremos el comando de ejecutar en un instante.) Docker es conveniente porque lo envuelve todo sin necesidad de un entorno Go local. docker run En mi experiencia personal, la instalación fue un poco como una pesadilla. No pude hacer que la imagen de Docker funcionara, ya que constantemente recibí errores cuando intenté conectarme a ella, ya que no se reconoció ningún navegador. Luego decidí construir manualmente en mi Mac, y encontré los mismos errores. Sin embargo, después de horas de depuración, encontré que necesitaba actualizar algunas dependencias, especialmente uTLS; hubo conflictos en las versiones de las bibliotecas, y todo esto causaba problemas. De todos modos, logré instalarlo, así que si obtienes algunos errores al principio, no renuncies. Obtener o crear certificados TLS JA3Proxy puede actuar como un proxy HTTPS, lo que significa que intercepta TLS y presenta su propio certificado a su cliente. Por defecto, se busca y Si no proporciona uno, puede ejecutarlo en modo simple (como un proxy HTTP normal) y simplemente ignorar la verificación de certificado en su cliente (no se recomienda para la producción, pero es aceptable para la prueba). cert.pem key.pem La mejor práctica es generar un certificado raíz y clave auto-signado, y configurar su rascador para confiar en ese certificado, para que pueda interceptar el tráfico sin advertencias de seguridad. openssl req -x509 -newkey rsa:2048 -sha256 -days 365 -nodes -keyout key.pem -out cert.pem -subj "/CN=JA3Proxy" Esto crea a / (Para el uso de la producción, puede incluso usar un CA interno legítimo si tiene esa configuración, pero para la mayoría de los propósitos de rascado, un auto firmado está bien siempre que su cliente sepa confiar en él.) cert.pem key.pem Inicia JA3Proxy con una huella digital de Chrome Ahora ejecutamos el proxy. Si usamos el binario, ejecutemos un comando como: ./ja3proxy -port 8080 -client Chrome -version 131 -cert cert.pem -key key.pem -upstream YOURPROXYIP:PORT Vamos a romper este comando: -Port 8080 le dice que escuche en el puerto 8080 (puede elegir otro puerto si es necesario). -client Chrome -versión 131 selecciona el perfil de huellas dactilares. En este ejemplo, utiliza el perfil integrado para Chrome 131. Los reemplazarías con el perfil que coincida con el navegador/versión que desees -por ejemplo, si Chrome 130 es compatible en la versión más reciente, puedes usar -client Chrome -versión 130. (Puedes encontrar la lista de huellas dactilares disponibles comprobando la documentación de JA3Proxy o la biblioteca uTLS que utiliza. -cert y -key especifique los archivos de certificado TLS que generamos en el paso 2. -upstream 123.45.67.89:1080 es la dirección del proxy upstream. Esto debe ser reemplazado con su punto final de proxy residencial. Importante: JA3Proxy espera que esto sea una dirección de proxy SOCKS5__github.com__. Si su proveedor le dio algo como proxy.provider.com:8000 con un nombre de usuario / contraseña, puede probar el formato de nombre de usuario:password@proxy.provider.com:8000. (JA3Proxy analizará la cadena y debe manejar la autenticación para SOCKS5 si se le da en el formulario de usuario:pass@host:port. Si eso no funciona, puede configurar su proxy residencial para ser IP-permitido o usar una característica de lista blanca de IP para evitar auth, o ejecutar un proxy local Si se usaba Docker, el equivalente sería: docker run -p 8080:8080 \ -v $(pwd)/cert.pem:/app/cert.pem -v $(pwd)/key.pem:/app/key.pem \ ghcr.io/lylemi/ja3proxy:latest \ -client Chrome -version 133 -cert /app/cert.pem -key /app/key.pem \ -upstream YOURPROXYIP:PORT Montamos el cert y la tecla en el contenedor y exponemos el puerto 8080. Ajuste el comando para incluir sus credenciales/host proxy reales. (o cualquiera que sea el host / puerto que especifique). localhost:8080 Un caso de uso del mundo real - MrPorter.com MrPorter.com es un sitio web de comercio electrónico de moda que, junto con muchos otros en la industria, se protege con Akamai Bot Manager. Usando una simple solicitud de Python, tal como se especifica en el archivo En el repositorio, encontré un error de tiempo, como se esperaba. simple_request.py import requests URL = "https://www.mrporter.com/en-gb/mens/product/loewe/clothing/casual-shorts/plus-paula-s-ibiza-wide-leg-printed-cotton-blend-terry-jacquard-shorts/46376663162864673" headers = { "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8", "accept-language": "en-US,en;q=0.5", "priority": "u=0, i", "sec-ch-ua": "\"Brave\";v=\"135\", \"Not-A.Brand\";v=\"8\", \"Chromium\";v=\"135\"", "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": "\"macOS\"", "sec-fetch-dest": "document", "sec-fetch-mode": "navigate", "sec-fetch-site": "none", "sec-fetch-user": "?1", "sec-gpc": "1", "service-worker-navigation-preload": "true", "upgrade-insecure-requests": "1", "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36" } def main(): try: response = requests.get(URL, headers=headers, timeout=10) response.raise_for_status() print(response.text) except requests.RequestException as e: print(f"Error fetching the page: {e}") if __name__ == "__main__": main() El resultado: Error fetching the page: HTTPSConnectionPool(host='www.mrporter.com', port=443): Read timed out. (read timeout=10) Por el uso , de No obstante, no pude encontrar una base de datos que indique que las solicitudes de Python usan comúnmente esta huella digital. por supuesto, es diferente de la huella digital que tengo usando Brave Browser, con los mismos encabezados y Agente de Usuario. La herramienta de impresión digital Scrapfly TLS Podemos ver los resultados La herramienta de impresión digital Scrapfly TLS Podemos ver los resultados El orden de las Cipher Suites es diferente, y por lo tanto, la huella digital también será diferente. Ahora, iniciemos el docker JA3Proxy, sin conectar un proxy residencial, y veamos lo que sucede. docker run -p 8080:8080 \ -v $(pwd)/cert.pem:/app/cert.pem -v $(pwd)/key.pem:/app/key.pem \ ghcr.io/lylemi/ja3proxy:latest \ -client Chrome -version 131 -cert /app/cert.pem -key /app/key.pem Hemos recibido el mensaje HTTP Proxy Server listen at :8080, with tls fingerprint 131 Chrome para que podamos usar localhost:8080 como un proxy en nuestro script de solicitud de Python. Otra causa de errores en mi configuración fue que intenté usar Python Requests para conectarme a JA3Proxy. Después de cavar por un tiempo, encontré que el problema era que la biblioteca de solicitudes no soporta HTTP/2, mientras que JA3Proxy lo hace cuando se utiliza una versión moderna de Chrome. Para mis pruebas, necesito usar HTTPX, como se muestra en el archivo . request_with_proxies.py En este caso, si llamo de nuevo la API de Scrapfly TLS, la primera parte de la cadena JA3 (el orden de cifrado) . es idéntico al de mi navegador es idéntico al de mi navegador Como prueba final, si usamos este script para solicitar la página de MrPorter, podemos descargarlo sin ningún problema. Configuración de un proxy residencial Ahora que hemos resuelto la falsificación de la huella digital de TLS, solo tenemos que rotar la IP que verá el sitio web de destino. JA3Proxy tiene una opción que nos ayuda en esto, llamada Upstream. Al iniciar el comando JA3Proxy como sigue, ./ja3proxy -addr 127.0.0.1 -client Chrome -version 131 -cert cert.pem -key key.pem -upstream socks5h://USER:PASS@PROVIDER:PORT -debug podemos tunelar nuestras solicitudes utilizando nuestro proveedor de proxy preferido. Tenga en cuenta que debe conectarse a través de SOCKS5, por lo que asegúrese de que su proveedor soporte esta función. Al comprobar la IP después de hacer esto, puedo ver que mis IPs de rotación residencial están en su lugar, y puedo seguir descargando páginas de MRPorter sin ningún problema. pierluigivinciguerra@Mac 85.AKAMAI-JA3PROXY % python3.10 request_with_proxies.py 200 {"ip":"5.49.222.37"} pierluigivinciguerra@Mac 85.AKAMAI-JA3PROXY % python3.10 request_with_proxies.py 200 {"ip":"197.244.237.29"} pierluigivinciguerra@Mac 85.AKAMAI-JA3PROXY % python3.10 request_with_proxies.py 200 {"ip":"41.193.144.67"} pierluigivinciguerra@Mac 85.AKAMAI-JA3PROXY % python3.10 request_with_proxies.py 200 {"ip":"102.217.240.216"} pierluigivinciguerra@Mac 85.AKAMAI-JA3PROXY % python3.10 request_with_proxies.py Conclusiones El nivel de protección del sitio web es medio, por lo que no hay desafío complejo de huellas dactilares del navegador para eludir, pero, en mi experiencia, es el caso de uso más común cuando nos encontramos con Akamai en nuestro camino. Decidí seguir el enfoque JA3Proxy para eludirlo, para que esta solución pueda utilizarse en diversos marcos.Si estás utilizando Scrapy, siempre puedes confiar en Scrapy Impersonate, a pesar de sus limitaciones, o puedes intentar establecer las cifras en el orden correcto manualmente. El artículo es parte de la serie “The Lab” de Pierluigi Vinciguerra. Compruebe su página Substack para obtener más información sobre el rascado web. El artículo es parte de la serie “The Lab” de Pierluigi Vinciguerra. Compruebe su página Substack para obtener más información sobre el rascado web. “El laboratorio”