OpenSource-Hub

puppeteer

ライブラリ

puppeteer/puppeteer

Chrome および Firefox ブラウザーを制御する JavaScript API。

概要

Puppeteer は、DevTools プロトコルまたは WebDriver BiDi を介して Chrome または Firefox を制御するハイレベルな API を提供します。デフォルトでヘッドレスモードで動作し、ブラウザの自動化、テスト、Web クローリングに広く使用されています。Node.js をサポートし、スクリーンショット、PDF 生成、フォーム操作などの機能を提供します。

README プレビュー

# Puppeteer\n\n[](https://github.com/puppeteer/puppeteer/actions/workflows/ci.yml)\n[](https://npmjs.org/package/puppeteer)\n\n\n\n> Puppeteer is a JavaScript library which provides a high-level API to control\n> Chrome or Firefox over the\n> [DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/) or [WebDriver BiDi](https://pptr.dev/webdriver-bidi).\n> Puppeteer runs in the headless (no visible UI) by default\n\n## [Get started](https://pptr.dev/docs) | [API](https://pptr.dev/api) | [FAQ](https://pptr.dev/faq) | [Contributing](https://pptr.dev/contributing) | [Troubleshooting](https://pptr.dev/troubleshooting)\n\n## Installation\n\n```bash npm2yarn\nnpm i puppeteer # Downloads compatible Chrome during installation.\nnpm i puppeteer-core # Alternatively, install as a library, without downloading Chrome.\n```\n\n:::note\n\nModern package managers (including npm (see the [RFC](https://github.com/npm/rfcs/pull/868)), pnpm, Yarn, Bun, and Deno) block dependency install scripts by default. If the install script is blocked, Puppeteer will not download the browser during installation, leading to runtime errors.\n\nYou can manually download the required browsers after installation by running:\n\n```bash npm2yarn\nnpx puppeteer browsers install\n```\n\nAlternatively, you can configure your package manager to allow the install script to run (for example, with npm, by adding `"puppeteer"` to `"allowScripts"` in your `package.json`).\n\n:::\n\n## MCP\n\nInstall [`chrome-devtools-mcp`](https://github.com/ChromeDevTools/chrome-devtools-mcp),\na Puppeteer-based MCP server for browser automation and debugging.\n\nPuppeteer also supports the experimental [WebMCP](https://pptr.dev/guides/webmcp) API.\n\n## Example\n\n```ts\nimport puppeteer from 'puppeteer';\n// Or import puppeteer from 'puppeteer-core';\n\n// Launch the browser and open a new blank page.\nconst browser = await puppeteer.launch();\nconst page = await browser.newPage();\n\n// Navigate the page to a UR

FAQ (5)

トラブル対応
localhost で browserWSEndpoint 経由で Puppeteer を Chrome に接続する際に発生する ECONNREFUSED ::1 エラーの修正方法

これは、Node.js 18+ が localhost を IPv6 アドレス ::1 に解決する一方、Chrome の DevTools サーバーは IPv4 の 127.0.0.1 でのみリッスンしているために発生します。http://localhost:9222/json/version から返される webSocketDebuggerUrl には ws://localhost:... が含まれているため、::1:9222 への接続が拒否されます(この問題は Puppeteer 17.0.0 で発生するようになりました)。**回避策:** 接続する前に、エンドポイント内の localhost を 127.0.0.1 に置き換えてください。

const { webSocketDebuggerUrl } = await fetch('http://127.0.0.1:9222/json/version').then(r => r.json());
const browser = await puppeteer.connect({
  browserWSEndpoint: webSocketDebuggerUrl.replace('localhost', '127.0.0.1')
});

あるいは、dns.setDefaultResultOrder('ipv4first') を使用して Node の DNS 解決結果の順序を IPv4 優先に設定するか、--dns-result-order=ipv4first オプションを付けて Node を起動してください。

参照 Issue #8873
トラブル対応
Puppeteerのフルページスクリーンショットで埋め込み動画のサムネイルが空白になるのはなぜですか?また、どうすれば修正できますか?

埋め込みの動画や iframe は遅延読み込みされることが多いため、page.screenshot({ fullPage: true }) がページをキャプチャする前にレンダリングされないことがあります。解決策: まずページをスクロールして遅延読み込みをトリガーし、その後トップにスクロールして戻ってからスクリーンショットを撮影します。

オプション 1 — マウスホイールでスクロールをシミュレートする:

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

for (let i = 0; i < 10; i++) {
  await page.mouse.wheel({ deltaY: 400 });
  await new Promise(resolve => setTimeout(resolve, 1000));
}

await page.evaluate(() => window.scrollTo(0, 0));
await new Promise(resolve => setTimeout(resolve, 3000));

await page.screenshot({ fullPage: true, path: 'thumbnails.png' });

オプション 2 — 各 video/iframe を直接ビュー内にスクロールする:

await page.evaluate(async () => {
  for (const el of document.querySelectorAll('video, iframe')) {
    el.scrollIntoView();
    await new Promise(r => setTimeout(r, 200));
  }
  window.scrollTo(0, 0);
});
await page.screenshot({ path: 'fullpage.png', fullPage: true });

どちらのアプローチも、キャプチャ前に遅延読み込みされるサムネイルを強制的にレンダリングさせます。Puppeteer 22.13.1 で動作を確認済みです。

参照 Issue #12778
トラブル対応
Puppeteer で Dedicated Worker からインターセプトされたリクエストが一切処理されないのはなぜですか(request.respond/continue/abort が効果を持ちません)?

これは Puppeteer v25.12.0 までの既知のバグです。専用ワーカー(dedicated worker)が fetch() を呼び出すと、Chrome はページセッションで Fetch.requestPaused を発行しますが、Network.requestWillBeSent はワーカーセッションで発行します。競合(race)により、Puppeteer は一時停止(paused)イベントをセッション情報なしで保存し、その後 Fetch ドメインを持たないワーカーセッションで Fetch.fulfillRequest(または continue/abort)を送信します。Chrome はこれを 'Fetch.fulfillRequest' wasn't found として拒否し、Puppeteer はそのエラーを握りつぶすため、ワーカーのリクエストは永久にハングします。修正方法: PR #15605 を含むバージョン(25.12.0 以降の main で修正済み)に Puppeteer をアップグレードしてください。例: npm install puppeteer@latest。これはセッションルーティングの競合状態(race condition)であるため、影響を受けるバージョンでは信頼できる回避策はありません。requestWillBeSent がたまたま先に到着した場合にのみリクエストは成功します。

参照 Issue #15497
トラブル対応
Puppeteer の fullPage スクリーンショットで fixed/sticky ヘッダーが誤った位置(中央や下部)に表示されるのはなぜですか?また、どうすれば修正できますか?

原因: page.screenshot({ fullPage: true }) はデフォルトで captureBeyondViewport: true を使用するため、スクロール位置をリセットせずにドキュメント全体をキャプチャします。コード内でページをスクロールしている場合(例えば、遅延読み込みを発動させるためにページの最下部までスクロールする autoScroll ヘルパーなど)、window.scrollY は最下部に留まったままになります。その結果、position: fixed/sticky を持つ要素やスクロールベースの JS が、ページの上部ではなく現在のビューポート位置にレンダリングされてしまいます。

修正方法 1 — キャプチャする前にページ上部へスクロールして戻る:

await autoScroll(page);
await page.evaluate(() => window.scrollTo(0, 0));
await page.waitForTimeout(300); // sticky 要素が落ち着くのを待つ
await page.screenshot({ path: 'example.png', fullPage: true });

修正方法 2 — CSS を注入してヘッダーを absolute 位置に強制するか、完全に非表示にする:

await page.addStyleTag({ content: 'header, .navbar, .sticky-nav { position: absolute !important; }' });
// または完全に削除する場合:
// await page.addStyleTag({ content: 'header { display: none !important; }' });
await page.screenshot({ path: 'example.png', fullPage: true });

オプションとして、page.screenshot({ fullPage: true, captureBeyondViewport: false }) を指定するとキャプチャの動作は変わりますが、スクロール位置をリセットする方法が最も確実な回避策です。

参照 Issue #8191
トラブル対応
なぜ puppeteer.connect() は browserURL のパスプレフィックスを削除し、/t/token/json/version ではなく /json/version を呼び出すのですか?

これは、Puppeteer が new URL('/json/version', browserURL) を使用しているために発生します。WHATWG URL API では、/ で始まるパスは絶対パスであり、ベース URL のパス名全体を置き換えます。この問題は Puppeteer PR #15435 で、既存のパス名に json/version を連結することで修正されています。その修正を含むリリースに puppeteer-core または puppeteer をアップグレードしてください。

一時的な回避策: プレフィックスを保持しながらバージョンエンドポイントを自分で解決し、browserWSEndpoint で接続します。

const versionURL = new URL(browserURL);
versionURL.pathname = versionURL.pathname.replace(/\/?$/, '/') + 'json/version';

const response = await fetch(versionURL.href);
const { webSocketDebuggerUrl } = await response.json();

const browser = await puppeteer.connect({
  browserWSEndpoint: webSocketDebuggerUrl,
});

これにより、http://host:9222/t/token が正しく http://host:9222/t/token/json/version に変換されます。

参照 Issue #15250