テスト

Puppeteer(パペティア)とは?使い方・インストールとv25の変更点【25.16対応】

Puppeteer(パペティア)とは?使い方・インストールとv25の変更点【25.16対応】

Puppeteer(パペティア)は、ChromeとFirefoxをプログラムから操作するNode.jsのライブラリです。開発はGoogleのChromeチームで、ページを開く・クリックする・入力する・スクリーンショットやPDFを保存する、といったブラウザ操作をJavaScriptで書けます。2026年10月28日時点の最新版は、同月22日公開の25.16.0で、5月の25.0.0からはESMのみの配布となり、Node.js 22.12以上が必要です。この記事では、仕組みと読み方、インストール時にChromeが入らない問題、要素の取り方、Playwright・Seleniumとの選び方、古いコードが動かなくなる版ごとの変更を、25.16.0を手元で動かした結果をもとに整理します。

まとめ:Puppeteerの要点

  • PuppeteerはChrome・FirefoxをChrome DevTools Protocol(CDP)かWebDriver BiDiで操るNode.jsライブラリ。ライセンスはApache-2.0で、商用でも無料。
  • 読み方はパペティア。英語で「人形遣い」の意味。
  • npm i puppeteer で本体とChrome for Testingが入る。pnpmなどでinstall scriptが止まるとChromeが入らず、実行時に Could not find Chrome が出るので npx puppeteer browsers install を実行する。
  • 要素の操作は page.locator() が推奨。表示・有効化・位置の安定を自動で待つ。
  • 公式サポート対象はChromeとFirefox。WebKitでの検証にはPlaywrightを選べますが、Safari製品版そのものは操作できません。
  • v25からESMのみ・Node.js 22.12以上・executablePath() がPromiseを返す。page.waitForTimeout() はv22で削除済み。

Puppeteerの定義と仕組み

公式サイトpptr.devは、Puppeteerを「Chrome or FirefoxをDevTools ProtocolかWebDriver BiDi経由で操作する高水準APIを提供するJavaScriptライブラリ」と定義し、既定ではヘッドレス(画面を出さない状態)で動くと説明しています。実際のブラウザエンジンでページを描画してから操作するので、JavaScriptが後から作る要素も扱えます。GitHubのリポジトリ(puppeteer/puppeteer)のスター数は約9.6万(2026年10月28日時点)です。

Puppeteerの読み方と英語の意味

読み方はパペティアです。英語の puppeteer は「人形遣い」の意味で、ブラウザを人形に見立てて糸で操る、という命名です。Chrome for Developersの日本語ページでは見出しが「操り人形師」と訳されています。実験器具のピペッター(pipette)とは関係ありません。

CDPとWebDriver BiDi:2つのプロトコル

Puppeteerは既定ではブラウザとWebSocketでつながり、制御用のプロトコルで命令を送ります。使われるプロトコルはブラウザで決まります。公式のWebDriver BiDiの解説によると、Firefoxは既定でWebDriver BiDi、Chromeは既定でCDPです。ChromeがBiDiに切り替わっていないのは、CDPの機能がまだBiDiで全部使えるわけではないためです。

起動のしかた browser.protocol の値(実測)
launch()(Chrome) cdp
launch({ browser: 'firefox' }) webDriverBiDi
launch({ protocol: 'webDriverBiDi' })(Chrome) webDriverBiDi

BiDiでは、エミュレーション系(page.emulate() など)、カバレッジ、トレース、page.createCDPSession() などが使えません。Firefoxで createCDPSession() を呼ぶと、UnsupportedOperation という例外が出ました(25.16.0・Firefox 158.0.1で確認)。CDPの細かい機能を使うコードは、Chromeで動かす前提で書くことになります。

Puppeteerでできること・向かない用途

  • スクレイピング:SPAのように、JavaScriptの実行後にしか中身が揃わないページからデータを取る。
  • E2Eテスト:ログインから操作、結果の確認までを実際のブラウザで再現する。JestやMochaなどと組み合わせる。
  • スクリーンショット・PDF生成:請求書や帳票のPDF化、画面の見た目の差分確認に使う。PDFの設定とAWS Lambdaでの動かし方はPuppeteerでPDFを生成する方法で詳しく扱っています。
  • ネットワークの傍受と性能計測:リクエストを止める・書き換える、パフォーマンストレースを取る。

向かないのは、静的なHTMLを取るだけの用途です。ブラウザを起動すると、ディスクに数百MBのブラウザを置いたうえでプロセスを立ち上げることになります。fetchで同じHTMLが取れるなら、それで十分です。また、PuppeteerはSafari(WebKit)を操作できません。対応ブラウザの一覧にあるのはChromeとFirefoxだけです。

Puppeteerをインストールする

前提はNode.js 22.12以上です(TypeScriptを使う場合は5.0.1以上)。Node.jsのメンテナンス中のLTSのうち最も新しい版に合わせる方針なので、Node 18や20の環境は25系の動作対象外です。

npm i puppeteer

npm i puppeteer で入るブラウザと容量

本体に加えて、そのPuppeteerの版で動作が保証されたChrome for Testingと、軽量版の chrome-headless-shell がダウンロードされます。保存先はプロジェクトの中ではなく ~/.cache/puppeteer(v19.0.0から)です。公式のインストールガイドはmacOSのダウンロード量を約170MBとしていますが、25.16.0をmacOS(x64)に入れて展開後のディスク使用量を測ると、Chrome for Testing 156.0.8078.47が391MB、chrome-headless-shellが216MBでした。node_modules自体は32MBです。DockerイメージやCIのキャッシュの容量は、この展開後のサイズで見積もってください。

pnpm・Bunで「Could not find Chrome」になる原因と直し方

ブラウザのダウンロードは、依存パッケージのinstall script(postinstall)で行われます。パッケージマネージャの種類・バージョン・設定によっては、このスクリプトが止められ、Chromeが未取得のまま起動に失敗します。pnpm 11.15.1で pnpm add [email protected] を実行すると ERR_PNPM_IGNORED_BUILDS が出てスクリプトは動きませんでした。npm 11.17.0ではスクリプトは動きましたが、allowScripts の対象外だという警告が出ます。ブラウザが無い状態で起動すると、次のエラーになります。

Could not find Chrome (ver. 156.0.8078.47). This can occur if either
 1. you did not perform an installation before running the script (e.g. `npx puppeteer browsers install chrome`) or
 2. your cache path is incorrectly configured (which is: ...).

直し方は2つです。インストール後に npx puppeteer browsers install を実行してブラウザを入れるか、パッケージマネージャにpuppeteerのスクリプト実行を許可します(npmなら package.json の allowScripts に "puppeteer": true を書く、pnpmなら pnpm approve-builds)。CIでは前者のコマンドをビルド手順に1行入れておくと、パッケージマネージャの設定に左右されません。

puppeteerとpuppeteer-coreの違い

項目 puppeteer puppeteer-core
ブラウザ Chrome for Testingを自動で入れる 入れない
起動時の指定 不要 executablePath か channel
設定ファイル・環境変数 読む 読まない
向く場面 開発・学習・一般の自動化 リモートのブラウザに接続/ブラウザを自前で管理

インストール済みのChromeを使うなら puppeteer-core で launch({ channel: 'chrome' }) と書けます。通常の puppeteer パッケージでは、保存先や取得するブラウザを .puppeteerrc.cjs などの設定ファイルか、PUPPETEER_CACHE_DIR・PUPPETEER_SKIP_DOWNLOAD などの環境変数で変えます(設定の解説)。ブラウザのダウンロードに関する設定を変えた場合は、npx puppeteer browsers install を実行し直して適用します。

Puppeteerの使い方:最小コードと基本操作

ページを開いてスクリーンショットとPDFを保存する

25系はESMのみの配布なので、import で書くのが基本です。拡張子を .mjs にするか、package.jsonに "type": "module" を書けば、トップレベルで await が使えます。

// shot.mjs
import puppeteer from 'puppeteer';
import { writeFile } from 'node:fs/promises';

const browser = await puppeteer.launch();   // 既定はヘッドレス
try {
  const page = await browser.newPage();
  await page.goto('https://example.com/');
  console.log(await page.title());         // Example Domain

  await page.screenshot({ path: 'example.png' });
  const pdf = await page.pdf();            // 戻り値は Uint8Array
  await writeFile('example.pdf', pdf);
  const base64 = Buffer.from(pdf).toString('base64');
} finally {
  await browser.close();                   // 途中で失敗してもブラウザを閉じる
}

screenshot() と pdf() の戻り値は、v23からBufferではなくUint8Arrayです。古い記事の pdf.toString('base64') はエラーにならず、37,80,68,70,... という数字の列を返します(実測)。API Gatewayなどに返すコードでは Buffer.from() で包んでください。try〜finally で閉じておくと、goto() が失敗したときにもChromeのプロセスが残りません。なお、従来の require('puppeteer') もNode.js 26.5.0では動きました。Node.js側の機能でESMのパッケージをrequireしているためです。

要素を取る:page.$・page.$$とLocatorの使い分け

API 返すもの 待つか
page.$(sel) 最初の1件の ElementHandle か null 待たない
page.$$(sel) 全件の ElementHandle の配列 待たない
page.$eval(sel, fn) 1件に fn を当てた結果 待たない
page.$$eval(sel, fn) 全件の配列に fn を当てた結果 待たない
page.waitForSelector(sel) 現れた要素 DOMに現れるまで
page.locator(sel) 操作の予約 操作できる状態まで

差が出るのは、JavaScriptが後から要素を作るページです。0.8秒後にリストとボタンを描画するページで試すと、読み込み直後の page.$$eval('#list li', els => els.length) は0でした。一方 page.locator('#more').click() はボタンが現れるまで約1秒待ってからクリックし、成功しています。公式のページ操作ガイドによると、Locatorはクリックや入力の前に、要素が画面内にあること・表示されていること・有効であること・2フレーム続けて位置が動かないことを確かめます。

// 操作は Locator(自動で待つ)
await page.locator('input[name="q"]').fill('puppeteer');
await page.locator('button[type="submit"]').click();

// 取得は、待ってから $$eval でまとめて読む
await page.waitForSelector('.result');
const titles = await page.$$eval('.result h3', els => els.map(e => e.textContent));

クリックや入力はLocator、データの読み出しは waitForSelector で待ってから $$eval、と分けるとタイムアウトに悩まされにくくなります。固定時間の待機は、v22で削除された page.waitForTimeout() の代わりに new Promise(r => setTimeout(r, 1000)) と書けば済みますが、待つ時間をいくら長くしても遅い回線では外れることがあるので、条件で待つ方法を優先してください。

ヘッドレスモードを切り替える

await puppeteer.launch();                     // 新ヘッドレス(v22から既定)
await puppeteer.launch({ headless: 'shell' }); // chrome-headless-shell(軽量)
await puppeteer.launch({ headless: false });   // 画面を表示(デバッグ用)

v22から既定になった新ヘッドレスは、通常のChromeと同じ実装で動きます。公式のヘッドレスモードの解説は、Chromeの全機能が要らず速度を優先する場面に 'shell' を勧めています。どちらのモードでも、User-Agentには HeadlessChrome という文字列が入りました(新ヘッドレスは HeadlessChrome/156.0.0.0、shellは HeadlessChrome/156.0.8078.47)。サイト側はこの文字列だけでヘッドレスと判定できるので、自社サイトのテストでボット対策に弾かれる場合は、許可リストやテスト環境で対応するのが筋です。

Playwright・Seleniumとの違いと選び方

観点 Puppeteer Playwright Selenium
開発 Google(Chromeチーム) Microsoft Seleniumプロジェクト
ブラウザ Chrome・Firefox Chromium・Firefox・WebKit 主要ブラウザ全般
言語 JavaScript・TypeScript JS・Python・Java・.NET Java・Python・C#ほか
テストランナー なし(Jest等と組む) あり(@playwright/test) なし
CDPの直接利用 可(Chrome) 可(Chromium) 一部

新しくE2Eテストを作るなら、Chromium・Firefox・WebKitで検証でき、テストランナーも付くPlaywrightを第一候補にします。テスト資産がJavaやPythonにある、あるいは社内の検証環境がSelenium Gridで組まれているならSeleniumです。Puppeteerを選ぶのは、Node.jsの小さなスクリプトでChromeを動かしたい場合と、CDPを直接使ってネットワークやトレースを細かく扱いたい場合です。PDFやスクリーンショットの生成だけなら、テストランナーの無いPuppeteerの方が依存は少なくて済みます。E2Eテストを CI/CD に組み込む段階で体制づくりに迷う場合は、DevOps・CI/CD導入支援でもご相談を受けています。コードを書かない方式も含めた全体像はBrowser Automationの4つの方式にまとめています。

v20〜v25の変更点:古いコードが動かない理由

Puppeteerはメジャー版のたびに既定の挙動が変わります。検索で見つかるコードがどの版のものかを確かめるのに、次の表を使ってください(日付はCHANGELOGの記載)。

版 主な破壊的変更
v20.0.0(2023-05-02) 同梱ブラウザがChromiumからChrome for Testingへ
v22.0.0(2024-02-05) 新ヘッドレスが既定に/page.waitForTimeout() 削除
v23.0.0(2024-08-07) FirefoxはBiDiが既定に/戻り値がUint8Arrayへ
v24.0.0(2025-01-09) CDP経由のFirefox操作を削除(FirefoxはBiDiのみ)
v25.0.0(2026-05-12) ESMのみ/Node.js 22以上/executablePath() がPromiseに

v25ではほかに、Browser.isConnected()、Puppeteer.product、マウス操作の clickCount オプションも削除されました。手元で console.log(puppeteer.executablePath()) を実行すると、パスではなく Promise { <pending> } が表示されます。await を付け忘れると、そのまま文字列として扱う処理が壊れます。isConnected() を使っていたコードは browser.connected プロパティに書き換えます。

Python・Ruby・GoでPuppeteer相当を使う方法

Puppeteer本体はNode.js専用で、公式の他言語版はありません。Python向けの非公式移植「pyppeteer」は、最後のリリースが2024年2月の2.0.0で、リポジトリのREADMEには「メンテナンスされていない、playwright-pythonを検討してほしい」と書かれています。PythonでChromeを操作するなら、公式にPython版があるPlaywrightを使います。Ruby向けの「puppeteer-ruby」は個人が保守する非公式Gemで、2026年7月に0.53.0が出ています。GoならChromeをCDPで操作するchromedpが同じ位置づけです。

AIエージェントからPuppeteerを使う:chrome-devtools-mcp

pptr.devのトップには、Puppeteerを土台にしたMCPサーバー chrome-devtools-mcp の案内があります。chrome-devtools-mcpのREADMEは、Claude CodeやCursor、Copilotなどのコーディングエージェントを利用先に挙げています。エージェントは、このサーバー経由でChromeを開き、クリックやスクリーンショット、コンソールやネットワークの確認を行います。自分でPuppeteerのコードを書かなくても、エージェントにブラウザを操作させられる形です。導入と設定はChrome DevTools MCPの導入手順と設定で解説しています。

よくある質問

Puppeteerの読み方は?

パペティアです。英語で「人形遣い」を意味する単語で、実験器具のピペッターとは別物です。

Puppeteerは無料で使えますか?

はい。Apache-2.0ライセンスのオープンソースで、商用利用も無料です。

PuppeteerでSafariを操作できますか?

できません。対応はChromeとFirefoxです。WebKitでの表示確認にはPlaywrightを使えます。ただし、Safari製品版そのものの動作確認は別途必要です。

PuppeteerはPythonで使えますか?

公式のPython版はありません。非公式のpyppeteerは保守されていないとREADMEに明記されているため、PythonならPlaywright for Pythonを選びます。

Puppeteerで動かすとボットだと分かりますか?

分かる場合があります。25.16.0では、新ヘッドレスでもUser-Agentに HeadlessChrome が入りました。アクセス先の利用規約やrobots.txtを守り、自社サイトのテストなら許可リストで通すのが確実です。

関連記事

お気に入りに入れた記事の一覧

一創の公式 SNS

X では毎朝の新着記事と IT ニュースの速報を、YouTube・TikTok・Instagram・LinkedIn・Facebook では記事の解説動画を配信しています。

この記事は以下の記事からリンクされています

資料請求

今日のトレンド記事 直近 24 時間で、いつもより多く読まれている記事

  1. 2026.10.29 テックブログ ソニー生命の情報漏洩38.5万件|ログインできない理由、再開状況と窓口の電話番号
  2. 2026.11.03 テックブログ ノジマ不正アクセスで約700万件漏えい:対象確認・窓口と乗っ取り注文を止める実装
  3. 2026.11.03 テックブログ クラブツーリズム不正アクセス:約432万件の対象確認と偽メールの見分け方・流出検知の設計
  4. 2026.11.02 テックブログ サントリーの不正アクセスで約10万人分漏えい|M365のファイル大量ダウンロードを監査ログで調べる手順
  5. 2026.11.02 テックブログ アララの不正アクセス:メール約7,700万件の持ち出しと契約企業が行うAPIキー再設定・代替送信・連名報告

RELATED POSTS 関連記事

目次