🎯 カスタマイズ可能で検出回避型のクラウドブラウザ。自社開発のChromiumを搭載し、ウェブクローラーAIエージェント向けに設計されています。👉今すぐ試す
ブログに戻ります

Puppeteer ファイルダウンロード: Node.js 開発者のための完全ガイド

Alex Johnson
Alex Johnson

Senior Web Scraping Engineer

30-Jun-2026

TL;DR:

  • ヘッドレスChromeのダウンロードはCDPの問題であり、Puppeteer-APIの問題ではありません。 Puppeteerには一級のpage.download()はなく、Browser.setDownloadBehaviorでChrome DevToolsプロトコルを直接操作し、Browser.downloadProgressをリッスンします。
  • allowAndNameeventsEnabledの組み合わせが、実際に完了を報告します。 挙動を設定するだけでは「ファイルを保存」のダイアログが抑制され、イベントをオンにすることで、固定のスリープで推測するのではなく、完了したバイト数をawaitできます。
  • クラウドブラウザでは、ファイルはサーバー側に保存されるため、ページを通じてバイトを取得します。 page.evaluate()内の同一オリジンのfetch()は、ファイルをbase64形式で返し、これをデコードしてローカルディスクに書き込みます。ヘッドフルマシンも共有ボリュームもありません。
  • ダウンロードにもボット対策やジオゲーティングが適用されます。 多くのゲート付きファイルは、特定の国の住宅IPにのみ提供されるため、proxyCountryで出口を固定することが、ダウンロードを成功させるための一部です。
  • すべてのフローは、1回のPuppeteer.connect()呼び出しでScrapeless Scraping Browser上で実行されます。 クラウドブラウザがセッションを生成し、検出防止のフィンガープリンティングを適用し、Puppeteerに標準のWebSocketエンドポイントを提供します — 以降のダウンロードコードは単純なCDPです。
  • 無料で始められます。 新しいScrapelessアカウントには無料のScraping Browserランタイムが含まれています — app.scrapeless.comでサインアップしてください。

はじめに: "Puppeteerでファイルをダウンロードする"ことが見た目よりも難しい理由

PuppeteerはNode.js開発者にChromeページを完全に制御する力を与えます — クリック、タイピング、DOMの読み取りが可能です。ファイルのダウンロードは専用メソッドがない唯一の一般的なタスクです。 await page.download(selector)は存在しません。デフォルトのヘッドレスセッションでダウンロードリンクをクリックすると、役に立たない2つのことのいずれかが発生します:ナビゲーションが飲み込まれるか、Chromeがダウンロードディレクトリが設定されていないために転送をブロックします。

実際の制御は1層下、Chrome DevToolsプロトコル(CDP)にあります。Browser.setDownloadBehaviorは、Chromeにファイルの行き先と許可の有無を指示します。Browser.downloadWillBeginBrowser.downloadProgressはライフサイクルを報告し、スリープして期待するのではなく、ファイルが完成する正確な時刻を待つことができます。

これを自分のマシンで実行すると、CDPとは無関係な2つの問題が残ります:ターゲットサイトはヘッドレスChromeをボットとしてフラグ付けし、ゲート付きファイルは期待する地域の住宅IP以外のものを拒否することがよくあります。このガイドはScrapeless Scraping Browserの上にすべてのフローを実行します — セッションを生成し、住宅の出口を適用し、Puppeteerに通常のWebSocketエンドポイントを提供する検出防止クラウドブラウザです。ダウンロードコードは純粋なCDPのままです。検出と地理の問題はランタイムによって処理されます。クラウドブラウザが追加するひとつのツイストは、ファイルがサーバー側でダウンロードされることです — このガイドの後半では、これらのバイトをローカルディスクに引き戻すためのパターンを示します。


できること

  • ログインの背後にあるレポート、エクスポート、ステートメントを取得 — 請求書PDF、CSVエクスポート、データルームファイル — セッションが認証されているとき。
  • クライアント側からblobを使用してページが生成するファイルをキャプチャ(チャートエクスポート、「CSVをダウンロード」ボタン)し、静的URLとして存在しないもの。
  • 特定の国の住宅IPにのみ提供されるゲート付きドキュメントを取得し、リクエスト前に出口を固定します。
  • downloadProgressを使用して、転送が終了するのを決定的に待つ fragilesfixed delayではなく。
  • 同じスクリプトを多くのファイルやアカウントにスケールし、ヘッドフルマシンを立ち上げずにブラウザをリモートで使用します。

なぜScrapeless Scraping Browserか

Scrapeless Scraping Browserは、ウェブクローラーやAIエージェント向けに設計されたカスタマイズ可能な検出防止クラウドブラウザです。特にPuppeteerのダウンロード向けに、以下の機能を提供します:

  • 標準のPuppeteer接続Puppeteer.connect()は通常のBrowserオブジェクトを返し、すでに知っているすべてのCDP呼び出しが変更なく動作します。
  • 195カ国以上の住宅プロキシproxyCountryを固定して、ゲート付きファイルが信頼するIPに配信されるようにします。
  • クラウド側の検出防止フィンガープリンティング — セッションは本物のブラウザのように見えるため、ダウンロードリンクがボット壁の背後に隠されることなく実際に提供されます。
  • セッションの永続性 — ナビゲーションを超えてクッキーと認証状態を温かく保ち、これによりログインしたダウンロードが可能になります。
  • 自己開発したChromium — 完全なCDPサーフェスがあり、Browser.setDownloadBehaviorおよびダウンロードイベントは、文書に記載された通りに正確に動作します。

無料プランでのAPIキーを取得するには、app.scrapeless.comをご覧ください。


前提条件

  • Node.js 18以上
  • ScrapelessアカウントとAPIキー — app.scrapeless.comでサインアップ
  • Puppeteerおよびasync/awaitに関する基本的な理解

インストール

1. SDKとPuppeteerを追加する

以下の英語のテキストを日本語に翻訳します。


Scrapeless SDKはクラウドセッションを作成し、Puppeteerをそれに接続します。puppeteer-coreが必要です(Chromiumがバンドルされていないプロトコルクライアント — ブラウザはリモートです):

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

2. APIキーを設定する

環境から読み取り、ハードコーディングしないでください:

bash Copy
export SCRAPELESS_API_KEY="your_api_token_here"

設定: Puppeteerをクラウドブラウザに接続する

Puppeteer.connect()はScrapelessセッションを作成し、標準のPuppeteer Browserを返します。ここでプロキシ国を指定すると、すべてのリクエスト — ダウンロードを含め — が希望する地域から出て行きます。

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, // セッションが生存する秒数
});

const page = await browser.newPage();

ここから、browserpageは通常のPuppeteerオブジェクトです。以下はすべて標準のCDPです。


基本的な実装: ダウンロード動作を設定し、完了を待つ

重要なCDPコールが2つあり、待機するイベントが1つあります:

  1. Browser.setDownloadBehaviorbehavior: 'allowAndName'はダウンロードを許可し、ファイル名をサーバー側でGUIDで名付けます。eventsEnabled: trueはほとんどのガイドが見逃す部分です — これがないと、進行状況イベントは発火せず、再びスリープ状態に戻ります。
  2. Browser.downloadWillBeginは転送が開始されたことを通知し、suggestedFilenameguidを提供します。
  3. Browser.downloadProgressinProgresscompleted(またはcanceled)を報告し、receivedBytestotalBytesを示します。
javascript Copy
const cdp = await page.createCDPSession();

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

// 転送が実際に終了するまで解決しない
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 });
    }
  });
});

ダウンロードをトリガーします — ボタンをクリックする、リンクをクリックする、またはここで示すようにページがクライアント側で生成するファイル — そして約束を待ちます:

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

// ブラウザ内でファイルを生成する「CSVをダウンロード」ボタン
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 }

約束はstate === 'completed'が到着した瞬間に解決されます — 固定のスリープはなく、実際のバイト数が戻されます。

無料プランのAPIキーを取得するには: app.scrapeless.com


クラウドのひねり: バイトをローカルディスクに取得する

ローカルのヘッドフル実行では、allowAndNameはファイルをdownloadPathに書き込み、ディスクから読み取ります。クラウドブラウザでは、ファイルはリモートセッションに置かれ、あなたのマシンには届きません — したがって、downloadPathはサーバー側であり、ローカルの/tmp/downloadsは空のままです。

信頼できるパターンは、ページコンテキスト内でファイルのバイトを取得し、それをbase64として返し、ローカルにデコードして書き込むことです。一つのルール: fetch()同一オリジンポリシーに従うため、まずファイルのオリジンに移動し、それから取得します:

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

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

// fetch()が同一オリジンになるようにファイルのオリジンに到達します(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 }

以下は翻訳結果です:

認証されたページ内でフェッチが実行されるため、これは セッションのクッキーを持ち運びます。そのため、ログインが必要なファイルは、ログインを必要としないファイルと同じようにダウンロードされます。CDPイベントアプローチとこのフェッチアプローチは補完的です:クリックによってトリガーされた転送が完了したタイミングを知るためにイベントを使用し、すでにファイルのURLがあり、ローカルにバイトを戻したい場合には、ページ内フェッチを使用します。


高度なパターン

ゲート付きファイルの出口を固定します。 ドキュメントが特定の地域にのみサービスを提供する場合、接続時に proxyCountry を設定します。ダウンロードはその住宅IPを引き継ぎます — リクエストごとのプロキシ操作は不要です。

認証後にダウンロードします。 ログインフローとダウンロードのために同じ page (したがって同じセッションとクッキー) を維持します。Scrapeless セッションの永続化は、ナビゲーション間で認証状態を保持するため、上記のページ内フェッチはログイン済みのコンテキストを認識します。

大きなファイルの進行状況を読み取ります。 Browser.downloadProgressstate: 'inProgress' と増加する receivedBytes で発火します。実際の進行バーを表示するために、totalBytes と対比させてログを取ります。

完了したらセッションを閉じます。 await browser.close() がクラウドセッションを迅速に終了させるので、使用していないランタイムを保持しません。


トラブルシューティング

症状 原因 修正
downloadProgress イベントが一度も発火しない eventsEnabled が設定されていない Browser.setDownloadBehavioreventsEnabled: true を渡します
クリックしてもダウンロードされずにナビゲートする サーバーがファイルをインラインで送信し、添付ファイルとして送信していない ファイルURLでページ内 fetch() パターンを使用します
ローカル downloadPath が空 ファイルがリモートクラウドセッションにあり、ディスク上にない ページを通してバイトを取得します(「クラウドツイスト」を参照)
fetch() が CORS エラーをスローする ページのオリジンがファイルのオリジンと異なる フェッチの前に page.goto(new URL(fileUrl).origin)
ダウンロードリンクが表示されない サイトがそれをボット/地理的障壁の後ろに隠している proxyCountry を固定し、クラウドブラウザのフィンガープリンティングに実際のページをレンダリングさせます

結論:パイプラインの第一級のステップとしてのダウンロード

Puppeteerを使用してファイルをダウンロードすることは、3つの動きに集約されます:Chromeにダウンロードを許可し報告するように指示する(Browser.setDownloadBehavioreventsEnabled)、実際の完了イベントを待つ(Browser.downloadProgress)、そして — クラウドブラウザ上で — 同一オリジンのページ内フェッチを介してバイトを引き戻します。Scrapeless Scraping Browserで実行すると、CDPに関係のない2つの難しい部分(ボット検出と地理的制限)がランタイムに統合され、公開ファイルで動作する同じスクリプトがゲートされた認証済みファイルでも機能します。ダウンロードに至るフォーム駆動フローには、Scraplingクラウドブラウザガイド と組み合わせて、このスクリーピングブラウザ製品ページおよびドキュメントを参照して、完全なCDPインターフェースを確認しましょう。エグレスを固定し、認証ファイルのためにセッションを温め、スリープの代わりに completed を待ちます。


AI駆動のデータパイプラインを構築する準備はできていますか?

私たちのコミュニティに参加して、無料プランを獲得し、ダウンロードおよび抽出パイプラインを構築している開発者とつながりましょう:Discord · Telegram

無料のScraping Browserランタイムを取得し、上記のパターンをワークフローに必要なファイル、地域、ログインに適応させるために、app.scrapeless.comにサインアップしてください。スケールについては料金をご覧ください。


よくある質問

Q: Puppeteerには組み込みのダウンロードメソッドがありますか?
いいえ。page.download() は存在しません。ダウンロードは Browser.setDownloadBehavior で構成し、Browser.downloadWillBegin および Browser.downloadProgress イベントで観察します。

Q: ファイルをダウンロードするのにプロキシは必要ですか?
公衆ファイルには厳密には必要ありません。地域によって制限されているファイルや、住宅IPのみに提供されるファイルについては、接続時に proxyCountry を固定する必要がありますので、サイトが信頼するIPから転送されるようにします。

Q: クラウドブラウザ上で実行しているときにローカルダウンロードディレクトリが空なのはなぜですか?
ファイルがリモートセッションにダウンロードされるためではなく、あなたのマシンにはダウンロードされません。上記のように、page.evaluate() 内でファイルURLをフェッチし、ローカルでbase64をデコードすることでバイトを取得します。

Q: ログインの背後にあるファイルをダウンロードするにはどうすればよいですか?
最初に同じページで認証を行い、その後インページのfetch()を実行してください — セッションのクッキーが含まれているため、ファイルはログインユーザーとしてダウンロードされます。Scrapelessのセッション持続性により、ナビゲーションをまたいでその認証状態が保持されます。

Q: タイムアウトを推測するのではなく、ダウンロードが完了するのをどうやって待つのですか?
Browser.downloadProgressをリッスンし、state === 'completed'のときに解決してください。このイベントにはreceivedBytestotalBytesが含まれているので、実際の進捗も表示できます。

Q: AIエージェントや追加のツールなしでこれを実行できますか?
はい。これは通常のPuppeteerにScrapelessセッション上のCDPを加えたもので、エージェントは必要ありません。SDKは接続を生成するだけです。

Scrapelessでは、適用される法律、規制、およびWebサイトのプライバシーポリシーを厳密に遵守しながら、公開されているデータのみにアクセスします。 このブログのコンテンツは、デモンストレーションのみを目的としており、違法または侵害の活動は含まれません。 このブログまたはサードパーティのリンクからの情報の使用に対するすべての責任を保証せず、放棄します。 スクレイピング活動に従事する前に、法律顧問に相談し、ターゲットウェブサイトの利用規約を確認するか、必要な許可を取得してください。

最も人気のある記事

カタログ