🎯 Um navegador em nuvem personalizável e anti-detecção alimentado por Chromium desenvolvido internamente, projetado para rastreadores web e agentes de IA. 👉Experimente agora
De volta ao blog

Download de Arquivo Puppeteer: Um Guia Completo para Desenvolvedores Node.js

Alex Johnson
Alex Johnson

Senior Web Scraping Engineer

30-Jun-2026

TL;DR:

  • Os downloads no Chrome headless são um problema do CDP, não um problema da API do Puppeteer. Puppeteer não tem um page.download() de primeira classe; você controla diretamente o Chrome DevTools Protocol com Browser.setDownloadBehavior e ouve Browser.downloadProgress.
  • allowAndName mais eventsEnabled é a combinação que realmente relata a conclusão. Definir o comportamento por si só silencia a caixa de diálogo "salvar arquivo"; ativar eventos é o que permite que você await a contagem de bytes concluída em vez de adivinhar com um atraso fixo.
  • Em um navegador na nuvem, o arquivo fica do lado do servidor — então você busca os bytes de volta através da página. Um fetch() de mesma origem dentro de page.evaluate() retorna o arquivo como base64, que você decodifica e escreve no disco local. Sem máquina headful, sem volume compartilhado.
  • Anti-bot e geo-bloqueio se aplicam a downloads também. Muitos arquivos bloqueados servem apenas a um IP residencial no país certo; fixar a saída com proxyCountry é parte do processo para garantir que o download seja bem-sucedido.
  • Todo o fluxo roda no Scrapeless Scraping Browser com uma chamada Puppeteer.connect(). O navegador na nuvem cria a sessão, aplica detecção de impressão digital anti-detectação e entrega ao Puppeteer um ponto de extremidade WebSocket padrão — seu código de download é simples CDP a partir daí.
  • Grátis para começar. Novas contas Scrapeless incluem tempo de execução gratuito do Scraping Browser — inscreva-se em app.scrapeless.com.

Introdução: por que "baixar um arquivo com Puppeteer" é mais difícil do que parece

Puppeteer dá aos desenvolvedores Node.js controle total sobre uma página do Chrome — clicando, digitando, lendo o DOM. Downloads de arquivos são a única tarefa comum para a qual não há um método dedicado. Não existe await page.download(selector). Clicar em um link de download em uma sessão padrão headless faz uma das duas coisas pouco úteis: a navegação é engolida, ou o Chrome bloqueia a transferência porque nenhum diretório de download está configurado.

O controle real está uma camada abaixo, no Chrome DevTools Protocol (CDP). Browser.setDownloadBehavior informa ao Chrome onde os arquivos devem ir e se deve permitir esses downloads; Browser.downloadWillBegin e Browser.downloadProgress relatam o ciclo de vida para que você possa esperar pelo momento exato em que um arquivo termina em vez de dormir e esperar.

Execute isso na sua própria máquina e você ainda possui dois problemas não relacionados ao CDP: o site de destino sinaliza o Chrome headless como um bot, e arquivos bloqueados muitas vezes recusam qualquer coisa que não seja um IP residencial na região esperada. Este guia executa todo o fluxo em cima do Scrapeless Scraping Browser — um navegador na nuvem anti-detectação que cria a sessão, aplica saída residencial e entrega ao Puppeteer um ponto de extremidade WebSocket normal. O código de download permanece puro CDP; os problemas de detecção e geolocalização são tratados pelo tempo de execução. Há uma reviravolta que um navegador na nuvem adiciona — os arquivos são baixados do lado do servidor — e a segunda metade deste guia mostra o padrão para puxar esses bytes de volta para o seu disco local.


O Que Você Pode Fazer Com Isso

  • Puxar relatórios, exportações e declarações por trás de um login — PDFs de fatura, exportações CSV, arquivos de sala de dados — assim que a sessão for autenticada.
  • Capturar arquivos gerados que uma página constrói no lado do cliente a partir de um blob (exportações de gráficos, botões "baixar CSV") e que nunca existem como uma URL estática.
  • Pegar documentos bloqueados que servem apenas a um IP residencial em um país específico, fixando a saída antes da solicitação.
  • Aguardar de forma determinística que uma transferência termine usando downloadProgress em vez de um atraso fixo frágil.
  • Escalar o mesmo script por muitos arquivos ou contas sem precisar de máquinas headful — o navegador é remoto.

Por Que Scrapeless Scraping Browser

Scrapeless Scraping Browser é um navegador na nuvem personalizável e anti-detectação, projetado para rastreadores da web e agentes de IA. Para downloads com Puppeteer especificamente, ele oferece:

  • Uma conexão padrão do PuppeteerPuppeteer.connect() retorna um objeto Browser comum, então cada chamada do CDP que você já conhece funciona inalterada.
  • Proxies residenciais em mais de 195 países — fixe proxyCountry para que arquivos bloqueados sirvam a um IP que eles confiam.
  • Impressão digital anti-detectação do lado da nuvem — a sessão se parece com um navegador real, então o link de download é realmente oferecido em vez de estar escondido atrás de um muro de bot.
  • Persistência da sessão — mantenha cookies e estado de autenticação quentes durante as navegações, o que torna os downloads com login possíveis.
  • Chromium auto-desenvolvido — superfície CDP completa, então Browser.setDownloadBehavior e os eventos de download se comportam exatamente conforme documentado.

Obtenha sua chave de API no plano gratuito em app.scrapeless.com.


Pré-requisitos

  • Node.js 18 ou mais recente
  • Uma conta Scrapeless e chave de API — inscreva-se em app.scrapeless.com
  • Familiaridade básica com Puppeteer e async/await

Instalar

1. Adicione o SDK e o Puppeteer

O SDK Scrapeless cria a sessão na nuvem e conecta o Puppeteer a ela. Você precisa do puppeteer-core (o cliente de protocolo sem um Chromium embutido — o navegador é remoto):

bash Copy
npm install @scrapeless-ai/sdk puppeteer-core

2. Defina sua chave API

Leia-a do ambiente; nunca a codifique diretamente:

bash Copy
export SCRAPELESS_API_KEY="seu_token_api_aqui"

Puppeteer.connect() cria uma sessão Scrapeless e retorna um Browser padrão do Puppeteer. Defina o país do proxy aqui para que cada solicitação — incluindo o download — seja realizada na região desejada:

javascript Copy
import { Puppeteer } from '@scrapeless-ai/sdk';

const browser = await Puppeteer.connect({
  apiKey: process.env.SCRAPELESS_API_KEY,
  sessionName: 'puppeteer-downloads',
  proxyCountry: 'US',
  sessionTTL: 300, // segundos que a sessão permanece ativa
});

const page = await browser.newPage();

A partir daqui, browser e page são objetos comuns do Puppeteer. Tudo abaixo é padrão do CDP.


Implementação básica: definir comportamento de download e aguardar a conclusão

Existem duas chamadas do CDP que importam e um evento no qual você deve aguardar:

  1. Browser.setDownloadBehavior com behavior: 'allowAndName' permite o download e nomeia o arquivo pelo seu GUID no lado do servidor. eventsEnabled: true é a parte que a maioria dos guias esquece — sem isso, nenhum evento de progresso é acionado e você volta a dormir.
  2. Browser.downloadWillBegin informa que uma transferência começou, com o suggestedFilename e um guid.
  3. Browser.downloadProgress relata inProgresscompleted (ou canceled), com receivedBytes e totalBytes.
javascript Copy
const cdp = await page.createCDPSession();

await cdp.send('Browser.setDownloadBehavior', {
  behavior: 'allowAndName',
  downloadPath: '/tmp/downloads',
  eventsEnabled: true,
});

// Resolva apenas quando a transferência realmente terminar
const downloadComplete = new Promise((resolve) => {
  let meta = {};
  cdp.on('Browser.downloadWillBegin', (e) => {
    meta = { filename: e.suggestedFilename, guid: e.guid };
  });
  cdp.on('Browser.downloadProgress', (e) => {
    if (e.state === 'completed') {
      resolve({ ...meta, totalBytes: e.totalBytes });
    }
  });
});

Agora, inicie o download — clicando em um botão, um link ou, como aqui, em um arquivo gerado pelo cliente na página — e aguarde a promessa:

javascript Copy
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });

// Um botão "download CSV" que constrói o arquivo no navegador a partir de um blob
await page.evaluate(() => {
  const blob = new Blob(['col1,col2\n1,2\n3,4\n'], { type: 'text/csv' });
  const a = document.createElement('a');
  a.href = URL.createObjectURL(blob);
  a.download = 'report.csv';
  document.body.appendChild(a);
  a.click();
});

const result = await downloadComplete;
console.log(result);
// { filename: 'report.csv', guid: '845c9455-…', totalBytes: 18 }

A promessa é resolvida no momento em que state === 'completed' chega — sem sono fixo, e você recebe a contagem real de bytes de volta.

Obtenha sua chave API no plano gratuito: app.scrapeless.com


A reviravolta na nuvem: obter os bytes no seu disco local

Em uma execução local com interface gráfica, allowAndName grava o arquivo no seu downloadPath e você o lê do disco. Em um navegador na nuvem, o arquivo vai para a sessão remota, não para a sua máquina — então downloadPath está no lado do servidor e seu /tmp/downloads local permanece vazio.

O padrão confiável é buscar os bytes do arquivo dentro do contexto da página e retorná-los como base64, depois decodificá-los e escrevê-los localmente. A única regra: fetch() está sujeito à política de mesma origem, então navegue para a origem do arquivo primeiro, depois busque:

javascript Copy
import { writeFileSync } from 'node:fs';

const fileUrl = 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf';

// Acesse a origem do arquivo para que fetch() seja de mesma origem (sem bloqueio CORS)
await page.goto(new URL(fileUrl).origin, { waitUntil: 'domcontentloaded' });

const out = await page.evaluate(async (url) => {
  const res = await fetch(url);
  const bytes = new Uint8Array(await res.arrayBuffer());
  let binary = '';
  for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
  return {
    status: res.status,
    type: res.headers.get('content-type'),
    b64: btoa(binary),
  };
}, fileUrl);

const buffer = Buffer.from(out.b64, 'base64');
writeFileSync('./dummy.pdf', buffer);
console.log({ status: out.status, type: out.type, bytes: buffer.length });
// { status: 200, type: 'application/pdf; qs=0.001', bytes: 13264 }

Porque a busca é executada dentro da página autenticada, ela transporta os cookies da sessão — assim, arquivos atrás de um login são baixados exatamente como arquivos à frente de um. A abordagem de evento CDP e essa abordagem de busca são complementares: use os eventos para saber quando uma transferência acionada por clique foi concluída; use a busca dentro da página quando você já tiver a URL do arquivo e quiser os bytes de volta localmente.


Padrões Avançados

Defina a saída para arquivos bloqueados. Se um documento serve apenas para uma região, defina proxyCountry no momento da conexão. O download, então, herda esse IP residencial — sem a confusão de proxy por solicitação.

Autentique-se, depois baixe. Mantenha a mesma page (e, portanto, a mesma sessão e cookies) para o fluxo de login e o download. A persistência de sessão sem scrap mantém o estado de autenticação aquecido durante as navegações, então a busca dentro da página acima vê um contexto autenticado.

Leia o progresso para arquivos grandes. Browser.downloadProgress também dispara com state: 'inProgress' e um receivedBytes crescente. Registre a proporção em relação a totalBytes para exibir uma barra de progresso real em vez de um spinner.

Feche a sessão quando terminar. await browser.close() encerra a sessão na nuvem prontamente, para que você não esteja mantendo tempo de execução que não está usando.


Solução de Problemas

Sintoma Causa Correção
Nenhum evento downloadProgress é acionado eventsEnabled não definido Passe eventsEnabled: true para Browser.setDownloadBehavior
Clique navega em vez de baixar O servidor envia o arquivo inline, não como um anexo Use o padrão de recuperação fetch() dentro da página na URL do arquivo
downloadPath local está vazio O arquivo está na sessão remota da nuvem, não no seu disco Busque os bytes de volta através da página (veja "a reviravolta da nuvem")
fetch() lança um erro CORS A origem da página é diferente da origem do arquivo page.goto(new URL(fileUrl).origin) antes de buscar
O link de download nunca aparece O site o escondeu atrás de um muro de bot/geo Defina proxyCountry e deixe a impressão digital do navegador na nuvem renderizar a página real

Conclusão: downloads como um passo de primeira classe em seu pipeline

Baixar um arquivo com Puppeteer se resume a três movimentos: dizer ao Chrome para permitir e relatar downloads (Browser.setDownloadBehavior com eventsEnabled), aguardar o verdadeiro evento de conclusão (Browser.downloadProgress), e — em um navegador na nuvem — puxar os bytes de volta através de uma busca dentro da página com a mesma origem. Executá-lo no Scrapeless Scraping Browser junta as duas partes difíceis que não têm nada a ver com CDP — detecção de bot e geo-bloqueio — na execução, então o mesmo script que funciona em um arquivo público também funciona em um bloqueado, autenticado. Para fluxos orientados por formulários que levam a um download, combine isso com o guia de navegador em nuvem Scrapling, e veja a página do produto Scraping Browser e documentação para toda a superfície CDP. Defina a saída, mantenha a sessão aquecida para arquivos autenticados e espere pelo completed em vez de uma pausa.


Pronto para Construir Seu Pipeline de Dados Poderado por IA?

Junte-se à nossa comunidade para reivindicar um plano gratuito e conectar-se com desenvolvedores criando pipelines de download e extração: Discord · Telegram.

Inscreva-se em app.scrapeless.com para um tempo de execução gratuito do Scraping Browser e adapte os padrões acima aos arquivos, regiões e logins que seu fluxo de trabalho precisa. Veja preços para escalabilidade.


FAQ

P: O Puppeteer tem um método de download embutido?
Não. Não existe page.download(). Você configura downloads através do Chrome DevTools Protocol com Browser.setDownloadBehavior e os observa com os eventos Browser.downloadWillBegin e Browser.downloadProgress.

P: Preciso de um proxy para baixar arquivos?
Para arquivos públicos, não estritamente. Para arquivos bloqueados por região ou servidos apenas para IPs residenciais, sim — defina proxyCountry no momento da conexão para que a transferência seja realizada a partir de um IP que o site confia.

P: Por que meu diretório de download local está vazio ao executar em um navegador na nuvem?
Porque o arquivo é baixado para a sessão remota, não para sua máquina. Recupere os bytes buscando a URL do arquivo dentro de page.evaluate() e decodificando o base64 localmente, como mostrado acima.

P: Como faço para baixar um arquivo que está atrás de um login?
Autentique-se primeiro na mesma página, depois execute o fetch() na página — ele carrega os cookies de sessão, então o arquivo é baixado como o usuário logado. A persistência de sessão sem rastreamento mantém esse estado de autenticação durante as navegações.

P: Como posso esperar o download terminar em vez de adivinhar um tempo limite?
Escute o Browser.downloadProgress e resolva quando state === 'completed'. O evento inclui receivedBytes e totalBytes, então você também pode exibir o progresso real.

P: Posso executar isso sem um agente de IA ou ferramentas extras?
Sim. Isso é apenas Puppeteer puro mais CDP sobre a sessão Scrapeless — nenhum agente é necessário. O SDK apenas estabelece a conexão.

Na Scorretless, acessamos apenas dados disponíveis ao público, enquanto cumprem estritamente as leis, regulamentos e políticas de privacidade do site aplicáveis. O conteúdo deste blog é apenas para fins de demonstração e não envolve atividades ilegais ou infratoras. Não temos garantias e negamos toda a responsabilidade pelo uso de informações deste blog ou links de terceiros. Antes de se envolver em qualquer atividade de raspagem, consulte seu consultor jurídico e revise os termos de serviço do site de destino ou obtenha as permissões necessárias.

Artigos mais populares

Catálogo