← Voltar ao blog

Por que o parser é detectado pelo fingerprinting TLS mesmo com IP residencial limpo: como verificar e corrigir

IP residencial não evita bloqueio se a impressão digital TLS do parser for diferente da impressão digital de um navegador comum. Vamos analisar como verificar e configurar corretamente.

📅28 de setembro de 2026

Você adquiriu um caro IP residencial, configurou a rotação, inseriu um User-Agent realista — mas o parser ainda vai para o captcha ou recebe uma resposta vazia. O problema quase sempre não está no IP, mas na impressão TLS: a biblioteca que você está usando para enviar a solicitação HTTPS "soa" diferente de um navegador real. Sistemas anti-bot como Wildberries, Ozon, Cloudflare e Akamai percebem isso antes mesmo de verificarem seu endereço IP.

O que é impressão TLS e por que é mais importante que o IP

Quando um cliente estabelece uma conexão HTTPS, ele envia ao servidor um pacote ClientHello — parte do handshake TLS. Nele estão criptografados a lista de versões TLS suportadas, o conjunto de cifras (cipher suites), a ordem das extensões (extensions), curvas elípticas e algoritmos de compressão. Este conjunto de parâmetros é único para cada combinação "biblioteca + sistema operacional + versão do stack TLS".

Chrome, Firefox e Safari formam o ClientHello de maneira única, e esse conjunto praticamente não muda de solicitação para solicitação — ao contrário do IP ou User-Agent, que são fáceis de falsificar. Já as bibliotecas HTTP padrão — requests, urllib3, o HttpClient padrão em Java, o stack TLS embutido do Node.js — formam um ClientHello completamente diferente, porque utilizam OpenSSL ou outra biblioteca de forma diferente de um navegador.

É por isso que você pode conectar um IP residencial "limpo", inserir um User-Agent recente do Chrome real — e ainda assim ser bloqueado. O servidor vê um IP de um usuário de uma residência, vê o cabeçalho "Chrome 124", mas o handshake TLS diz: "isso é um script Python". A discrepância é um sinal claro para o anti-bot.

Como os sistemas anti-bot detectam o parser pelo JA3/JA4

Para transformar os parâmetros do ClientHello em um identificador compacto, é utilizado o algoritmo JA3 (e sua versão mais nova JA4). Ele pega a versão do TLS, a lista de cifras, extensões e curvas, concatena-os em uma string e faz um hash através do MD5. O resultado é um hash curto do tipo 769,47-53-5-10...,0-23-65281...,29-23-24,0, que identifica de forma única a "impressão" do cliente.

Provedores de anti-bot (Cloudflare, Akamai, PerimeterX, DataDome — e seus análogos que usam Wildberries e Ozon) mantêm bancos de dados de hashes JA3/JA4 conhecidos de bibliotecas HTTP populares: requests, aiohttp, Scrapy, Node fetch, Java HttpClient, Go net/http. Se o hash coincide com uma assinatura conhecida de "script", e não com a assinatura do Chrome/Firefox/Safari — a solicitação é marcada como suspeita antes mesmo da análise de comportamento.

Em seguida, o sistema verifica a correspondência da impressão TLS com o User-Agent declarado. Se nos cabeçalhos está escrito "Chrome 124 no Windows", mas a impressão TLS corresponde ao OpenSSL 1.1.1 da biblioteca padrão do Python — isso é chamado de incompatibilidade TLS/HTTP, um dos sinais mais confiáveis de detecção de automação. É assim que os parsers são detectados mesmo com um IP residencial ideal e cabeçalhos corretos.

Como verificar sua impressão TLS: ferramentas

Antes de corrigir o problema, é preciso ver o que o servidor vê. Existem vários serviços públicos que mostram seu hash JA3/JA4 e o conjunto completo de parâmetros do ClientHello:

  • tls.peet.ws — mostra JA3, JA4, lista de cifras e extensões em formato JSON, conveniente para verificação automática via script.
  • ja3er.com — banco de dados de hashes JA3 conhecidos vinculados a bibliotecas e navegadores específicos.
  • browserleaks.com/tls — comparação visual da sua impressão com impressões típicas de navegadores.
  • Wireshark localmente — se você quiser ver o pacote bruto ClientHello ao enviar uma solicitação do seu script.

O teste prático é simples: abra tls.peet.ws no Chrome comum e anote o hash JA4. Em seguida, envie uma solicitação GET para o mesmo endereço do seu parser (via requests, curl_cffi ou qualquer outra biblioteca) através do mesmo proxy e compare os hashes. Se eles diferirem — o servidor percebe a diferença entre "navegador" e "script" a cada solicitação, independentemente de quão limpo seja o IP.

Verificação em Python: requests, httpx, curl_cffi

Vamos analisar na prática por que as bibliotecas padrão do Python entregam o parser. Uma solicitação comum via requests:

import requests

resp = requests.get("https://tls.peet.ws/api/all", proxies={
    "https": "http://user:pass@proxy_host:port"
})
print(resp.json()["tls"]["ja4"])
# O resultado será diferente do JA4 do Chrome real,
# pois requests usa o módulo ssl padrão do Python

O problema é que requests e httpx usam o OpenSSL do sistema através do módulo ssl, e a ordem e o conjunto de extensões TLS estão rigidamente fixados e não coincidem com Chrome/Firefox. A solução é a biblioteca curl_cffi, que usa o curl patchado com perfis TLS reais de navegadores:

from curl_cffi import requests as cffi_requests

resp = cffi_requests.get(
    "https://tls.peet.ws/api/all",
    impersonate="chrome124",
    proxies={"https": "http://user:pass@proxy_host:port"}
)
print(resp.json()["tls"]["ja4"])
# O hash será idêntico ao do Chrome 124 real no desktop

O parâmetro impersonate faz com que o curl_cffi reproduza não apenas o ClientHello, mas também a ordem dos cabeçalhos HTTP/2 (frame order), que também faz parte da impressão. Abordagem semelhante é utilizada pelas bibliotecas tls-client para Go e undetected-chromedriver para aqueles que fazem parsing através de um navegador real, e não através de um cliente HTTP.

Se o parsing é feito através de um navegador headless (Playwright, Puppeteer, Selenium), a impressão TLS é gerada pelo motor Chromium/Firefox e, por padrão, coincide com o navegador real. Mas aqui surge outro problema — assinaturas de automação em nível de JS (flags do webdriver, canvas fingerprint), portanto, para cenários headless, patches adicionais como playwright-stealth são necessários.

TLS + HTTP/2 + cabeçalhos: por que a combinação é importante

A impressão TLS é apenas uma camada de detecção. Sistemas anti-bot comparam vários níveis simultaneamente:

  • TLS ClientHello (JA3/JA4) — conjunto de cifras e extensões.
  • Impressão HTTP/2 — ordem dos pseudo-cabeçalhos (:method, :path, :authority), configurações do frame SETTINGS, tamanho da janela.
  • Cabeçalhos HTTP — ordem e conjunto de cabeçalhos comuns (Accept-Language, Sec-Ch-Ua, Sec-Fetch-*).
  • User-Agent — deve corresponder à versão do perfil TLS: se o UA diz "Chrome 124", mas o TLS corresponde ao Chrome 110, isso também é suspeito.

Um erro comum é atualizar o User-Agent para a versão mais recente do Chrome, esquecendo de atualizar o perfil TLS no curl_cffi ou em outra biblioteca. Essa discrepância de versões é percebida pelo anti-bot tão claramente quanto a total ausência de camuflagem. Verifique se a versão impersonate e a versão no User-Agent coincidem, e atualize ambos os parâmetros em sincronia quando novas versões do navegador forem lançadas.

Outro ponto é a ordem dos cabeçalhos. O navegador envia os cabeçalhos em uma ordem estritamente definida, enquanto muitas bibliotecas HTTP os ordenam alfabeticamente ou pela ordem em que foram adicionados ao código. Mesmo que o conjunto de cabeçalhos seja idêntico ao do navegador, uma ordem incorreta é um sinal adicional para sistemas anti-bot avançados como o DataDome.

O papel dos proxies: por que um IP limpo não salva

O IP residencial resolve uma tarefa específica — reduz a suspeita em relação à geografia, ASN e reputação do endereço. IPs de data centers frequentemente estão em listas negras, pois deles flui massivamente tráfego automatizado, enquanto os residenciais pertencem a provedores reais e usuários comuns. Para fazer parsing de Wildberries, Ozon ou Avito, isso é crítico: sem um IP limpo, a solicitação é bloqueada apenas por esse critério, mesmo sem verificar o TLS.

Mas IP e impressão TLS são duas camadas de proteção independentes, e resolvem problemas diferentes. O IP diz ao servidor "de onde" a solicitação veio, a impressão TLS diz "com o que" foi enviada. Portanto, a combinação de um IP limpo e um perfil TLS correto é o mínimo necessário para um parsing estável. Para tarefas com alta frequência de solicitações e um anti-bot agressivo, é melhor usar proxies residenciais, pois eles oferecem uma baixa porcentagem de bloqueios por reputação de IP, mas devem ser combinados com uma biblioteca que reproduza corretamente o perfil TLS de um navegador real.

Para monitoramento de preços em marketplaces, onde a velocidade e o volume de solicitações são importantes, frequentemente são utilizados proxies de data centers em combinação com camuflagem TLS via curl_cffi — isso é mais barato que residenciais e bastante eficaz, se o sistema anti-bot do site não for muito agressivo. E para tarefas onde o site verifica ativamente redes móveis (por exemplo, parsing de versões móveis de aplicativos via API), usam-se proxies móveis — eles oferecem um nível adicional de confiança devido à reputação das redes operadoras.

Checklist de configuração do parser sem detecção

Reúna a verificação em um único processo antes de lançar o parser em produção:

  1. Meça o hash JA4 do seu script através do tls.peet.ws e compare com um navegador real da mesma versão.
  2. Use uma biblioteca com suporte a impersonação TLS: curl_cffi (Python), tls-client (Go), CycleTLS (Node.js).
  3. Sincronize a versão do perfil TLS (impersonate) com a versão no User-Agent.
  4. Verifique a ordem dos cabeçalhos HTTP — ela deve coincidir com a do navegador real, e não ser alfabética.
  5. Conecte um IP residencial ou móvel limpo de acordo com a geolocalização da sua tarefa.
  6. Configure a rotação de IP separadamente do perfil TLS — não os vincule rigidamente.
  7. Atualize regularmente o perfil TLS ao lançar novas versões do Chrome — assinaturas antigas entram nas bases de dados de anti-bots mais rápido do que parece.
  8. Para cenários com verificações em JS (Cloudflare Challenge), use um navegador headless com patches stealth em vez de um cliente HTTP limpo.

Comparação de bibliotecas e ferramentas

Ferramenta Impressão TLS do navegador Velocidade Quando usar
requests / httpx Não, entrega script Alta Sites sem detecção de TLS, APIs internas
curl_cffi Sim, cópia exata Alta Marketplaces, anti-bot Cloudflare/Akamai
tls-client (Go) Sim Muito alta Alta carga, parsing em massa
Playwright / Puppeteer Sim, motor real Baixa JS-render, Cloudflare Challenge, SPAs complexas
Scrapy (padrão) Não Alta Sites sem proteção anti-bot rigorosa

Conclusão

A impressão TLS é uma camada de proteção que muitos parsers ignoram completamente, gastando recursos para encontrar o IP e User-Agent ideais, mas esquecendo que a própria estrutura do handshake TLS revela a automação antes que o servidor olhe para os cabeçalhos. A solução é usar bibliotecas com suporte a impersonação TLS (curl_cffi, tls-client), sincronizar a versão do perfil com o User-Agent e verificar o hash JA4 final antes de lançar em escala.

O IP ainda é um fator importante — sem um endereço limpo, mesmo a impressão TLS ideal não ajudará a contornar o bloqueio por reputação de rede. Para parsing de marketplaces e monitoramento de preços, é sensato combinar a configuração TLS correta com proxies residenciais — essa combinação cobre ambas as camadas de detecção e reduz significativamente a porcentagem de bloqueios em longas sessões de parsing.