Skip to content

非公式本サイトは非公式の日本語ドキュメントであり、Cloudflare 公式サイトではありません。最新情報はdevelopers.cloudflare.comをご確認ください。

Playwright

最終更新 Markdown で表示Agent セットアップ

Playwright は Microsoft が開発したオープンソースパッケージで、ブラウザー自動化ができます。フロントエンドテストの作成、スクリーンショットの取得、ページのクロールによく使われます。

Workers チームは、Cloudflare WorkersBrowser Run で動くように改変した Playwright のバージョン をフォークしています。

このバージョンはオープンソースで、Cloudflare の Playwright フォーク で確認できます。npm パッケージは npmjs から @cloudflare/playwright としてインストールできます。

npm i -D @cloudflare/playwright

Worker で Playwright を使う

この では、todomvc アプリケーションを使い、Cloudflare Worker で Playwright テストを実行します。

手順を省略してすぐに始めたい場合は、下の Deploy to Cloudflare を選びます。

Deploy to Cloudflare

Wrangler の設定ファイルに browser binding があることを確認します。

{
	"$schema": "./node_modules/wrangler/config-schema.json",
	"name": "cloudflare-playwright-example",
	"main": "src/index.ts",
	"workers_dev": true,
	"compatibility_flags": ["nodejs_compat"],
	// Set this to today's date
	"compatibility_date": "2026-09-20",
	"upload_source_maps": true,
	"browser": {
		"binding": "MYBROWSER",
	},
}
"$schema" = "./node_modules/wrangler/config-schema.json"
name = "cloudflare-playwright-example"
main = "src/index.ts"
workers_dev = true
compatibility_flags = [ "nodejs_compat" ]
# Set this to today's date
compatibility_date = "2026-09-20"
upload_source_maps = true

[browser]
binding = "MYBROWSER"

npm パッケージをインストールします。

npm i -D @cloudflare/playwright

Playwright の使い方の例を見ていきます。

スクリーンショットを撮る

ブラウザー自動化で Web ページのスクリーンショットを撮るのは、よくある用途です。このスクリプトは、ブラウザーに https://demo.playwright.dev/todomvc へ移動させ、いくつかの項目を作成し、ページのスクリーンショットを撮り、レスポンスとして画像を返します。

import { launch } from "@cloudflare/playwright";

export default {
	async fetch(request: Request, env: Env) {
		const browser = await launch(env.MYBROWSER);
		const page = await browser.newPage();

		await page.goto("https://demo.playwright.dev/todomvc");

		const TODO_ITEMS = [
			"buy some cheese",
			"feed the cat",
			"book a doctors appointment",
		];

		const newTodo = page.getByPlaceholder("What needs to be done?");
		for (const item of TODO_ITEMS) {
			await newTodo.fill(item);
			await newTodo.press("Enter");
		}

		const img = await page.screenshot();
		await browser.close();

		return new Response(img, {
			headers: {
				"Content-Type": "image/png",
			},
		});
	},
};

Trace

Playwright の Trace は、ワークフロー実行の詳細ログです。ユーザーのクリックやナビゲーション、ページのスクリーンショット、コンソールメッセージなどを記録し、デバッグに使います。開発者は trace.zip ファイルを ローカルで開く か、GUI ツールの Playwright Trace Viewer にアップロードしてデータを調べられます。

Trace ファイルを生成する Worker の例です。

import fs from "fs";
import { launch } from "@cloudflare/playwright";

export default {
	async fetch(request: Request, env: Env) {
		const browser = await launch(env.MYBROWSER);
		const page = await browser.newPage();

		// Start tracing before navigating to the page
		await page.context().tracing.start({ screenshots: true, snapshots: true });

		await page.goto("https://demo.playwright.dev/todomvc");

		const TODO_ITEMS = [
			"buy some cheese",
			"feed the cat",
			"book a doctors appointment",
		];

		const newTodo = page.getByPlaceholder("What needs to be done?");
		for (const item of TODO_ITEMS) {
			await newTodo.fill(item);
			await newTodo.press("Enter");
		}

		// Stop tracing and save the trace to a zip file
		await page.context().tracing.stop({ path: "trace.zip" });
		await browser.close();
		const file = await fs.promises.readFile("trace.zip");

		return new Response(file, {
			status: 200,
			headers: {
				"Content-Type": "application/zip",
			},
		});
	},
};

アサーション

Playwright のよくある用途のひとつがソフトウェアテストです。Playwright の API にはテストアサーション機能があります。詳細は Playwright ドキュメントの Assertions を参照してください。todomvc のデモページに対して expect() テストアサーションを行う Worker の例です。

import { launch } from "@cloudflare/playwright";
import { expect } from "@cloudflare/playwright/test";

export default {
	async fetch(request: Request, env: Env) {
		const browser = await launch(env.MYBROWSER);
		const page = await browser.newPage();

		await page.goto("https://demo.playwright.dev/todomvc");

		const TODO_ITEMS = [
			"buy some cheese",
			"feed the cat",
			"book a doctors appointment",
		];

		const newTodo = page.getByPlaceholder("What needs to be done?");
		for (const item of TODO_ITEMS) {
			await newTodo.fill(item);
			await newTodo.press("Enter");
		}

		await expect(page.getByTestId("todo-title")).toHaveCount(TODO_ITEMS.length);

		await Promise.all(
			TODO_ITEMS.map((value, index) =>
				expect(page.getByTestId("todo-title").nth(index)).toHaveText(value),
			),
		);
	},
};

Storage state

Playwright は storage state に対応しており、Cookie やその他のストレージデータを取得・永続化できます。この例では、storage state を使って Cookie やその他のストレージデータを Workers KV に保存します。

まず、KV 名前空間があることを確認します。次のコマンドで新規作成できます。

npx wrangler kv namespace create KV

次に、Wrangler の設定ファイルに KV 名前空間を追加します。

{
	"name": "storage-state-examples",
	"main": "src/index.ts",
	"compatibility_flags": ["nodejs_compat"],
	// Set this to today's date
	"compatibility_date": "2026-09-20",
	"browser": {
		"binding": "MYBROWSER",
	},
	"kv_namespaces": [
		{
			"binding": "KV",
			"id": "<YOUR-KV-NAMESPACE-ID>",
		},
	],
}
name = "storage-state-examples"
main = "src/index.ts"
compatibility_flags = [ "nodejs_compat" ]
# Set this to today's date
compatibility_date = "2026-09-20"

[browser]
binding = "MYBROWSER"

[[kv_namespaces]]
binding = "KV"
id = "<YOUR-KV-NAMESPACE-ID>"

これで、storage state を使って Cookie やその他のストレージデータを KV に保存できます。

src/index.tsts
// gets persisted storage state from KV or undefined if it does not exist
const storageStateJson = await env.KV.get("storageState");
const storageState = storageStateJson
	? ((await JSON.parse(
			storageStateJson,
		)) as BrowserContextOptions["storageState"])
	: undefined;

await using browser = await launch(env.MYBROWSER);
// creates a new context with storage state persisted in KV
await using context = await browser.newContext({ storageState });

await using page = await context.newPage();

// do some actions on the page that may update client-side storage

// gets updated storage state: cookies, localStorage, and IndexedDB
const updatedStorageState = await context.storageState({ indexedDB: true });

// persists updated storage state in KV
await env.KV.put("storageState", JSON.stringify(updatedStorageState));

Keep Alive

browser.close() を省略すると、ブラウザーインスタンスは開いたままになり、再接続して 再利用 できます。ただし、デフォルトでは 1 分間操作がないと自動で閉じます。ミリ秒単位の keep_alive オプションで、このアイドル時間を最大 10 分まで延長できます。

const browser = await playwright.launch(env.MYBROWSER, { keep_alive: 600000 });

上記を使うと、操作がなくてもブラウザーは最大 10 分間開いたままになります。

セッションの再利用

Browser Run Worker の性能を上げるいちばんの方法は、使い終わったあともブラウザーを開いたままにし、新しいリクエストのたびにそのセッションへ接続して再利用することです。Playwright の browser.close の扱いは Puppeteer と異なります。Playwright では、connect セッションで取得したブラウザーは切断され、launch セッションで取得したブラウザーは閉じます。

import { env } from "cloudflare:workers";
import { acquire, connect } from "@cloudflare/playwright";

async function reuseSameSession() {
	// acquires a new session
	const { sessionId } = await acquire(env.BROWSER);

	for (let i = 0; i < 5; i++) {
		// connects to the session that was previously acquired
		const browser = await connect(env.BROWSER, sessionId);

		// ...

		// this will disconnect the browser from the session, but the session will be kept alive
		await browser.close();
	}
}

カスタム User-Agent を設定する

Playwright でカスタム User-Agent を指定するには、browser.newContext() で新しいブラウザーコンテキストを作るときのオプションに設定します。このコンテキストから作る以降のページは、新しい User-Agent を使います。対象サイトが User-Agent に応じて別のコンテンツを返す場合に便利です。

const context = await browser.newContext({
	userAgent:
		"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
});

ヘッドフルモードでのローカルデバッグ(実験的)

wrangler dev または vite dev でローカル開発すると、Chrome はデフォルトでヘッドレスモードで起動します。Chrome を表示あり(ヘッドフル)で起動するには、X_BROWSER_HEADFUL 環境変数を設定します。

X_BROWSER_HEADFUL=true npx wrangler dev

Cloudflare Vite plugin を使う場合は次のとおりです。

X_BROWSER_HEADFUL=true npx vite dev

ブラウザーウィンドウが開き、Playwright の自動化をリアルタイムで確認できます。ナビゲーション、要素の選択、ページ操作のデバッグがしやすくなります。

セッション管理

ブラウザーセッションの管理を簡単にするため、Playwright API に新しいメソッドを追加しています。

開いているセッションを一覧する

playwright.sessions() は、現在実行中のセッションを一覧します。次のような出力になります。

[
	{
		"connectionId": "2a2246fa-e234-4dc1-8433-87e6cee80145",
		"connectionStartTime": 1711621704607,
		"sessionId": "478f4d7d-e943-40f6-a414-837d3736a1dc",
		"startTime": 1711621703708
	},
	{
		"sessionId": "565e05fb-4d2a-402b-869b-5b65b1381db7",
		"startTime": 1711621703808
	}
]

セッション 478f4d7d-e943-40f6-a414-837d3736a1dc には稼働中の Worker 接続(connectionId=2a2246fa-e234-4dc1-8433-87e6cee80145)があり、セッション 565e05fb-4d2a-402b-869b-5b65b1381db7 は空きです。接続が有効なあいだ、ほかの Worker はそのセッションに接続できません。

最近のセッションを一覧する

playwright.history() は、開いているものと閉じたものの両方を含む最近のセッションを一覧します。現在の利用状況を把握するのに役立ちます。

[
	{
		"closeReason": 2,
		"closeReasonText": "BrowserIdle",
		"endTime": 1711621769485,
		"sessionId": "478f4d7d-e943-40f6-a414-837d3736a1dc",
		"startTime": 1711621703708
	},
	{
		"closeReason": 1,
		"closeReasonText": "NormalClosure",
		"endTime": 1711123501771,
		"sessionId": "2be00a21-9fb6-4bb2-9861-8cd48e40e771",
		"startTime": 1711123430918
	}
]

セッション 2be00a21-9fb6-4bb2-9861-8cd48e40e771 はクライアントが browser.close() で明示的に閉じ、セッション 478f4d7d-e943-40f6-a414-837d3736a1dc は最大アイドル時間に達して閉じました(制限 を参照)。

ダッシュボードでもこの情報を確認できますが、少し遅れることがあります。

現在の上限

playwright.limits() は、現在の上限を一覧します。

{
	"activeSessions": [
		{ "id": "478f4d7d-e943-40f6-a414-837d3736a1dc" },
		{ "id": "565e05fb-4d2a-402b-869b-5b65b1381db7" }
	],
	"allowedBrowserAcquisitions": 1,
	"maxConcurrentSessions": 2,
	"timeUntilNextAllowedBrowserAcquisition": 0
}
  • activeSessions は、現在開いているセッションの ID を一覧します。
  • maxConcurrentSessions は、同時に開けるブラウザー数を定義します。
  • allowedBrowserAcquisitions は、設定されているレート 制限 に照らして、新しいブラウザーセッションを開けるかどうかを示します。
  • timeUntilNextAllowedBrowserAcquisition は、次のブラウザーを起動できるまでの待ち時間です。

Playwright API

Playwright API の全体は、Playwright API ドキュメント にあります。

次の機能はまだ完全には対応していません。現在、対応を進めています。

これは網羅的な一覧ではありません。元の機能セットとの差を埋める作業が進むにつれて、内容はすぐに変わります。完全に対応している機能の細かい最新一覧は、最新のテスト結果 でも確認できます。

役に立ちましたか?