Download de Arquivo Puppeteer: Um Guia Completo para Desenvolvedores Node.js
Senior Web Scraping Engineer
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 comBrowser.setDownloadBehaviore ouveBrowser.downloadProgress. allowAndNamemaiseventsEnabledé 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êawaita 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 depage.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
downloadProgressem 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 Puppeteer —
Puppeteer.connect()retorna um objetoBrowsercomum, então cada chamada do CDP que você já conhece funciona inalterada. - Proxies residenciais em mais de 195 países — fixe
proxyCountrypara 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.setDownloadBehaviore 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
npm install @scrapeless-ai/sdk puppeteer-core
2. Defina sua chave API
Leia-a do ambiente; nunca a codifique diretamente:
bash
export SCRAPELESS_API_KEY="seu_token_api_aqui"
Configurar: conectar o Puppeteer ao navegador na nuvem
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
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:
Browser.setDownloadBehaviorcombehavior: '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.Browser.downloadWillBegininforma que uma transferência começou, com osuggestedFilenamee umguid.Browser.downloadProgressrelatainProgress→completed(oucanceled), comreceivedBytesetotalBytes.
javascript
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
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
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.



