O fingerprinting TLS identifica o software que abre uma conexão HTTPS observando como ele a abre — quais cifras ele oferece e em que ordem, quais extensões e curvas elípticas ele lista — antes que qualquer conteúdo da requisição seja enviado. Cada biblioteca TLS e cada versão de navegador diz “olá” a um servidor de forma ligeiramente diferente, e essa saudação é visível para o servidor em texto puro, mesmo que tudo depois dela seja criptografado. JA3 e seu sucessor JA4 transformam a saudação em um hash curto. Sistemas anti-bot comparam esse hash com o que o navegador alegado deveria ter produzido. É por isso que um script Python que se anuncia como Chrome, conectando-se através de um IP residencial impecável, ainda é pego: o IP dizia “usuário doméstico em Berlim”; o handshake TLS dizia “OpenSSL em um script.”
De onde vem o fingerprint: o ClientHello
Uma conexão HTTPS começa com um handshake TLS. A primeira mensagem, enviada pelo cliente, é o ClientHello. Ela não é criptografada — e não pode ser, porque a criptografia ainda não foi negociada — e contém, entre outras coisas:
- a versão do TLS que o cliente suporta;
- a lista de suites de cifras que ele está disposto a usar, em sua ordem de preferência;
- uma lista de extensões — SNI (o nome do host), ALPN (quais protocolos de aplicação, ex.:
h2,http/1.1), grupos suportados (curvas elípticas), algoritmos de assinatura, key share, session ticket, e assim por diante — novamente em uma ordem específica; - as curvas elípticas e formatos de ponto que ele suporta.
Nenhum desses valores é secreto e nenhum é escolhido por site; eles estão embutidos na biblioteca TLS e na aplicação que a usa. Chrome 128 envia um ClientHello específico; Firefox envia outro; o módulo ssl do Python (OpenSSL) envia um terceiro; o crypto/tls do Go um quarto; curl um quinto. O servidor vê o ClientHello de toda conexão de qualquer forma — ele precisa, para respondê-lo. Gravá-lo e fazer hash não custa nada.
JA3 e JA4: transformando o handshake em uma assinatura
JA3
Introduzido por pesquisadores da Salesforce em 2017, o JA3 concatena cinco campos do ClientHello — versão TLS, suites de cifras, extensões, curvas elípticas, formatos de ponto de curva elíptica — como listas decimais separadas por vírgula, e então aplica hash MD5 na string. O resultado é um fingerprint de 32 caracteres, como cd08e31494f9531f560d64c695473da9. Qualquer um pode calculá-lo a partir de uma captura de pacotes, e listas que mapeiam hashes JA3 para clientes conhecidos (“este hash = Chrome 120 no Windows,” “este hash = python-requests”) são amplamente compartilhadas.
JA3 tem uma fraqueza que se tornou uma vantagem para evasão: porque ele aplica hash na lista de extensões em ordem, e o Chrome (desde a versão 110) randomiza a ordem das extensões em cada conexão, uma única instalação do Chrome produz muitos hashes JA3 diferentes. Isso foi feito deliberadamente para desencorajar servidores de se fixarem em um único fingerprint — e tornou o JA3 muito menos útil para identificar navegadores.
JA4
JA4, lançado pela FoxIO em 2023, foi projetado para sobreviver a isso. Ele ordena as listas de cifras e extensões antes de aplicar hash (então a embaralhada do Chrome não importa mais), mantém alguns campos legíveis, e incorpora mais sinais: se a conexão é via TCP ou QUIC, o tipo de SNI, o valor ALPN, a versão TLS, e contagens de cifras e extensões. Um fingerprint JA4 parece t13d1516h2_8daaf6152771_e5627efa2ab1: o primeiro bloco diz “TLS 1.3 sobre TCP, 15 cifras, 16 extensões, ALPN h2,” os outros dois são hashes truncados da lista ordenada de cifras e da lista ordenada de extensões mais algoritmos de assinatura. JA4 é na verdade uma família (JA4 para TLS, JA4H para cabeçalhos HTTP, JA4S para o lado do servidor, JA4X para certificados, e outros); quando fornecedores de anti-bot dizem “fingerprint TLS” hoje, geralmente querem dizer JA4 ou um equivalente proprietário construído da mesma forma.
Por que o proxy não pode ajudar
Um proxy retransmite o handshake TLS; ele não o reescreve. Com um proxy HTTP, o cliente envia CONNECT host:443, o proxy abre um túnel TCP, e o ClientHello próprio do cliente viaja pelo túnel até o destino intocado. Com SOCKS5, a mesma coisa acontece uma camada abaixo. O servidor de destino, portanto, vê dois fatos independentes:
- o IP de origem — o do proxy, residencial e impecável;
- o ClientHello — o do cliente, dizendo exatamente qual biblioteca o construiu.
A lógica anti-bot então faz uma pergunta simples: o fingerprint TLS corresponde ao User-Agent? O cabeçalho User-Agent alega “Chrome 128 no Windows.” O JA4 diz “OpenSSL 3.x via Python.” Chrome real nunca produz esse JA4. A requisição é sinalizada — não porque o IP é ruim, mas porque a história é internamente inconsistente. Esta é a razão mais comum pela qual um proxy residencial “limpo” ainda recebe CAPTCHAs em sites protegidos, e é por isso que dizemos que um proxy responde de onde, não quem; veja o que um proxy faz e não esconde.
O proxy pode importar em um aspecto: alguns provedores terminam o TLS eles mesmos (um proxy “man-in-the-middle” que descriptografa e re-criptografa, exigindo que você instale seu certificado). Nesse caso, o destino vê o ClientHello do proxy, não o seu — o que geralmente é pior, já que é uma biblioteca do lado do servidor, não um navegador. Proxies comuns não fazem isso.
Como cada tipo de cliente parece
| Cliente | O que seu fingerprint TLS diz | Consistente com um User-Agent de navegador? |
|---|---|---|
| Chrome / Firefox / Safari reais | Esse navegador e versão, naquele SO | Sim — ele é o navegador |
Python requests, httpx, aiohttp | OpenSSL conforme configurado pelo módulo ssl do Python | Não — reconhecível como script independentemente dos cabeçalhos |
Node.js fetch / axios | Build OpenSSL/BoringSSL do Node | Não |
Go net/http | Pilha TLS própria do Go; distinta | Não |
| curl (build padrão) | OpenSSL/LibreSSL conforme compilado | Não |
| Chrome headless via Puppeteer/Playwright | Chrome real — TLS correto | Sim para TLS; outros sinais (flags de automação, plugins ausentes) podem vazar |
| Clientes “imitadores” (curl-impersonate, curl_cffi, tls-client) | ClientHello de um navegador escolhido, reproduzido byte a byte | Sim, se você também combinar os cabeçalhos com o mesmo navegador |
Como ter um fingerprint consistente
Existem três rotas honestas, em ordem crescente de custo.
- Use um navegador real. Automatize Chrome ou Firefox com Playwright ou Puppeteer; o TLS então é genuinamente do navegador. Mais lento e pesado que HTTP puro, mas para sites protegidos é o padrão. Associe cada contexto de navegador ao seu próprio proxy — veja proxies em Playwright, Puppeteer e Selenium.
- Use um cliente HTTP imitador. Bibliotecas como curl_cffi (Python, construído sobre curl-impersonate) e tls-client reproduzem o ClientHello e as configurações HTTP/2 de navegadores específicos, então você obtém velocidade de scraper com o fingerprint de um navegador. Você deve então manter todos os outros cabeçalhos consistentes com a mesma versão do navegador — User-Agent,
Accept-Language, client hintssec-ch-ua— ou você troca uma contradição por outra. Nosso guia de proxies em Python mostra a troca derequestsparacurl_cffi. - Pare de fingir. Se um alvo oferece uma API oficial, use-a com sua identidade real de cliente. O fingerprinting TLS só é um problema quando o fingerprint contradiz a alegação.
O que não funciona: definir um User-Agent de Chrome no requests. Isso muda um cabeçalho e deixa o handshake intocado — a incompatibilidade agora é mais nítida do que antes, porque um UA simples de python-requests com um fingerprint OpenSSL é pelo menos autoconsistente.
O panorama geral: fingerprints se acumulam
TLS é uma camada. Fornecedores modernos de anti-bot também fazem fingerprinting da conexão HTTP/2 (valores do frame SETTINGS, tamanhos de janela, ordem de cabeçalhos e pseudo-cabeçalhos — às vezes chamado de fingerprinting Akamai), da pilha TCP/IP (tamanho de janela, TTL, opções; p0f clássico), e claro do navegador em si através de JavaScript, que um cliente HTTP não pode executar. Cada camada deve contar a mesma história que as outras e que o IP. Um IP residencial com fingerprint TLS de navegador e configurações HTTP/2 de navegador, mas sem execução de JavaScript, ainda é uma anomalia em um site que espera que o desafio JS seja executado. É por isso que a resposta honesta para “qual proxy evita detecção?” é “nenhum sozinho” — e por que nossos rankings pesam o que o provedor faz além do IP; veja a comparação de proxies elite.
Como ver seu próprio fingerprint
Várias páginas públicas ecoam o JA3/JA4 que calculam para sua conexão, junto com qual navegador acham que é. Carregue uma de um navegador real, depois busque-a com seu script através do mesmo proxy, e compare. Se os dois diferirem, você encontrou a razão pela qual seu script é tratado de forma diferente do seu navegador — e nenhuma troca de proxy vai corrigir isso. Adicione isso às verificações em Como testar um proxy sempre que o alvo for conhecido por executar anti-bot empresarial.
Perguntas frequentes
O que é JA3?
Um hash MD5 de cinco campos do ClientHello TLS (versão, cifras, extensões, curvas, formatos de ponto) usado para identificar o software do cliente. Funciona bem para scripts e bibliotecas; tornou-se não confiável para Chrome uma vez que o Chrome começou a randomizar a ordem das extensões.
O que é JA4?
O sucessor do JA3: ele ordena as listas antes de aplicar hash para que a embaralhada de extensões não o altere, mantém parte do fingerprint legível, e inclui transporte (TCP/QUIC), ALPN e contagens. É a base da maioria das detecções atuais de fingerprint TLS.
Um proxy residencial muda meu fingerprint TLS?
Não. O proxy tunela seu handshake inalterado; o destino vê o IP do proxy e seu ClientHello. Apenas o software do cliente determina o fingerprint.
Posso falsificar o fingerprint TLS de um navegador em Python?
Sim, com clientes imitadores como curl_cffi, que reproduzem o ClientHello e o comportamento HTTP/2 de um navegador escolhido. Você deve manter os cabeçalhos consistentes com o mesmo navegador. requests/httpx puros não conseguem fazer isso.
Fingerprinting TLS é o mesmo que fingerprinting de navegador?
Não. O fingerprinting TLS lê o handshake da conexão criptografada e identifica o software do cliente; o fingerprinting de navegador executa JavaScript e identifica o dispositivo (canvas, fontes, GPU). Sistemas anti-bot usam ambos, além da reputação do IP, e verificam se concordam.
Por que o mesmo script é bloqueado em um site e não em outro?
Porque verificações de fingerprint TLS são uma característica de produtos anti-bot empresariais, não da web em geral. Sites sem essa proteção nunca olham para o handshake; sites com ela o comparam ao User-Agent em cada requisição.