Puppeteer は、JavaScript から本物の Chrome を操作するための Google の Node ライブラリです。自動化の処理を書けば、Chrome DevTools Protocol が命令を運び、ブラウザがページを完全に描画してから内容を読み取れます。GitHub では puppeteer/puppeteer に置かれており、Apache-2.0 ライセンス、TypeScript 実装、スター数は約 95.3k(スナップショット取得日に 95,307)です。公式の立ち位置は意図的に狭く、「Chrome(実験的に Firefox)を制御するための JavaScript API」とされています。この一文だけで、何ができて何ができないのかがよく分かります。
私は Puppeteer 24.16.0 を、他のブラウザ自動化ライブラリと同じ検証環境で試しました。対象は、ページネーション付きの静的カタログ、記事ページ、JavaScript で描画されるカタログ、JSON API、500 を返すルート、小さなクローリンググラフ、さらに Books to Scrape と Quotes to Scrape です。結果はきれいで、余計な手間もなく描画できました。ただし、机の上にひとつだけ残った仕事もありました。これはどのヘッドレスブラウザでも同じで、そのギャップを正直に語れるかどうかが、実用的なレビューと単なる宣伝文の分かれ目です。
注目すべきは、再現率の数値以上に別の点でした。JSON エンドポイントからデータを取得するページでは、Puppeteer は DOM を一切スクレイピングせずに 8 件すべてを取得しました。ページ内で fetch を実行し、レスポンスオブジェクトを直接読み取ったのです。これに、ネイティブ描画と正常なスクリーンショット取得が加わる。つまりこのツールは、クローラーではなく、成熟した Chrome レンダラーだということです。この違いは、最初の 1 行を書く前から重要です。
Puppeteer とは何か、そして何と競合するのか
まずはカテゴリ名をはっきりさせましょう。Puppeteer は ブラウザ自動化ライブラリ です。Chrome を起動し、ページを開き、ページ内の JavaScript を実行させ、描画結果を読み取ったりスクリーンショットにしたりできます。HTTP クライアントと HTML パーサーではなくこれを使う理由はひとつ。サーバーが最初に返す空の殻ではなく、スクリプト実行後のページそのものが欲しいからです。
競合相手は、Scrapy のようなクローラーフレームワークや LLM 向け Markdown 変換ツールではなく、Playwright や Selenium のような実ブラウザ系ライブラリです。Puppeteer に 1,000 件の URL を投げて、キュー管理、重複排除、丁寧なスロットリング、データセット出力までやらせようとするなら、それはレンダラーをクローリング問題に持ち込んでいるだけです。各ページは美しく描画してくれますが、オーケストレーションは一切してくれません。(これは欠陥ではなく、守備範囲の違いです。導入前に必ず理解しておくべき最重要ポイントなので、あとで改めて触れます。)

Puppeteer は Google の Chrome チーム発で、Chrome 優先の設計になっているのはそのためです。API もブラウザのデバッグプロトコルに薄くきれいに被せたような作りになっています。年季は十分で、むしろそのおかげで安心して使えるタイプです。必要なメソッドは長く安定しており、ドキュメントも充実、周辺エコシステムも厚いです。
ネイティブ描画と、ページ内 fetch の使い方
実際の使い方を決める重要な挙動が 2 つあるので、結果表から切り出しておきます。
まずはネイティブ描画です。JavaScript で構築されるカタログページは、読み込み後にクライアント側で商品グリッドを生成するタイプですが、8/8 で取得でき、フルページスクリーンショットも保存されました。設定は最小限で、goto の後に対象コンテンツを待つ処理は入れています。公開されている Quotes to Scrape の JS ページも、同じやり方で 10 件すべての引用を返しました。これはテスト用 fixture の結果であり、一般化した描画再現率ではありません。
次に JSON API です。fixture では /api/dynamic-products から商品情報を読み込みました。page.evaluate で同一オリジンの fetch を実行すると、描画済みの行を解析せずに 8 件すべてを取得できました。これは Puppeteer 固有の発見機能ではなく、一般的なブラウザ評価パターンです。エンドポイントとリクエスト契約が分かっているなら抽出をかなり簡単にできますが、認証ヘッダー、実行時トークン、資格情報ポリシー、CORS/CSP、Service Worker、ページネーションなどの条件によっては、アプリの実リクエストは変わります。
最後に押さえておくべきなのは数値ではなく認識です。Puppeteer は成熟した Chrome レンダラーであり、クローラーではありません。この 2 つは両立しますが、後者はレビュー記事でしばしば省かれます。
Puppeteer は Chrome とどう会話するのか

Chrome 上では、Puppeteer は Chrome DevTools Protocol(CDP)を使います。これはブラウザの DevTools が使う、WebSocket 経由の JSON プロトコルです。puppeteer.launch() で Chrome を起動してこの接続を開き、goto、$$eval、screenshot などの呼び出しで、ブラウザ操作を高レベル API として扱えます。Firefox は下で触れる WebDriver BiDi の経路に対応しているため、Puppeteer のすべての操作が CDP 命令に対応するわけではありません。
page.evaluate はページの文脈で関数を実行します。そのため、相対パスの fetch('/api/...') はそのページのオリジンを使い、条件が合えば Cookie やセッション状態も再利用できます。ただし、アプリが生成する認証ヘッダー、リクエストオプション、トークン、Service Worker の動作を自動的に再現するわけではありません。この同一オリジンの fixture では JSON を直接返しましたが、本番のリクエストでは実際の契約内容を確認する必要があります。
また、Puppeteer が重い理由でもあります。各ページは、背後に本物のレンダリングエンジンを持つ実ブラウザのタブです。JavaScript が多いページで正確に動く代わりに、HTTP のみの取得と比べてメモリと起動時間を消費します。無料で描画できるわけではありません。CDP は、その請求書を見える形にしているだけです。
エンジンの話を率直にすると
「Puppeteer は Chrome 専用」という言い方をよく見ますが、今回試したバージョンではそれは正確ではありません。ここを正しく理解すると、比較の見え方が変わります。
| エンジン | Puppeteer 24.16.0 での制御方法 | 今回のテストで使用 |
|---|---|---|
| Chrome | CDP 経由で Chrome 優先 — 既存の自動化がそのまま動く既定経路 | はい |
| Firefox | v23 以降、WebDriver BiDi 経由の対応が文書化済み | いいえ |
| WebKit | 制御対象ではない | — |
Chrome for Developers と Mozilla の両方が、Firefox 対応を発表時に紹介しています。私が使った 24.16.0 は v23 より十分新しいので、「Chrome 専用」という表現は実際の同梱内容を狭く言い過ぎています。WebKit 非対応と、Playwright に比べてまだ若いクロスエンジン戦略こそが、実際の幅の違いです。単純に「1 エンジン対 3 エンジン」ではありません。
Firefox / BiDi の経路はドキュメント化され、このバージョンでも利用可能ですが、私の fixture はそこでは走らせていません。したがって、ここでは機能の存在を報告しているのであって、計測結果を示しているわけではありません。Firefox の描画が重要な対象なら、本番導入前に自分のページで確認してください。エンジンと言語の観点で比較をじっくり見たい人は、Playwright と Puppeteer の比較で同じテストを両方にかけて「どちらを選ぶべきか」を整理しています。ここでは Puppeteer 単体が主役です。
セットアップとインストールの実態:重いのはブラウザ本体
既定の npm install puppeteer は、互換性のある Chrome for Testing ビルドをダウンロードします。この動作は設定でスキップしたり別の場所に向けたりでき、別の実行ファイルを指定することもできます。そのため、バージョン一致は導入方法に左右されます。このインストールで最も重いのはブラウザのダウンロードでした。パッケージマネージャーの監査スナップショットを、永続的なセキュリティ特性として扱うべきではありません。
この自動バンドルは、本当に便利でもあり、本当に容量を食うものでもあります。両面をちゃんと認識しておく価値があります。利点は、互換ブラウザを探したり、手でバージョン固定したりしなくてよいこと。npm install だけで動く組み合わせが手に入ります。欠点は、ブラウザを丸ごとダウンロードするので、特に CI ではディスクと帯域を見積もる必要があることです。キャッシュがないと、毎回の新しい runner でそのコストを払うことになります。
Playwright との違いもここにあります。Playwright はライブラリの導入とブラウザの取得を分けていて、npx playwright install を別途実行してブラウザビルドを取りにいきます。どちらもつらいわけではありませんが、失敗の仕方が違います。Puppeteer は 1 回のコマンドでサイズ感に驚かされることがあり、Playwright は 2 段目を忘れていて驚くことがあります。どちらを使っているのかを把握しておきましょう。
実測結果

すべてのテストは、Node v22.22.3、macOS arm64、Puppeteer 24.16.0、および同梱 Chrome の環境で、ローカルの fixture サーバー(127.0.0.1)と 2 つの公開デモサイトに対して実行しました。各 fixture の正解データは事前に記録しており、再現率は Puppeteer がたまたま出力した内容ではなく、固定された期待値に対して測定しています。
公開リサーチパックには、fixture server、test runner、ground truth が含まれています。依存関係ロックと生の実行サマリーは、厳格なセキュリティ審査で依存ロックデータと環境依存のエンドポイント情報が却下されたため、公開パッケージには含めていません。安全なローカル fixture を再現するには、tools/puppeteer/tests 内で npm install を実行し、その後 node run_puppeteer_material_tests.mjs を走らせて、公開された ground truth と照合してください。公開デモページは変わる可能性があるため、期待件数の確認にはローカル fixture のほうが安定しています。
正確な過去の依存関係を再構成したいなら、未公開の lock を公開証拠として扱うのではなく、ローカルで新しい lockfile を作成して監査してください。
| テスト | 対象 | 結果 |
|---|---|---|
| 静的カタログ + ページネーション | ローカル fixture | 12/12、再現率 1.0 |
| 記事抽出 | ローカル fixture | タイトル + 本文 3/3 段落、ボイラープレート分離済み |
| 動的 JS ページ(ネイティブ描画) | ローカル fixture | 8/8、再現率 1.0、フルページスクリーンショット保存 |
動的 JSON API(ページ内 fetch) | ローカル fixture | 8/8、再現率 1.0、DOM スクレイピングなし |
| HTTP 500 の処理 | ローカル fixture | 500 ステータスを確認可能、例外なし |
| クローリンググラフ(手書き BFS) | ローカル fixture | 12 ページ、深さ {0:1, 1:4, 2:7} |
| Books to Scrape | 公開デモ | 商品 20 件 |
| Quotes JS | 公開デモ | 引用 10 件、ネイティブ描画 |
いくつかは表だけでは伝わりにくいので、補足しておきます。
手作業で書いたページネーションのコードは、期待された 12 件のカタログ項目をすべて回収しました。記事セレクタはタイトルと 3 段落の本文を正しく取得し、その周辺のボイラープレートは DOM 上に残っていました。Puppeteer は描画済み DOM を提供し、どこまでを記事本文とみなすかは、Puppeteer ではなくセレクタロジックが決めています。
テストした HTTP 500 のルートでは、goto は 500 ステータスを確認できるレスポンスオブジェクトを返し、例外は投げませんでした。とはいえ、これはタイムアウト、DNS 障害、ブラウザクラッシュ、フレーム切断、その他のナビゲーションエラーまで面倒を見るという意味ではありません。それらは別途ハンドリングが必要です。
このレビューで一番重要なのはクローリンググラフです。fixture の内部リンクをたどって 12 ページを巡回し、URL を再訪しないよう深さを管理するには、手書きの幅優先探索(BFS) が必要でした。Puppeteer にはビルトインのクローリングキューがないからです。結果として、深さ {0:1, 1:4, 2:7} の 12 ページすべてを見つけられました。つまり BFS 自体はうまく動いたわけですが、その BFS は私が書いたものです。Puppeteer は各ページを描画しただけで、サイトを歩くロジックは自分で実装しました。12 ページなら数十行で済みますが、何千 URL で重複排除、リトライ、礼儀正しい遅延まで必要になると、その数十行はプロジェクトになります。
ひとつ繰り返しておきたい注意点があります。アーティファクトには各テストの実行時間が含まれていますが、これは 1 回だけ、1 台のマシンだけで測った観測です。1 台のノート PC と 1 回の実行だけを根拠に、Puppeteer の速度を他と順位づけするつもりはありません。数値が示しているのは、8 種類のページタイプにまたがる再現率と挙動です。ストップウォッチの比較ではありません。
今回テストしなかったこと
結果を必要以上に広く読まれないよう、テストから外した項目を明示しておきます。したがって、以下は今回の数値の範囲外です。
| テスト外の項目 | 状態 |
|---|---|
| WebDriver BiDi 経由の Firefox | 24.16.0 では文書化済み・利用可能だが、今回は未実施 |
| プロキシとリクエストインターセプト | 未検証。どちらもサポート機能だが今回は未実行 |
| 並列ページのスケール | 小規模実行のみ。実際の同時実行下でのブラウザ群の挙動は未計測 |
| 最新リリースでの再実行 | 24.16.0 をテスト。2026-07-09 時点の npm latest は 25.3.0 で、メジャーバージョンが 1 つ先です。私が使った API(launch、goto、$$eval、screenshot、ページ内 fetch)は 24→25 で安定していますが、正確な数値を信じる前に 25.3.0 で再実行するのが誠実です |
これらは欠点ではありません。1 回の fixture 実行で正直に主張できる範囲の限界です。
長所と短所
長所:
- 明示的なコンテンツ待ちを伴うネイティブ JavaScript 描画。動的 fixture で 8/8、公開デモの 10 件の引用も取得でき、スクリーンショットも保存できた。
- 手書きのページネーションと記事セレクタが、期待された fixture 項目を回収できた。
- ページ内
fetchで、既知の同一オリジン API から 8 件すべてを DOM 解析なしで取得できた。 - テストした HTTP 500 は、例外なしで確認可能なレスポンスとして返ってきた。
- 既定インストールで互換性のある Chrome for Testing をダウンロードし、別実行ファイルの指定やダウンロードスキップも可能。
- CDP ベースの成熟した Chrome 志向 API、深いエコシステム、充実したドキュメント。Apache-2.0。
- 評判以上に広い範囲を持つ。v23 以降、WebDriver BiDi 経由の Firefox 対応が文書化されている。
短所:
- ビルトインのクローリングキュー、データセット書き出し、スロットリングがない。クローリング規模にするには自前コードかラッパーが必要。
- WebKit エンジンがなく、クロスエンジン対応の成熟度は Playwright より若い。
- 実ブラウザの重さがある。Chrome のダウンロードとページごとのメモリコストは、HTTP 専用ツールより高い。
- Node ベースなので、別言語から使うならブリッジの構築と保守が必要。
- 私が実行した版(24.16.0)は npm latest(25.3.0)より 1 メジャー古い。正確な数値を信じる前に現在版で再確認すべき。
どんな人向けか、どんな人は避けるべきか
Node を使っていて、対象ページが Chrome で問題なく描画されるなら、Puppeteer はかなり有力です。多くのサイトはそうです。JavaScript 実行後のページを読んだりスクリーンショットにしたりできる、成熟したフォーカス型ライブラリを求めるなら、これが自然な選択肢になります。動的ページのまとまりをスクレイピングしたい、ページのセッションを使って JSON API を抜きたい、描画結果を証拠として保存したい、という用途にはかなり強いです。Firefox の BiDi 対応も将来的に使えますし、エコシステムが厚いので、遭遇する問題の多くは誰かがすでに経験しています。
一方で、問題が描画ではなくクローリングのオーケストレーションなら、よく考えたほうがいいです。数百、数千の URL を、重複排除・リトライ・レート制限付きで巡回する必要があるなら、Puppeteer だけでは結局クローラーを手で作り直すことになります。それはこのツールにとって適切なレイヤーではありません。もしページがそもそも JavaScript を必要としないなら、ヘッドレスブラウザ自体をやめたほうがいいです。HTTP リクエストとパーサーで取れるなら、本物のブラウザはメモリと初期設定時間を無駄にするだけの高コストな過剰装備です。そして WebKit の再現性や、JavaScript 以外の言語クライアントが必要なら、このツールは軸が違います。
代替手段と Thunderbit の位置づけ
まず率直に言うと、Puppeteer は無料で、Apache-2.0 ライセンス、セルフホスト型です。必要なものはすべて自分で持ちます。ブラウザ群、追加したクローリングコード、そして継続する bot 対策との攻防です。多くのプロジェクトでは、その所有形態こそが適切ですし、権限のあるページを、手元にあるブラウザより安く描画できるマネージドサービスはありません。
オープンソース内で比較するなら、見た目のブランドではなく仕事の内容で比べるのが正解です。特にクローリング規模なら、Crawlee が自然な相棒です。PuppeteerCrawler が、Puppeteer があえて持たないリクエストキュー、データセット、スロットリングを包んでくれるので、描画の強みはそのままに、オーケストレーションを追加できます。LLM パイプライン向けに「きれいな Markdown」が欲しいなら、Crawl4AI は実ブラウザを動かして、その形式で出力します。そもそもブラウザが要らないページなら、Scrapy のような HTTP 優先フレームワークが別カテゴリとして有力です。複数をまとめて検討したいなら、オープンソーススクレイパー総覧 でカテゴリごとの違いを横並びで確認できます。
Thunderbit のようなマネージドサービスは、ブラウザ操作と抽出を API の裏側に隠します。今回はこの Puppeteer fixture では実行していないので、描画、ブロック回避、抽出品質、コストについて同条件の比較はしていません。判断の境界は運用責任の所在です。ブラウザとクローリングのコードを自分で保守するか、そのレイヤーの一部を事業者に任せるか、です。
Puppeteer ではベンダー利用料はかかりませんが、計算資源、帯域、ブラウザ保守、オーケストレーション、運用は自分の責任です。マネージド型は利用量に応じて課金され、その責任の一部を提供側に移します。この実験では、その結果比較までは行っていません。
結論
Node を使っていて、Chrome 優先のブラウザ自動化が必要なら、Puppeteer 24.16.0 は試す価値があります。手作業で用意した fixture では、静的項目 12 件、動的項目 8 件、公開デモの引用 10 件を回収できました。既知の同一オリジン API は page.evaluate 経由で 8 件返し、スクリーンショットも動作し、テストした HTTP 500 は確認可能なままでした。ただし、これらは指定した fixture と旧メジャーバージョンに限った結果であり、一般的な抽出再現率を証明するものではありません。
とはいえ、主張は正確にしましょう。Puppeteer はレンダラーであってクローラーではありません。12 ページの巡回には、ビルトインキューがないため手書きの BFS が必要でした。規模が大きくなると、その不足分は本当の仕事になります。Crawlee に任せるか、自分で仕組みを作る必要があります。Chrome 優先で WebDriver BiDi 経由の Firefox 対応はあるものの WebKit はなく、クロスエンジンの幅を求める道具ではありません。本物のブラウザの重さもあります。そして私は 25.3.0 が最新の時点で 24.16.0 を試しているので、正確な数値を信じる前に現行版で再実行すべきです。この 4 点を理解していれば、Puppeteer は非常に優秀な Chrome 自動化ライブラリです。サイトを丸ごとクローリングしてくれると期待すると、欲しかったはずのクローラーを自分で書くことになります。
Web データ抽出に Thunderbit を試す Get Started Free
FAQ
Puppeteer は JavaScript ページを描画できますか? 追加プラグインは必要ですか?
ネイティブに描画できます。追加プラグインは不要です。今回の動的 fixture では、クライアント側で生成された商品 8 件を再現率 1.0 で取得し、フルページスクリーンショットも保存できました。公開されている Quotes to Scrape の JS ページも同じ方法で 10 件すべてを返しました。単純に goto して、描画済み DOM を読むだけです。Puppeteer は DevTools Protocol 経由で本物の Chrome を動かすため、読み取り前にページ内スクリプトが実際に実行されます。
Puppeteer は HTML を解析せずに JSON API をスクレイピングできますか?
はい、エンドポイントとリクエスト契約が許すなら可能です。page.evaluate はページのオリジンからリクエストを送れ、条件が合えば Cookie も再利用できます。ただし、アプリが付与するヘッダー、トークン、オプション、Service Worker の動作を自動で再現するわけではありません。同一オリジンの fixture では、DOM 解析なしで 8 件すべてを返しました。
Puppeteer は web クローラーですか? いいえ。ブラウザ自動化ライブラリであって、クローラーフレームワークではありません。リクエストキュー、データセット出力、スロットリングがないので、私の 12 ページの巡回(深さ {0:1, 1:4, 2:7})には手書きの幅優先探索が必要でした。これは欠陥ではなく、守備範囲の違いです。クローリング規模で使うなら、Crawlee の PuppeteerCrawler のようなラッパーと組み合わせるのがよいでしょう。Puppeteer が省いているキューやデータセット機構を補ってくれます。
Puppeteer は Chrome 専用ですか? 今はもう違います。CDP 経由で Chrome 優先ではありますが、v23 以降は WebDriver BiDi 経由で Firefox 対応が文書化されていますし、私が試した 24.16.0 はそれより十分新しいです。対応していないのは WebKit であり、クロスエンジン戦略の成熟度も Playwright より若いです。正確な制約は「Chrome 専用」ではなく、そこです。今回は Chrome だけを使ったので、Firefox via BiDi は文書化された機能として述べているだけで、計測したわけではありません。
Puppeteer をインストールすると実際に何がダウンロードされますか?
既定では npm install puppeteer が互換性のある Chrome for Testing ビルドをダウンロードします。ダウンロードはスキップや向き先変更ができ、別の実行ファイルも指定可能なので、バージョン一致は導入方法次第です。特にキャッシュのない CI ランナーでは、ブラウザ分のディスクと帯域を見込んでください。このレビューは 24.16.0 でテストしました。公開時点の最新リリースで、主要な fixture を再実行することをおすすめします。


