A maioria dos scrapers falha antes mesmo de um único header ser lido.
O servidor analisa a assinatura em nível de conexão que o seu cliente envia pela rede e decide se você é um navegador ou uma biblioteca cliente fingindo ser um. Python requests, net/http do Go, curl padrão: todos eles entregam uma fingerprint distinta no momento do handshake. Sites que se preocupam com isso (Datadome, Akamai, Imperva, a camada gerenciada da Cloudflare) encerram a conexão ou exibem uma página de desafio antes mesmo que a sua string de User-Agent importe.
É isso que o unblocker: true resolve no FourA. No último mês, ajustamos os componentes necessários para fazê-lo funcionar de forma confiável.
O que há de novo
O unblocker: true é uma flag única em qualquer chamada do /api/single. Ative-a e faremos três coisas: injetar o conjunto de headers de navegador, enviar a request por meio de um transporte que corresponde exatamente ao que um navegador real trafega na rede e descompactar qualquer retorno do servidor (gzip, brotli, deflate). As duas primeiras opções estavam disponíveis desde o beta. A terceira (autodescompressão brotli) foi lançada em 25 de março, e o trabalho de fixação de versão entrou no ar no dia seguinte para manter headers e transporte em sincronia total.
Como funciona
Veja como é uma request:
curl -X POST "https://api.foura.ai/api/single" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"url": "https://example.com/products",
"method": "GET",
"unblocker": true
}'
Três camadas são executadas por baixo.
Injeção de header. Definimos o pacote completo de headers do navegador: User-Agent, Sec-Ch-Ua, Sec-Ch-Ua-Platform, Sec-Fetch-Site, Sec-Fetch-Mode, Sec-Fetch-Dest, Accept, Accept-Language e Accept-Encoding. A ordem importa. Navegadores reais emitem esses dados em uma sequência específica, e as bibliotecas de detecção verificam isso.
Assinatura de conexão. Nosso transporte replica o formato exato em nível de bytes de uma sessão de navegador atualizada: a mesma ordem de extensões, as mesmas preferências de cifra, as mesmas peculiaridades de handshake. O cURL padrão, o requests do Python e o net/http do Go produzem assinaturas sinalizadas por máquinas em milissegundos em infraestruturas protegidas.
Descompressão automática. Quando unblocker está ativo, definimos Accept-Encoding como gzip, deflate, br e o transporte descompacta o body. Você recebe uma string decodificada de volta (ou um Buffer se passar returnBuffer: true). Sem manipulação manual de brotli, sem divergências de headers versus body quando um site escolhe deflate em vez de gzip.
Por que a fixação de versões importa
As assinaturas de conexão são vinculadas à versão. Os detalhes de rede de um navegador neste mês não são os mesmos do mês passado, e um site que realiza fingerprinting com rigor notará a divergência. Fixamos as partes móveis juntas para que headers, objetos navigator e a assinatura de conexão informem exatamente a mesma versão do navegador.
Se isso parece trabalhoso, é porque realmente é. Tivemos problemas com uma inconsistência durante a migração do monorepo em março, quando uma parte foi atualizada automaticamente e o restante perdeu a sincronização. A correção levou dois commits: fixar a parte móvel e nunca confiar que o gerenciador de pacotes manterá tudo alinhado para você.
Impacto
Em testes internos contra sites que verificam a origem da requisição (finanças, viagens, grandes e-commerces), a diferença entre unblocker: false e unblocker: true é a diferença entre uma página de desafio e um status 200. Um cliente HTTP comum frequentemente recebe um 403 logo na primeira tentativa. A mesma URL com unblocker: true acessa a página, porque a request se parece exatamente com o navegador informado.
Mas para sites que não realizam fingerprinting (a maioria das APIs públicas, templates CMS legados, qualquer item protegido apenas por rate limits de IP), manter unblocker desativado funciona bem e economiza alguns milissegundos de negociação. Use onde for necessário.
Para usuários avançados
Alguns padrões úteis.
Combine unblocker com um proxy residencial quando o destino também verificar a reputação do IP. IPs de datacenter combinados a uma assinatura de conexão perfeita ainda geram alertas em ASNs que o site bloqueou. Nosso endpoint de proxy (/api/proxy) faz rotação por domínio de destino, portanto adicionar "proxy": "residential" à request geralmente é suficiente.
Ignore unblocker ao chamar APIs JSON que não se importam com navegadores. Os headers adicionais podem parecer suspeitos para uma API que espera um cliente programático, como um backend chamando seu próprio microsserviço.
Se o site verificar o visitante com JavaScript antes de exibir a página, apenas unblocker não será suficiente. Você precisa do endpoint de browser, que executa o JavaScript da página em um navegador completo. Esse é um produto diferente com preços de créditos distintos, e detalhamos isso em Tarefas de Browser: Como Fazer Scraping de Sites com Uso Intenso de JavaScript.
E você pode combinar unblocker com o bloco validate para rejeitar respostas que tecnicamente retornam 200, mas contêm uma página de desafio:
{
"url": "https://example.com/products",
"method": "GET",
"unblocker": true,
"validate": {
"data": { "fail": ["captcha", "Access Denied"] }
}
}
Isso transforma falhas silenciosas em falhas classificadas, o que é essencial para o monitoramento da sua taxa de sucesso no dashboard.
Próximos passos
Os navegadores lançam uma nova versão estável a cada quatro semanas. Atualizamos nossa stack para acompanhar. Você não precisa alterar nada do seu lado: o unblocker: true continua apontando para a versão de navegador que verificamos de ponta a ponta.
O trabalho mais complexo está por vir. Verificações de HTTP/3 já estão aparecendo em sites maiores, o transporte QUIC é mais difícil de emular com precisão do que o transporte antigo, e a migração de conjuntos estáticos de headers para uma emulação verdadeiramente dinâmica está começando. Sites protegidos passaram a verificar a ordem dos frames HTTP/2, e a diferença entre "uma biblioteca parecida com um navegador" e "um navegador real" vai diminuir de ambos os lados. Escreveremos sobre isso assim que lançarmos.