Puppeteer e CAPTCHA: por que aparece, como reduzir?

Publicado:

12 min de leitura

Acar Diveroli
Autor: Acar Diveroli
Grade de CAPTCHA com algumas células marcadas e um cursor de mouse

O Puppeteer é uma biblioteca Node.js que permite controlar o Chrome via código: abrir página, preencher formulário, tirar captura de tela, esperar o conteúdo dinâmico carregar. É usado em muitos trabalhos, de testes ponta a ponta à geração de relatórios. Mas, conforme a automação cresce, a maioria das equipes esbarra no mesmo obstáculo: o CAPTCHA.

Este artigo não fala sobre "resolver" o CAPTCHA, mas sobre entender por que ele aparece e evitar que seja disparado desnecessariamente em uma automação legítima. O CAPTCHA é a forma como o dono do site diz "não tenho certeza sobre esse tráfego"; ler esse sinal corretamente é sempre mais sustentável do que competir com ele. No fim do artigo há uma configuração funcional de Puppeteer, uma checklist e uma lista do que não fazer.

Tipos de CAPTCHA e a lógica de disparo

A maioria dos CAPTCHAs que você encontra hoje não é a tela de "selecione os semáforos na imagem". Existem três formas comuns:

  • Verificação invisível. Ao carregar a página, o ambiente do navegador e o comportamento são pontuados em segundo plano; o usuário não vê nada. Se a pontuação for baixa, passa-se para uma etapa visível.
  • Confirmação de um clique. Uma caixa "não sou um robô" ou uma confirmação leve como o Cloudflare Turnstile. Para a maioria dos usuários reais, passa com um único clique.
  • Quebra-cabeça visual ou interativo. A etapa que exige esforço humano, exibida quando a pontuação é muito baixa.

Essas três formas são fases diferentes do mesmo sistema de pontuação. Ou seja, o CAPTCHA não é uma questão de "apareceu" ou "não apareceu", mas de qual limite a sua pontuação ultrapassou. Cada medida que mantém a pontuação baixa evita que você chegue à etapa visível.

Por que o CAPTCHA aparece?

Proteções modernas contra bots não olham para uma única regra; pontuam muitos sinais em conjunto. Nas sessões do Puppeteer, os fatores que mais elevam essa pontuação são:

1. Tipo e reputação do endereço IP

Se a requisição vem de um IP de datacenter, ela já é considerada mais suspeita, de partida, do que uma requisição vinda de um usuário doméstico comum. Muitas sessões abertas em pouco tempo a partir do mesmo IP, ou o endereço já ter sido usado de forma abusiva antes, aumentam ainda mais a pontuação. Explicamos a diferença entre os tipos de IP no artigo Diferença entre proxy residencial e datacenter.

2. Velocidade e padrão de requisição

Pessoas leem páginas, rolam a tela, esperam. Uma sessão que abre dezenas de páginas por segundo, fazendo exatamente o mesmo clique no mesmo tempo em cada página, não se parece com comportamento humano. Até uma espera de intervalo fixo é um padrão; as esperas humanas são irregulares.

3. Vestígios de navegador headless

Um navegador aberto via automação, nas configurações padrão, pode carregar vestígios que o denunciam. O mais conhecido é a propriedade navigator.webdriver estar como true; essa propriedade existe como padrão justamente para indicar um navegador sob automação. Tamanhos de janela irreais (o padrão do Puppeteer é 800×600), recursos de navegador ausentes e valores de User-Agent específicos do modo headless também chamam atenção.

4. Perfil inconsistente

Um navegador com um IP vindo de Istambul, mas com idioma en-US e fuso horário de Nova York; ou uma única sessão com um fingerprint que muda a cada requisição. Sinais que se contradizem entre si são mais suspeitos do que cada um isoladamente. Explicamos como o fingerprint se forma no artigo O que é fingerprint do navegador?.

5. Ausência de histórico de sessão

Um navegador aberto do zero a cada execução, sem nenhum cookie, parece um usuário visitando o site pela primeira vez. Isso não é um problema por si só, mas eleva a pontuação quando combinado com outros sinais. O cookie de uma sessão que já passou por uma verificação reduz a pontuação nas visitas seguintes.

6. Análise comportamental

Algumas proteções não olham só o momento de entrada, mas o movimento do cursor e a consistência da interação ao longo de toda a sessão. Explicamos essa nova abordagem em detalhe no artigo Cloudflare Precursor.

Causas e medidas em uma tabela

CausaSinalMedida legítima
IP de datacenterTipo de ASN, reputação do IPProxy residencial ou ISP
Velocidade altaFrequência de requisição, intervalo fixoEspera variável, concorrência baixa
Vestígios headlessnavigator.webdriver, janela padrãoJanela realista, modo headless atualizado
Perfil inconsistenteContradição entre localização do IP e idioma/fuso horárioAjustar o perfil de acordo com o IP
Sessão sem históricoCookie vazio, perfil novouserDataDir persistente
Mudança de IP dentro da sessãoMesmo cookie, endereço diferenteIP sticky ou fixo

Como reduzir o CAPTCHA por meios legítimos?

O objetivo comum das medidas a seguir não é esconder a sua automação, mas garantir que ela não gere suspeita desnecessária.

Reduza a velocidade e distribua as requisições

Essa é a medida mais eficaz e mais barata. Adicione esperas variáveis entre as trocas de página, limite o número de abas abertas ao mesmo tempo e distribua o trabalho por horários diferentes do dia. Reduzir a carga no site de destino significa menos obstáculos para você e menos custo para o outro lado.

javascript
const bekle = (enAz, enCok) =>
  new Promise((coz) => setTimeout(coz, enAz + Math.random() * (enCok - enAz)));

for (const url of urls) {
  await page.goto(url, { waitUntil: "domcontentloaded" });
  // processar a página
  await bekle(2000, 6000);
}

Preserve sessões e cookies

Em vez de abrir um perfil novo a cada execução, use um diretório de dados de usuário persistente. Assim, os cookies e as verificações já concluídas são preservados entre as sessões:

javascript
import puppeteer from "puppeteer";

const browser = await puppeteer.launch({
  userDataDir: "./perfil-1",
});

Se você gerencia mais de uma conta ou tarefa, use um diretório separado para cada uma; misturar perfis gera o sinal de que muitas contas estão sendo geridas a partir de um único dispositivo.

Mantenha o perfil coerente

O idioma, o fuso horário e o tamanho de janela do navegador devem ser coerentes com a localização do IP que você está usando. Não mude esses valores durante a mesma sessão:

javascript
const page = await browser.newPage();
await page.setViewport({ width: 1366, height: 768 });
await page.emulateTimezone("Europe/Istanbul");
await page.setExtraHTTPHeaders({ "Accept-Language": "tr-TR,tr;q=0.9" });

Escolha o tamanho da janela entre valores comuns em dispositivos reais; uma resolução incomum chama atenção por si só.

Use um único IP por sessão

No Puppeteer, o proxy é passado pelo argumento de inicialização do Chrome. Se for necessária autenticação, use page.authenticate:

javascript
import puppeteer from "puppeteer";

const browser = await puppeteer.launch({
  args: ["--proxy-server=http://pr.proxynet.io:8000"],
});

const page = await browser.newPage();
await page.authenticate({ username: "kullanici", password: "parola" });

await page.goto("https://httpbin.org/ip", { waitUntil: "networkidle2" });
console.log(await page.evaluate(() => document.body.innerText));

await browser.close();

O importante aqui é o IP não mudar durante a sessão. O endereço IP mudar no meio de uma sessão já autenticada é uma das causas mais frequentes de CAPTCHA. Em fluxos assim, o Proxies de sessão fixa mantém o mesmo IP por um determinado período; em sessões longas baseadas em conta, o Proxies ISP é mais estável. Em sites protegidos, o Proxies residenciais, vindo de endereços de usuários reais, gera menos suspeita que IPs de datacenter.

Não bloqueie recursos desnecessariamente

Bloquear imagens e arquivos de estilo para economizar banda é um hábito comum. Mas um "navegador" que nunca carrega nenhuma imagem não se parece com um usuário real, e algumas proteções usam essa ausência como sinal. Se o custo de tráfego é o problema, bloquear apenas arquivos de mídia grandes (vídeo, imagens grandes) é um meio-termo mais equilibrado.

Prefira a fonte oficial quando possível

Se o site de destino oferece uma API, pode não ser nem necessário usar automação de navegador. APIs são mais rápidas, consomem menos recursos e você não esbarra em CAPTCHA. Se você está testando o seu próprio site ou o site de um cliente, pedir ao dono do site para isentar o seu tráfego de teste nas regras de proteção é a solução mais limpa.

Exemplo completo: uma configuração consistente de Puppeteer

Uma configuração que reúne as medidas acima, funciona com proxy e espera de forma variável entre as páginas:

javascript
import puppeteer from "puppeteer";

const bekle = (enAz, enCok) =>
  new Promise((coz) => setTimeout(coz, enAz + Math.random() * (enCok - enAz)));

const browser = await puppeteer.launch({
  userDataDir: "./perfil-1",
  args: ["--proxy-server=http://pr.proxynet.io:8000", "--window-size=1366,768"],
  defaultViewport: { width: 1366, height: 768 },
});

const page = await browser.newPage();
await page.authenticate({ username: "kullanici", password: "parola" });
await page.emulateTimezone("Europe/Istanbul");
await page.setExtraHTTPHeaders({ "Accept-Language": "tr-TR,tr;q=0.9" });

const urls = ["https://httpbin.org/ip", "https://httpbin.org/headers"];

for (const url of urls) {
  await page.goto(url, { waitUntil: "domcontentloaded", timeout: 30000 });
  console.log(url, (await page.evaluate(() => document.body.innerText)).slice(0, 80));
  await bekle(2000, 5000);
}

await browser.close();

Nessa configuração, o IP é fixo durante toda a sessão, o perfil é persistente, o fuso horário e o idioma são coerentes com a localização do IP (Turquia), e há uma espera irregular e parecida com a humana entre as páginas.

O que você não deve fazer

  • Usar serviços de resolução de CAPTCHA. Serviços que fazem pessoas ou modelos resolverem CAPTCHA e repassam o resultado para a automação miram diretamente em uma proteção que o dono do site estabeleceu de forma explícita. Isso viola os termos de uso de muitos sites e pode gerar risco jurídico.
  • Confiar em plugins de evasão de detecção. Plugins que afirmam esconder vestígios de automação vivem em uma corrida constante contra os provedores de proteção. Um método que funciona hoje pode não funcionar amanhã; construir seu fluxo de trabalho em cima disso não é sustentável.
  • Aumentar a velocidade quando bloqueado. O CAPTCHA é um aviso. Responder com mais requisições geralmente termina com o bloqueio total do IP.
  • Trocar o IP a cada requisição mantendo a mesma sessão. O cookie permanecer o mesmo enquanto o endereço muda o tempo todo é um padrão mais suspeito do que apenas trocar de IP.

Explicamos quais dados podem ser coletados sob quais condições no artigo A extração de dados é legal?.

O que fazer quando o CAPTCHA aparecer?

Se, mesmo com as medidas tomadas, você está vendo CAPTCHA, use isso como uma oportunidade de diagnóstico:

  1. Registre em qual página ele aparece. Na página de login, na listagem, na página de detalhe? Isso mostra onde a proteção está concentrada.
  2. Troque o IP e repita o mesmo fluxo. Se o CAPTCHA desaparecer, o problema está na reputação do IP; se persistir, é do perfil ou da velocidade.
  3. Reduza a velocidade pela metade. Se a taxa cair, o limite tem origem na velocidade.
  4. Compare o perfil com um navegador real. Se você entra no mesmo site com um Chrome normal e não vê CAPTCHA, os vestígios de automação são determinantes.

Esses quatro passos revelam, em algumas tentativas, qual sinal está elevando a pontuação. Fazer um teste de uma variável por vez economiza tempo em comparação a tentativas às cegas.

Outras ferramentas são melhores que o Puppeteer?

A situação do Selenium, do Playwright e do Puppeteer perante o CAPTCHA é, no fundo, a mesma: todos controlam um navegador real via código e estão sujeitos aos mesmos sinais. Trocar de ferramenta não elimina as causas acima. Para os equivalentes no ecossistema Python, veja nossos artigos de Selenium, Proxy com o SeleniumBase e Undetected ChromeDriver. Comparamos outros fatores que influenciam a escolha da linguagem no artigo Extração de dados: JavaScript ou Python?.

Perguntas frequentes

O modo headless aumenta o CAPTCHA?

O antigo modo headless carregava vestígios mais fáceis de diferenciar de um navegador normal. O modo headless atual do Chrome é muito mais próximo do navegador normal. Ainda assim, rodar em headless pode afetar a pontuação quando combinado com outros sinais.

O proxy evita totalmente o CAPTCHA?

Não. O tipo certo de IP reduz a pontuação de suspeita, mas outros sinais, como velocidade de requisição, inconsistência de perfil e comportamento, continuam existindo. O IP é apenas uma parte da solução.

Trocar de IP a cada requisição é uma boa ideia?

Em capturas de página independentes que não exigem sessão, sim; o Proxies rotativos é adequado para esse trabalho. Em fluxos com login ou de várias etapas, o IP precisa se manter fixo durante toda a sessão; caso contrário, a chance de CAPTCHA aumenta.

Posso usar proxy SOCKS5 no Puppeteer?

Sim. É passado no formato --proxy-server=socks5://servidor:porta. Mas o Chrome não suporta autenticação por usuário e senha para SOCKS5; se for usar SOCKS5, você precisa autorizar o IP pelo painel do proxy. As diferenças de protocolo estão no artigo Diferença entre SOCKS e HTTP proxy.

O CAPTCHA aparece menos em automação de site mobile?

A visualização mobile, por si só, não reduz a pontuação. Se você usa um perfil mobile, o IP também precisa ser mobile para haver coerência; um IP de desktop com perfil mobile é uma contradição. Explicamos a diferença do tráfego mobile no artigo Diferença entre proxy residencial e móvel.

O uso de proxy é diferente entre Puppeteer e Playwright?

A lógica é a mesma: o endereço do proxy é passado ao iniciar o navegador, e as credenciais são definidas em uma chamada separada. No Playwright, esse ajuste é feito em um único objeto, no formato launch({ proxy: { server, username, password } }).

Em resumo

No Puppeteer, o CAPTCHA costuma ter origem no tipo de IP, na velocidade de requisição, nos vestígios de navegador headless e no perfil inconsistente. Reduzir a velocidade, preservar sessões, manter o perfil coerente com a localização do IP e usar um IP fixo por sessão reduz de forma significativa o CAPTCHA em automações legítimas. Quando o CAPTCHA aparecer, fazer um teste de uma variável por vez para encontrar a causa é muito mais rápido do que tentativas às cegas. Já tentar contornar a proteção é um caminho frágil e arriscado. Você encontra os tipos de IP adequados para os seus projetos de automação nas nossas soluções de proxy.