O Akamai Bot Manager é uma das soluções anti-bot mais comuns no mercado. É usado por muitos sites de alto perfil, desde sites de comércio eletrônico até sites de viagens, e, dependendo de sua configuração, pode ser difícil de contornar. Com base na minha experiência, o padrão típico que encontro quando um site ativa a proteção do Akamai Bot Manager é que o raspador (geralmente um Scrapy na minha pilha) se pendura e termina a partir da primeira solicitação. Mas o que é o Akamai Bot Manager, e como posso ver se um site está usando? Avaliação geral do Akamai Bot Manager A detecção de bot da Akamai, como qualquer outro software de proteção anti-bot moderno, funciona em várias camadas. é uma das primeiras: a Akamai analisa os detalhes do toque de mão e da conexão TLS (JA3 TLS fingerprint, suites de criptografia, versão TLS, etc.) para ver se eles correspondem a um navegador real ou a uma ferramenta de automação conhecida. cada navegador (Chrome, Firefox, Safari, etc.) tem uma impressão digital TLS característica, e se o seu cliente TLS Client Hello não corresponde a qualquer navegador comum, a Akamai sabe que algo é peculiar. Network fingerprinting Também inspecciona – Os navegadores reais quase sempre usam HTTP/2+ nos dias de hoje, e eles enviam cabeçalhos HTTP em uma ordem e formato específicos. Se um cliente ainda está usando HTTP/1.1 ou tem cabeçalhos em uma ordem não-browser, é uma bandeira vermelha. O espelho de um browser real é crucial. HTTP/2 usage and header order and their order Outra camada é A Akamai verifica se o IP do cliente é de uma rede residencial, de uma rede móvel ou de um datacenter. IPs residenciais e móveis (o tipo de usuário real) têm uma pontuação alta em confiança, enquanto as faixas IP do datacenter conhecidas são automaticamente suspeitas. - sempre parecerem provenientes de diferentes locais de usuários reais, não de uma fazenda de servidores de nuvem. IP reputation and analysis residential proxies Por fim, Um sensor JavaScript na página da web recolhe uma infinidade de pontos de dados sobre o ambiente e as interações do cliente (como o tempo, os movimentos do mouse, ou sua ausência, propriedades incomuns no objeto do navegador, etc.).Os modelos de IA da Akamai cruncam esses dados para atribuir uma pontuação de probabilidade de bot a cada sessão.Este aspecto é o mais difícil de contornar e muitas vezes requer a execução de um navegador sem cabeça ou a replicação da lógica do sensor. (Isso está além do nosso escopo aqui – nosso foco será passar os controles de nível de rede, que é o caso mais comum para sites de comércio eletrônico, na minha experiência.) Emprego do Akamai Análise comportamental Usando scripts do lado do cliente e modelos de AI Emprego do Akamai Análise comportamental Análise comportamental Usando scripts do lado do cliente e modelos de AI Mas como podemos detectar que um site está usando o Akamai Bot Manager? Além de Se você notar o e Cookies usados em um site, este é o sinal mais claro de que ele está usando o Akamai para se proteger. A extensão do navegador Wappalyzer abc ak_bmsc A extensão do navegador Wappalyzer abc abc O que é bmsc O que é bmsc Dadas essas defesas, muitos usuários do Scrapy recorreram ao Download Manager para contornar o Akamai. Este plugin integra o biblioteca para fingir assinaturas de rede de navegadores reais. scrapy-impersonate curl_cffi Na prática, o Scrapy Impersonate faz com que as solicitações do seu Scrapy spider “olhem” como um Chrome ou Firefox: oferece impressões digitais TLS (JA3) que correspondem a esses navegadores, usa HTTP/2, e até ajusta cabeçalhos de quadros HTTP/2 de baixo nível para imitar os padrões do navegador. Características do Scrapy Impersonate Enquanto o Scrapy Impersonate é uma ferramenta poderosa, vem com certas limitações: 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 A solução que veremos hoje ajuda a resolver os dois primeiros pontos: vamos nos conectar. , para uma impressão digital TLS ideal e um proxy residencial rotativo para rodar nossos IPs e ter pontuações de reputação mais altas. 3o Proxy 3o Proxy Compreensão de impressões digitais TLS e JA3 Antes de mergulhar na solução, é importante entender exatamente o que estamos falsificando. Esta impressão digital é uma combinação da versão do protocolo TLS e um monte de opções que o cliente diz que suporta – pense nisso como o “dialeto” do cliente de falar TLS. Os componentes-chave incluem: 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: O conceito de é uma maneira padronizada de gravar esses detalhes do cliente TLS Hello. JA3, nomeado pelas iniciais de seus criadores, compõe uma cadeia de impressões digitais concatenando os campos acima em uma ordem específica: JA3 fingerprinting JA3_string = TLSVersion,CipherSuiteIDs,ExtensionIDs,EllipticCurveIDs,EllipticCurveFormatIDs Cada lista (cifras, extensões, etc.) é anexada por As seções de Por exemplo, um navegador do Chrome pode produzir uma cadeia JA3 como: - , 771,4866-4867-4865-....-47-255,0-11-10-16-23-...-21,29-23-30-25-24,0-1-2 Isto representa TLS 1.2 (771 é 0x0303), um conjunto específico de suites de cifragem, extensões, curvas suportadas e formatos de curva (os números são IDs padronizados). As ferramentas de segurança muitas vezes logam ou comparam o hash MD5 (porque é mais fácil de lidar do que uma longa cadeia de números). MD5 hashed Por que isso importa para a detecção de bot? Chrome versão X no Windows apresentar a mesma impressão JA3 para baixo na ordem de lista. Firefox terá seu próprio JA3 distinto. browser TLS stacks are fairly uniform Sempre A biblioteca de solicitações do Python (que usa OpenSSL sob o capô) tem um JA3 que é completamente diferente de qualquer navegador mainstream, por isso é facilmente detectável. Serviços anti-bots como o Akamai mantêm bancos de dados de hashes JA3: se o seu JA3 não estiver na lista de “bons conhecidos” (browsers comuns) ou se estiver em uma lista de automação conhecida, você ficará marcado. Em resumo, para passar as verificações de impressão digital TLS da Akamai, . we need our client’s JA3 to match a popular browser Isso geralmente significa imitar a última impressão digital do Chrome ou do Firefox (porque eles são os usuários mais comuns na web). Simplesmente alterar a cadeia User-Agent não é suficiente – devemos modificar o toque de mão TLS de baixo nível. (que, por si só, aproveita uma construção especial de bibliotecas curl e TLS para imitar navegadores). curl_cffi TLS Impersonation Proxy + Cadeia Proxy Residencial Nossa solução é para Para tornar o nosso scraper virtualmente indistinguível de um usuário de navegador real: 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. Instalação do JA3Proxy Vamos configurar o JA3Proxy e conectá-lo com um proxy residencial. Instalação do JA3Proxy O JA3Proxy é escrito em Go. Você tem duas opções fáceis: compilar a partir da fonte ou usar um contêiner do Docker. Para construir a partir da fonte, você precisará do Go instalado. Execute: git clone https://github.com/LyleMi/ja3proxy.git cd ja3proxy make Isso deve produzir a pode ser executado na pasta. (Alternativamente, você pode executar manualmente, uma vez que o projeto é baseado em Go.) ja3proxy go build Se você preferir o Docker, há uma imagem pré-construída no GitHub Container Registry. docker pull ghcr.io/lylemi/ja3proxy:latest Obterá a imagem mais recente. Você pode executá-la com (Nós mostraremos o comando executar em um momento.) Docker é conveniente porque ele empacota tudo sem precisar de um ambiente Go local. docker run Na minha experiência pessoal, a instalação foi um pouco de um pesadelo. Eu não pude fazer a imagem do Docker funcionar, como eu constantemente recebi erros ao tentar se conectar a ele, uma vez que nenhum navegador foi reconhecido. Então eu decidi construir manualmente no meu Mac, e eu encontrei os mesmos erros. No entanto, depois de horas de depuração, eu descobri que eu precisava atualizar algumas dependências, especialmente uTLS; havia conflitos nas versões das bibliotecas, e tudo isso estava causando problemas. De qualquer forma, eu consegui instalá-lo, então se você obter alguns erros no início, não desista. Obter ou criar certificados TLS O JA3Proxy pode atuar como um proxy HTTPS, o que significa que ele intercepta TLS e apresenta seu próprio certificado ao seu cliente. Por padrão, ele procura e Se você não fornecer um, você pode executá-lo no modo de texto simples (como um proxy HTTP normal) e simplesmente ignorar a verificação de certificado em seu cliente (não recomendado para produção, mas aceitável para testes). cert.pem key.pem A melhor prática é gerar um certificado raiz e chave auto-assinados, e configurar seu raspador para confiar nesse certificado, para que você possa interceptar o tráfego sem avisos de segurança. openssl req -x509 -newkey rsa:2048 -sha256 -days 365 -nodes -keyout key.pem -out cert.pem -subj "/CN=JA3Proxy" Isso cria a / (Para uso de produção, você pode até usar um CA interno legítimo se você tiver essa configuração, mas para a maioria dos fins de rascunho, um auto-assinado é bom desde que seu cliente saiba confiar nele.) cert.pem key.pem Iniciar o JA3Proxy com uma impressão digital do Chrome Agora nós executamos o proxy. Se usar o binário, execute um comando como: ./ja3proxy -port 8080 -client Chrome -version 131 -cert cert.pem -key key.pem -upstream YOURPROXYIP:PORT Vamos quebrar esse comando: A porta 8080 diz-lhe para ouvir na porta 8080 (você pode escolher outra porta, se necessário). -client Chrome -versão 131 seleciona o perfil de impressão digital. Neste exemplo, ele usa o perfil integrado para o Chrome 131. Você substituiria estes com o perfil correspondente ao navegador/versão que você deseja – por exemplo, se o Chrome 130 é suportado na versão mais recente, você pode usar -client Chrome -versão 130. (Você pode encontrar a lista de impressões digitais disponíveis verificando a documentação do JA3Proxy ou a biblioteca uTLS que ele usa. -cert e -key especificar os arquivos de certificado TLS que geramos na etapa 2. -upstream 123.45.67.89:1080 é o endereço do proxy upstream. Isso deve ser substituído pelo seu endpoint de proxy residencial. Importante: JA3Proxy espera que isso seja um endereço de proxy SOCKS5__github.com__. Se o seu provedor lhe deu algo como proxy.provider.com:8000 com um nome de usuário / senha, você pode tentar o formato de nome de usuário:password@proxy.provider.com:8000. (JA3Proxy analisará a cadeia e deve lidar com a autenticação para SOCKS5 se dada no formulário user:pass@host:port. Se isso não funcionar, você pode configurar seu proxy residencial para ser IP-permitido ou usar um recurso de lista branca IP para evitar auth, ou executar um pro Se você usar o Docker, o equivalente seria: 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 Nós montamos o cert e a chave no contêiner e expomos a porta 8080. Ajuste o comando para incluir suas credenciais/host proxy reais. (ou qualquer host/port que você especifique). localhost:8080 Um caso de uso do mundo real - MrPorter.com MrPorter.com é um site de e-commerce de moda que, juntamente com muitos outros na indústria, se protege com o Akamai Bot Manager. Usando uma simples solicitação Python, como especificado no arquivo no repositório, encontrei um erro de timeout, como esperado. 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() O resultado: Error fetching the page: HTTPSConnectionPool(host='www.mrporter.com', port=443): Read timed out. (read timeout=10) Ao usar , em No entanto, eu não consegui encontrar um banco de dados que indique que as solicitações Python comumente usam essa impressão digital. certamente, é diferente da impressão digital que eu tenho usando o Brave Browser, com os mesmos cabeçalhos e agente de usuário. A ferramenta de impressão digital Scrapfly TLS Podemos ver os resultados A ferramenta de impressão digital Scrapfly TLS Podemos ver os resultados A ordem dos Cipher Suites é diferente e, portanto, a impressão digital também será diferente. Agora, vamos iniciar o docker JA3Proxy, sem anexar um proxy residencial, e ver o que acontece. 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 Recebemos a mensagem HTTP Proxy Server listen at :8080, with tls fingerprint 131 Chrome Assim, podemos usar localhost:8080 como um proxy em nosso script de solicitação Python. Outra causa de erros na minha instalação foi que tentei usar Python Requests para se conectar ao JA3Proxy.Depois de cavar por um tempo, descobri que o problema era que a biblioteca de solicitações não suporta HTTP/2, enquanto o JA3Proxy faz quando usa uma versão moderna do Chrome. Para os meus testes, preciso usar HTTPX, como mostrado no arquivo . request_with_proxies.py Neste caso, se eu chamar a API Scrapfly TLS novamente, a primeira parte da cadeia JA3 (a ordem Cipher) . is identical to that of my browser é idêntico ao do meu browser Como um teste final, se usarmos este script para solicitar a página MrPorter, podemos baixá-lo sem qualquer problema. Criando um Proxy Residencial Agora que resolvemos a falsificação da impressão digital do TLS, só precisamos girar o IP que o site de destino verá. O JA3Proxy tem uma opção que nos ajuda nisso, chamada upstream. Ao executar o comando JA3Proxy como segue, ./ja3proxy -addr 127.0.0.1 -client Chrome -version 131 -cert cert.pem -key key.pem -upstream socks5h://USER:PASS@PROVIDER:PORT -debug Nós podemos tunelar nossos pedidos usando nosso provedor de proxy preferido. Por favor, note que você precisa se conectar via SOCKS5, por isso certifique-se de que seu provedor suporta esse recurso. Ao verificar o IP depois de fazer isso, posso ver que meus IPs de rotação residencial estão no lugar, e posso continuar a baixar páginas do MRPorter sem problemas. 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 Conclusões Neste post, vimos como contornar o Akamai Bot Manager no site MrPorter.O nível de proteção do site é médio, então não há nenhum desafio complexo de impressão digital do navegador para contornar, mas, na minha experiência, é o caso de uso mais comum quando encontramos o Akamai em nosso caminho. Eu escolho seguir a abordagem JA3Proxy para contorná-la, para que esta solução possa ser usada em vários frameworks.Se você estiver usando Scrapy, você pode sempre confiar no Scrapy Impersonate, apesar de suas limitações, ou você pode tentar definir os cifradores na ordem correta manualmente. O artigo faz parte da série “The Lab” de Pierluigi Vinciguerra. Consulte sua página Substack para mais conhecimento sobre Web Scraping. O artigo faz parte da série “The Lab” de Pierluigi Vinciguerra. Consulte sua página Substack para mais conhecimento sobre Web Scraping. “O Laboratório”