Akamai Bot Manager est l'une des solutions anti-bot les plus courantes sur le marché. Il est utilisé par de nombreux sites Web haut de gamme, allant des sites de commerce électronique aux sites de voyage, et, selon sa configuration, peut être difficile à contourner. Sur la base de mon expérience, le modèle typique que je rencontre lorsqu'un site Web active la protection Akamai Bot Manager est que le scraper (généralement un Scrapy dans mon pile) s'accroche et s'éteint à partir de la première demande. Mais qu’est-ce que Akamai Bot Manager, et comment puis-je voir si un site Web l’utilise? Gestionnaire de bot Akamai La détection des robots d’Akamai, comme tout autre logiciel de protection anti-bot moderne, fonctionne sur plusieurs couches. est l'un des premiers: Akamai analyse les détails de la prise de main et de la connexion TLS (empreinte digitale TLS JA3, suites de chiffrement, version TLS, etc.) pour voir s'ils correspondent à un navigateur réel ou à un outil d'automatisation connu. Chaque navigateur (Chrome, Firefox, Safari, etc.) a une empreinte digitale TLS caractéristique, et si votre client TLS Client Hello ne correspond pas à un navigateur courant, Akamai sait que quelque chose est dangereux. Network fingerprinting Il inspecte également – les navigateurs réels utilisent presque toujours HTTP/2+ ces jours-ci, et ils envoient des en-têtes HTTP dans un ordre et un format spécifiques.Si un client utilise toujours HTTP/1.1 ou a des en-têtes dans un ordre non-browser, c’est un drapeau rouge.En outre, Akamai recherche des en-têtes spécifiques au navigateur ou des valeurs que les scrapers pourraient omettre; assurant vos en-têtes (User-Agent, Accept-Language, etc.) Le miroir d’un vrai navigateur est crucial. HTTP/2 usage and header order and their order Une autre couche est Akamai vérifie si l'IP du client provient d'un réseau résidentiel, d'un réseau mobile ou d'un centre de données. Les IP résidentiels et mobiles (le type d'utilisateurs réels) obtiennent un score élevé de confiance, alors que les gammes IP du centre de données connues sont automatiquement suspectes. Les demandes de volume élevées d'une adresse IP unique ou d'un sous-réseau IP réduisent également le score de confiance. – toujours paraître provenir de différents emplacements d’utilisateurs réels, pas d’une ferme de serveurs cloud. IP reputation and analysis residential proxies Enfin , Un capteur JavaScript sur la page Web recueille une multitude de points de données sur l’environnement et les interactions du client (tels que le timing, les mouvements de souris ou leur absence, les propriétés inhabituelles de l’objet du navigateur, etc.).Les modèles d’IA d’Akamai recueillent ces données pour attribuer un score de probabilité de bot à chaque session.Cet aspect est le plus difficile à contourner et nécessite souvent l’exécution d’un navigateur sans tête ou la réplication de la logique du capteur. Akamai emploie Analyse comportementale Utilisation de scripts client-side et de modèles AI Akamai emploie Analyse comportementale Analyse comportementale Utilisation de scripts client-side et de modèles AI Mais comment pouvons-nous détecter qu'un site Web utilise Akamai Bot Manager? En dehors de Si vous remarquez le et les cookies utilisés sur un site Web, c’est le signe le plus clair qu’il utilise Akamai pour se protéger. l’extension de navigateur Wappalyzer habituelle - abc par bmsc l’extension de navigateur Wappalyzer habituelle - abc - abc par bmsc par bmsc Compte tenu de ces défenses, de nombreux utilisateurs de Scrapy se sont tournés vers Le gestionnaire de téléchargement pour contourner Akamai. Ce plugin intègre bibliothèque pour faire semblant de signatures réseau de navigateurs réels. scrapy-impersonate curl_cffi En pratique, Scrapy Impersonate fait que les demandes de votre scrapy spider « ressemblent » à un Chrome ou à Firefox : il offre des empreintes digitales TLS (JA3) qui correspondent à ces navigateurs, utilise HTTP/2, et ajuste même les en-têtes de cadre HTTP/2 de bas niveau pour imiter les schémas du navigateur. Caractéristiques de Scrapy Impersonate Bien que Scrapy Impersonate soit un outil puissant, il comporte certaines limitations: 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 solution que nous verrons aujourd’hui aide à résoudre les deux premiers points : nous allons chaîner ensemble , pour une empreinte digitale TLS optimale et un proxy résidentiel rotatif pour faire tourner nos IP et avoir des scores de réputation plus élevés. JA3Proxy 3 Proxy Comprendre les empreintes digitales TLS et JA3 Avant de plonger dans la solution, il est important de comprendre exactement ce que nous faisons de faux. Chaque client HTTPS présente un Cette empreinte digitale est une combinaison de la version du protocole TLS et d’une série d’options que le client dit qu’il prend en charge – pensez-y comme le « dialecte » du client pour parler TLS. 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: Le concept de est un moyen standardisé d'enregistrer ces détails TLS Client Hello. JA3, nommé d'après les initiales de ses créateurs, compose une chaîne d'empreintes digitales en concatenant les champs ci-dessus dans un ordre spécifique: JA3 fingerprinting JA3_string = TLSVersion,CipherSuiteIDs,ExtensionIDs,EllipticCurveIDs,EllipticCurveFormatIDs Chaque liste (numéros, extensions, etc.) est jointe par Les sections de Par exemple, un navigateur Chrome pourrait produire une chaîne JA3 comme : - , 771,4866-4867-4865-....-47-255,0-11-10-16-23-...-21,29-23-30-25-24,0-1-2 Cela représente TLS 1.2 (771 est 0x0303), un ensemble spécifique de suites de chiffrement, d'extensions, de courbes prises en charge et de formats de courbes (les numéros sont des ID standardisés). Les outils de sécurité enregistrent ou comparent souvent le hash MD5 (car il est plus facile à gérer qu’une longue chaîne de chiffres). MD5 hashed Pourquoi est-ce important pour la détection de bot? parce que Chrome version X sur Windows Présentez la même empreinte digitale JA3 jusqu'à l'ordre de la liste. Firefox aura son propre JA3 distinct. browser TLS stacks are fairly uniform toujours La bibliothèque de requêtes de Python (qui utilise OpenSSL sous le capot) a un JA3 qui est totalement différent de tout navigateur courant, il est donc facilement détectable. Les services anti-bot comme Akamai maintiennent des bases de données de hashes JA3 : si votre JA3 n’est pas sur la liste des « bons bien connus » (browsers courants) ou s’il est sur une liste d’automatisation connue, vous serez flagellé. En résumé, pour passer les contrôles d'empreintes digitales TLS d'Akamai, . we need our client’s JA3 to match a popular browser Cela signifie généralement imiter la dernière empreinte digitale de Chrome ou Firefox (car ce sont les utilisateurs les plus courants sur le web). La simple modification de la chaîne User-Agent ne suffit pas – nous devons modifier la prise de main TLS de bas niveau. (qui exploite elle-même une construction spéciale de bibliothèques curl et TLS pour imiter les navigateurs).Mais en dehors de Scrapy, nous avons besoin d’une autre façon d’atteindre le même effet. curl_cffi TLS Impersonation Proxy + chaîne de proxy résidentielle Notre solution est de pour rendre notre scraper pratiquement indistinguible d'un utilisateur de navigateur réel: 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. Guide de configuration pour JA3Proxy Nous allons configurer JA3Proxy et le chaîner avec un proxy résidentiel. Télécharger JA3Proxy JA3Proxy est écrit en Go. Vous avez deux options faciles: compiler à partir de la source ou utiliser un conteneur Docker. Pour construire à partir de la source, vous aurez besoin de Go installé. git clone https://github.com/LyleMi/ja3proxy.git cd ja3proxy make Cela devrait produire une dans le dossier. (Alternativement, vous pouvez exécuter manuellement puisque le projet est basé sur Go.) ja3proxy go build Si vous préférez Docker, il y a une image pré-construite sur le Registre des conteneurs de GitHub. docker pull ghcr.io/lylemi/ja3proxy:latest la dernière image. Vous pouvez ensuite l'exécuter avec (Nous allons montrer la commande exécution dans un instant.) Docker est pratique car il emballe tout sans avoir besoin d'un environnement Go local. docker run Dans mon expérience personnelle, l'installation était un peu un cauchemar. Je n'ai pas pu faire fonctionner l'image Docker, car j'ai constamment reçu des erreurs lors de la tentative de connexion à elle, car aucun navigateur n'a été reconnu. Puis j'ai décidé de construire manuellement sur mon Mac, et j'ai rencontré les mêmes erreurs. Cependant, après des heures de débogage, j'ai constaté que je devais mettre à jour certaines dépendances, en particulier uTLS; il y avait des conflits dans les versions des bibliothèques, et tout cela provoquait des problèmes. De toute façon, j'ai réussi à l'installer, donc si vous obtenez quelques erreurs au début, ne renoncez pas. Obtenir ou créer des certificats TLS JA3Proxy peut agir comme un proxy HTTPS, ce qui signifie qu’il intercepte TLS et présente son propre certificat à votre client. Par défaut, il cherche à et Si vous ne fournissez pas un certificat, vous pouvez l'exécuter en mode simple (comme un proxy HTTP normal) et simplement ignorer la vérification du certificat dans votre client (non recommandé pour la production, mais acceptable pour les tests). cert.pem key.pem La meilleure pratique est de générer un certificat racine et une clé auto-signées, et de configurer votre scraper pour faire confiance à ce certificat, de sorte que vous puissiez intercepter le trafic sans alertes de sécurité. openssl req -x509 -newkey rsa:2048 -sha256 -days 365 -nodes -keyout key.pem -out cert.pem -subj "/CN=JA3Proxy" Cela crée une / (Pour une utilisation de production, vous pourriez même utiliser une CA interne légitime si vous avez ce paramètre, mais pour la plupart des fins de scraping, une auto-signée est OK tant que votre client sait lui faire confiance.) cert.pem key.pem Lancez JA3Proxy avec une empreinte digitale Chrome Maintenant nous exécutons le proxy. Si vous utilisez le binaire, exécutez une commande comme: ./ja3proxy -port 8080 -client Chrome -version 131 -cert cert.pem -key key.pem -upstream YOURPROXYIP:PORT Détruisons cette commande : - port 8080 lui dit d'écouter sur le port 8080 (vous pouvez choisir un autre port si nécessaire). -client Chrome -version 131 sélectionne le profil d'empreinte digitale. Dans cet exemple, il utilise le profil intégré pour Chrome 131. Vous le remplaceriez par le profil correspondant au navigateur/version souhaitée - par exemple, si Chrome 130 est pris en charge dans la dernière version, vous pourriez utiliser -client Chrome -version 130. (Vous pouvez trouver la liste des empreintes digitales disponibles en vérifiant la documentation de JA3Proxy ou la bibliothèque uTLS qu'il utilise. -cert et -key spécifient les fichiers de certificat TLS que nous avons générés à l'étape 2. -upstream 123.45.67.89:1080 est l'adresse du proxy upstream. Ceci devrait être remplacé par votre endpoint proxy résidentiel. Important: JA3Proxy s'attend à ce qu'il s'agisse d'une adresse proxy SOCKS5__github.com__. Si votre fournisseur vous a donné quelque chose comme proxy.provider.com:8000 avec un nom d'utilisateur / mot de passe, vous pouvez essayer le format username:password@proxy.provider.com:8000. (JA3Proxy analysera la chaîne et devrait gérer l'authentification pour SOCKS5 si elle est donnée dans le formulaire user:pass@host:port. Si cela ne fonctionne pas, vous pouvez configurer votre proxy résidentiel pour être IP-autorisé ou utiliser Si vous utilisez Docker, l’équivalent serait : 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 Nous montons le cert et la clé dans le conteneur et exposons le port 8080. Ajustez la commande pour inclure vos identifiants proxy / hôte réels. (ou quel que soit l'hôte / port que vous spécifiez). localhost:8080 Un cas d'utilisation du monde réel - MrPorter.com MrPorter.com est un site de commerce électronique de mode qui, comme beaucoup d'autres dans l'industrie, se protège avec Akamai Bot Manager. En utilisant une simple requête Python, comme spécifié dans le fichier Dans le répertoire, j'ai rencontré une erreur de délai, comme prévu. 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() Résultat : Error fetching the page: HTTPSConnectionPool(host='www.mrporter.com', port=443): Read timed out. (read timeout=10) En utilisant , à Cependant, je n'ai pas pu trouver une base de données indiquant que les demandes Python utilisent couramment cette empreinte digitale. L’outil d’empreintes digitales Scrapfly TLS Nous pouvons voir les résultats L’outil d’empreintes digitales Scrapfly TLS Nous pouvons voir les résultats L'ordre des suites Cipher est différent, et par conséquent, l'empreinte digitale sera également différente. Maintenant, allons démarrer le docker JA3Proxy, sans joindre un proxy résidentiel, et voyons ce qui se passe. 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 Nous avons reçu le message HTTP Proxy Server listen at :8080, with tls fingerprint 131 Chrome Ainsi, nous pouvons utiliser localhost:8080 comme proxy dans notre script de requête Python. Une autre cause d'erreur dans mon configuration était que j'ai essayé d'utiliser Python Requests pour se connecter à JA3Proxy. Après avoir creusé pendant un certain temps, j'ai constaté que le problème était que la bibliothèque de requêtes ne supporte pas HTTP/2, alors que JA3Proxy le fait lors de l'utilisation d'une version moderne de Chrome. Pour mes tests, je dois utiliser HTTPX, comme indiqué dans le fichier . request_with_proxies.py Dans ce cas, si j'appelle à nouveau l'API Scrapfly TLS, la première partie de la chaîne JA3 (l'ordre Cipher) . est identique à celle de mon navigateur est identique à celle de mon navigateur À titre de test final, si nous utilisons ce script pour demander la page MrPorter, nous pouvons la télécharger sans aucun problème. Créer un proxy résidentiel Maintenant que nous avons résolu la falsification de l'empreinte digitale TLS, nous avons juste besoin de tourner l'IP que le site Web cible verra. JA3Proxy a une option qui nous aide dans cela, appelée upstream. En lançant la commande JA3Proxy comme suit, ./ja3proxy -addr 127.0.0.1 -client Chrome -version 131 -cert cert.pem -key key.pem -upstream socks5h://USER:PASS@PROVIDER:PORT -debug Nous sommes en mesure de tuneler nos demandes en utilisant notre fournisseur de proxy préféré. Veuillez noter que vous devez vous connecter via SOCKS5, alors assurez-vous que votre fournisseur prend en charge cette fonctionnalité. En vérifiant l'IP après cela, je peux voir que mes IP de rotation résidentielle sont en place, et je peux continuer à télécharger les pages MRPorter sans problème. 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 Les conclusions Dans ce post, nous avons vu comment contourner Akamai Bot Manager sur le site Web de MrPorter.Le niveau de protection du site Web est moyen, donc il n'y a pas de défi d'empreinte digitale complexe du navigateur à contourner, mais, selon mon expérience, c'est le cas d'utilisation le plus courant lorsque nous rencontrons Akamai sur notre chemin. Je choisis de suivre l'approche JA3Proxy pour l'écarter, de sorte que cette solution puisse être utilisée dans divers cadres. Si vous utilisez Scrapy, vous pouvez toujours compter sur Scrapy Impersonate, malgré ses limites, ou vous pouvez essayer de définir les chiffres dans l'ordre approprié manuellement. L'article fait partie de la série "The Lab" de Pierluigi Vinciguerra. Consultez sa page Substack pour plus de connaissances sur le web scraping. L'article fait partie de la série "The Lab" de Pierluigi Vinciguerra. Consultez sa page Substack pour plus de connaissances sur le web scraping. « Le laboratoire »