the KodeLab

Playwright CLI チュートリアル|Claude Code と組み合わせるブラウザ自動化

11,503 文字 29 分で読めます
Playwright CLI チュートリアル|Claude Code と組み合わせるブラウザ自動化

AI エージェントが Web ページを「見る」必要性はどんどん増えています。フロントエンドを修正したあとの画面確認、ログイン後のデータ取得、繰り返し発生するクリック操作の代行など、以前は Selenium や Puppeteer でプロジェクトを組まないとできなかった作業です。ところが Playwright は、もっともよく使う機能をコマンドラインツール playwright-cli として提供するようになりました。プロジェクト作成も npm 依存のインストールも不要で、一行のコマンドで完了します。本記事では Playwright そのもの、Puppeteer との違い、別途 CLI を作った理由、Playwright MCP との役割分担、そして Claude Code と組み合わせた 4 つの実用シナリオを順に紹介します。

例では Claude Code を使っていますが、同じパターンは他の AI エージェントでも動きます。Claude Desktop の Cowork や Code、Codex、Copilot、Gemini CLI、Antigravity など、使い慣れたものを選んでください。

Playwright の紹介

Playwright は Microsoft チームが 2020 年にオープンソースで公開したブラウザ自動化フレームワークで、Chromium・Firefox・WebKit の 3 大ブラウザエンジンをプログラムから操作でき、E2E テスト、クローリング、スクリーンショット、PDF 生成、フォーム自動入力など幅広い自動化作業に対応します。チームメンバーの多くは Google の Puppeteer 出身で、Microsoft に移ってから設計を一から見直し、Puppeteer の経験を活かしつつ積年の課題を解決しました。

Playwright は JavaScript/TypeScript、Python、Java、.NET の 4 言語に対応し、公式の VS Code 拡張、trace viewer、レポート生成ツールも揃っています。ブラウザ自動化分野でもっとも完成度の高いエコシステムといっていいでしょう。

Playwright と Puppeteer の比較

どちらもブラウザを操作できますが、狙いが少し違います。Puppeteer はもともと Chromium 専用で、API は比較的低レベル。一方 Playwright は最初からクロスブラウザを前提に設計され、「要素が出るまで待つ」「自動リトライ」といった、以前は自分で書く必要があった処理を内部に取り込んでいます。

項目PlaywrightPuppeteer
メンテナーMicrosoftGoogle(Chrome DevTools チーム)
対応ブラウザChromium、Firefox、WebKit主に Chromium(Firefox は実験的)
対応言語JS/TS、Python、Java、.NETJS/TS のみ
自動待機auto-wait を内蔵waitFor を自分で書く必要あり
デバッグTrace Viewer、Inspector、codegen最小限
CLI ツールあり(playwright-cli)公式 CLI なし

結論を一言でいうと、新規プロジェクトで Puppeteer を選ぶ理由はほとんどありません。すでに Puppeteer を使っていて Chromium で問題が起きていないなら、無理に乗り換える必要もありません。

なぜ playwright-cli が必要か

通常の Playwright で「この URL のスクリーンショットを 1 枚ほしい」といった小さな作業をやろうとすると、npm init でプロジェクトを作り、@playwright/test を入れ、.spec.ts を書き、npx playwright test を実行する、という流れになります。PNG 1 枚のためにプロジェクト一式は明らかに重すぎます。

playwright-cli はこうした「一回きりの用事」のために作られたもので、よく使う機能をサブコマンドとして npx playwright <サブコマンド> で呼び出せます。プロジェクトも設定ファイルもテストコードも不要です。

  • playwright screenshot:ページのスクリーンショット(フルページ、ビューポート指定、ダークモード対応)
  • playwright pdf:ページを PDF 化
  • playwright codegen:操作を録画してコードを自動生成
  • playwright open:Playwright 管理下のブラウザを開いて手動で調査
  • playwright install:ブラウザバイナリをダウンロード
  • playwright show-trace:trace ファイルを開いてデバッグ

この設計は AI エージェントにとって特に重要です。エージェントは長期セッションの維持は苦手ですが、「入力と出力が明確なコマンドを実行する」のは得意です。playwright-cli はブラウザ操作を原子的なコマンドに分解しているので、エージェントは 1 コマンド実行して成果物(画像、HTML、JSON)を受け取り、そこから推論を続けられます。

playwright-cli と Playwright MCP の違い

Microsoft にはすでに Playwright MCP(AI エージェントが長時間ブラウザを操作できる Model Context Protocol サーバー)があるのに、なぜさらに CLI が必要なのでしょうか。実はこの 2 つは競合ではなく補完関係にあります。

項目Playwright MCPplaywright-cli
実行モデル常駐サーバー、AI が一歩ずつ呼ぶ一回きりのコマンド、実行したら終了
トークン消費多い(毎ステップで DOM スナップショット)少ない(結果ファイルのみ)
向いている場面探索、試行錯誤、フロー不明確立済みフロー、バッチ、定期実行
スクリプト化難しい(エージェント内で動かす必要)簡単(シェルや cron にそのまま)
再現性中(AI の判断で揺れる)高(コマンド固定で結果も予測可能)

一言で覚えるなら 「探索は MCP、固定化は CLI」。AI エージェントが未知のサイトに初めて触るときは MCP で対話的にフローを探り、確認できたら CLI コマンドや小さなスクリプトに書き起こす。以降はトークンを消費せずに繰り返し実行できます。シナリオ 4 でこのパターンを具体的に示します。

CLI がトークンを節約できる理由

Playwright MCP は一歩ごと(クリック、入力、スクロール)に accessibility tree や DOM スナップショットを AI のコンテキストに返し、次の行動を考えさせます。少し複雑なページなら 1 回のスナップショットで数 KB〜数十 KB、十数ステップ操作すればかなりのトークンが消えてしまいます。

一方 playwright-cli では、AI エージェントが受け取るのは「ファイルパス + stdout 数行」だけ。ページ本体はディスクに残ります。「画面を見たい」ときだけマルチモーダルでスクリーンショットを読み(一度きりのコスト)、「中身を読みたい」ときは小さなスクリプトでページをコンパクトな Markdown や JSON に変換してから AI に渡す。情報を最小の有用単位まで圧縮してから AI に渡す、これがトークン節約の核心です。

Web ページを Markdown に変換して AI に渡す

playwright-cli 自体には --format=md がありませんが、自分で小さなスクリプトを書くのは簡単です。Playwright でページの HTML を取得し、@mozilla/readability で本文を抽出、turndown で Markdown に変換するだけ。十数行で済みます。

// page2md.mjs — ページを取得して本文抽出し、Markdown に変換
// 使い方: node page2md.mjs https://example.com > output.md
import { chromium } from 'playwright';
import { Readability } from '@mozilla/readability';
import { JSDOM } from 'jsdom';
import TurndownService from 'turndown';

const url = process.argv[2];
const browser = await chromium.launch({ channel: 'chrome' });
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle' });

const html = await page.content();
const doc = new JSDOM(html, { url }).window.document;
const article = new Readability(doc).parse();
const md = new TurndownService().turndown(article.content);

console.log(`# ${article.title}\n\n${md}`);
await browser.close();

このスクリプトで出てくる Markdown は生 HTML の 5〜10% 程度のサイズに収まり、広告・ナビ・サイドバーといったノイズは Readability がフィルタしてくれます。AI が読むのは精製されたコンテンツなので、トークン消費も数倍単位で減らせます。リサーチ、資料整理、記事要約などのシナリオに特に向きます。

インストールと初回利用

playwright-cli は Node.js 環境が必要です。Node.js 16 以上(18 以降推奨)がインストール済みか確認してください。すべての例で npx を使うので、あらかじめ npm install する必要はありません。npx が自動でパッケージを取得します。

バージョン確認と基本コマンド

# playwright のバージョンを確認(初回実行時に npm が自動ダウンロード)
npx playwright --version

# 利用可能なサブコマンド一覧
npx playwright --help

ブラウザのインストール

Playwright は自前ビルドの Chromium・Firefox・WebKit バイナリを用意しており(macOS では ~/Library/Caches/ms-playwright/、合計約 600MB)、すべてインストールするには以下を実行します。

# 既定のブラウザ(Chromium、Firefox、WebKit)をすべてインストール
npx playwright install

# Chromium だけをインストール(最小・最もよく使う)
npx playwright install chromium

システムにインストール済みの Chrome を使う

170MB の Chromium を追加でダウンロードしたくない場合、playwright-cli は --channel を指定することでローカルの Chrome や Edge を直接利用できます。以降の例はこの方式をベースにしますが、chromiumfirefoxwebkitmsedge も選択できます。

# システムの Chrome を使う
npx playwright screenshot --channel=chrome https://example.com out.png

# システムの Edge を使う
npx playwright screenshot --channel=msedge https://example.com out.png

# Playwright 同梱の Chromium を使う(先に install が必要)
npx playwright screenshot --browser=chromium https://example.com out.png

実用シナリオ

ここからは 4 つのシナリオで playwright-cli の使い方を紹介します。基本のスクリーンショットから、スクリプト録画、AI エージェントによる自動化、最後にフローをスケジュール実行可能なスクリプトに固定化するところまで。

シナリオ 1:スクリーンショットで UI を検証する

もっとも基本的で、もっとも実用的な使い方です。フロントエンドを修正したあと「画面が想定どおりか」を確認したい。以前はブラウザに切り替えて手動でリロード→目視→スクリーンショットという手順を踏んでいましたが、今は Claude Code に一行のコマンドを実行させるだけで済みます。

下のコマンドは https://example.com を対象にフルページ撮影します(--wait-for-selector の例では https://playwright.dev を使っています)。

# システム Chrome でフルページスクリーンショット
npx playwright screenshot \
  --channel=chrome \
  --full-page \
  https://example.com home.png

# ビューポート指定(iPhone サイズをシミュレート)
npx playwright screenshot \
  --channel=chrome \
  --viewport-size=375,812 \
  --full-page \
  https://example.com home-mobile.png

# 特定要素が出るまで待ってから撮影(ロード途中を撮らないため)
npx playwright screenshot \
  --channel=chrome \
  --wait-for-selector="article" \
  https://playwright.dev home-ready.png

Claude Code との組み合わせ方:CSS を修正したあと、上のコマンドを Claude に実行させ、マルチモーダルでスクリーンショットを読ませて想定どおりかを判断させます。自分でウィンドウを切り替えて再描画を見るより、「注意の切り替え」という一番高価なコストが節約できます。さらに一歩進めるなら、pixelmatch パッケージでベースライン画像と比較し、ビジュアルリグレッションを自動検出することも可能です。

Playwright Inspector
Playwright Inspector

シナリオ 2:codegen で操作を録画してコード化

codegen は Playwright 組み込みのレコーダーで、実行すると 2 つのウィンドウが同時に開きます。通常のブラウザと、操作内容をリアルタイムで Playwright コードに翻訳する Playwright Inspector です。

たとえば https://playwright.dev で「検索ボックスにキーワードを入れる」動作を録画するには:

# レコーダーを起動して playwright.dev を対象に JS ファイルとして出力
npx playwright codegen \
  --channel=chrome \
  --target=javascript \
  -o search.spec.js \
  https://playwright.dev

# Python として出力
npx playwright codegen \
  --channel=chrome \
  --target=python \
  -o search.py \
  https://playwright.dev

# ログイン状態を保存(終了時に cookie が auth.json に書き出される)
npx playwright codegen \
  --channel=chrome \
  --save-storage=auth.json \
  https://playwright.dev

生成されたファイルはおおよそ以下のような形です。Inspector は壊れにくい getByRolegetByText といった意味的ロケーターを自動選択します。

import { test, expect } from '@playwright/test';

test('search playwright docs', async ({ page }) => {
  await page.goto('https://playwright.dev/');
  await page.getByRole('button', { name: 'Search' }).click();
  await page.getByRole('searchbox').fill('screenshot');
  await page.getByRole('link', { name: /Screenshots/ }).first().click();
});

codegen の価値

  • ロケーターを自分で探さなくていい:Playwright が壊れにくい書き方を自動選択し、脆弱な CSS パスを避けてくれます
  • すぐに再生できる:Inspector の Resume を押せばそのままリプレイ検証可能
  • 複数言語出力--target で javascript、python、java、csharp に対応
  • ログイン状態の保持--save-storage / --load-storage で毎回ログインしなくて済む

Web 開発者の自動テストに十分?

多くの開発者が codegen を最初に見たときに抱く疑問です。結論からいうと、Playwright 自体は E2E テストに非常に向きますが、codegen が出すコードは「最初の下書き」としてだけ使うべきです。

録画をそのままテストにすると、アサーション(expect())がない、Page Object 構造がない、A/B テストや動的コンテンツで flaky になりやすい、エラー処理がない、といった問題があります。実務的な正解は、codegen でたたき台を録り、そこから手動(または Claude Code)でリファクタすることです。再利用可能な関数を切り出し、アサーションを足し、テストケースを分割し、待機や失敗処理を追加します。

視点を変えると、codegen は AI との協業に特に向いています。Claude がもっとも苦手なのは「見えないページで正しいロケーターを当てる」こと。codegen はそこを埋めてくれるので、人間が録画し、AI が整形してきれいなテストスイートに仕上げる、という分業が成立します。

よくある利用シーン

  • 新人が Playwright の書き方を学ぶ:クリックしながらコードを見られる
  • 未知サイトの DOM 構造を探る:F12 DevTools より圧倒的に速い
  • QA/PM との協働:テスト手順を再生可能なスクリプトとして共有できる
  • AI のタネにする:ラフな下書きを録画して Claude Code に整えてもらう
  • クローラーの偵察:手動操作を 1 度録画してからバッチ化する

シナリオ 3:既存ブラウザに接続して SNS アカウントを操作

このシナリオは OpenClaw、browser-use、Claude Computer Use に近い考え方です。ユーザーが自分のブラウザで手動ログインし 2FA まで通したあと、AI エージェントが接続して後続の操作を引き継ぎます。パスワードをコードに渡す必要がなく、CAPTCHA も通り越した状態、セッションは普段の利用と完全に同じになるため、ボット検知に引っかかりにくいメリットもあります。

鍵になる技術は Chrome DevTools Protocol(CDP)です。Chrome 起動時に --remote-debugging-port を付けると、Playwright が connectOverCDP で既存のブラウザにアタッチできます。

# デバッグポート付きで Chrome を起動し、専用の user-data ディレクトリを使う
# 起動後、このウィンドウで操作したい SNS に手動ログインしておく
# macOS:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
  --remote-debugging-port=9222 \
  --user-data-dir=/tmp/chrome-agent-profile

# Windows: "C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222 --user-data-dir=C:\tmp\chrome-agent
# Linux: google-chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-agent-profile

あとは Node.js の小さなスクリプトを書いて Claude Code にアタッチ操作を任せるだけです。以下はイメージで、実運用では Claude に要件を伝えて生成させる想定です。

import { chromium } from 'playwright';

// 既存の Chrome(ユーザーが SNS にログイン済み)にアタッチ
const browser = await chromium.connectOverCDP('http://localhost:9222');
const context = browser.contexts()[0];
const page = context.pages()[0];

// あとは通常の Playwright page と同じように操作できる
// 例:自分の投稿のコメントを集計、ブックマーク整理、DM のエクスポート
await page.goto('https://www.threads.net/@your-handle');
const posts = await page.locator('article').allTextContents();
console.log(posts);

// 注意:終了時に browser を close しないこと。ユーザーのブラウザを閉じてしまう
await browser.close();

注意事項と倫理的考慮

  • ボット検知:Facebook、Instagram、X などの大手プラットフォームはマウス軌跡や操作タイミングの監視があります。激しい大量操作は機械と判定されます
  • 利用規約(ToS):多くの SNS は自動化操作を禁止しています。個人用途(自分のデータ整理、エクスポート、管理)に留め、商用乱用や大量配信は避けてください
  • CDP ポートのセキュリティ--remote-debugging-port は既定で localhost にバインドされます。外部に公開しないでください
  • 安全な対象の推奨:監視が比較的緩い Threads、Mastodon、あるいは自分が管理権限を持つ Discord サーバーの管理画面のほうが、FB/IG より格段に安全です

シナリオ 4:フローをスクリプト化して AI トークンを節約する

この例は前述の MCP vs CLI の議論とつながります。探索段階では AI に MCP で対話的にフローを見つけさせ、フローが確定したら AI に Playwright スクリプトとして書き出させ、以降の実行では AI トークンを一切消費しない。AI を「一回きりのコンパイラ」として使う発想です。

「サイトの毎日ヘルスチェック」を例に、スクリーンショット、重要要素の存在確認、レポート出力までの流れを Claude Code に生成させると、だいたい次のようなスクリプトになります。

// daily-check.mjs — 毎日のトップページヘルスチェック
import { chromium } from 'playwright';
import fs from 'node:fs/promises';

const browser = await chromium.launch({ channel: 'chrome' });
const page = await browser.newPage();

const start = Date.now();
await page.goto('https://example.com', { waitUntil: 'networkidle' });
const loadTime = Date.now() - start;

// 重要要素が存在するかを確認
const articleCount = await page.locator('article').count();
const hasHeader = await page.locator('header').isVisible();

// スクリーンショット保存
const today = new Date().toISOString().slice(0, 10);
await page.screenshot({ path: `reports/${today}.png`, fullPage: true });

// JSON レポートを書き出し
const report = { date: today, loadTime, articleCount, hasHeader };
await fs.writeFile(`reports/${today}.json`, JSON.stringify(report, null, 2));
console.log(report);

await browser.close();

あとは cron や GitHub Actions で node daily-check.mjs を毎日実行するだけ。AI を起動する必要はまったくありません。同じパターンは次のような用途にも使えます。

  • 全記事ページに対して OG シェア用スクリーンショットをバッチ生成する
  • 特定ページの改版を監視する(ベースライン画像を保存し、pixelmatch で diff)
  • 管理画面からアクセス数・コメント数を CSV に書き出す
  • 週次でサイト内リンクのヘルスチェックレポートを出す

発想の転換が鍵です。AI の役割が「毎回の実行者」から「一回きりの著者」に変わるのです。書いたコード自体が資産で、100 回実行しても 1 回実行しても同じコスト。フロー自体が変わったときにだけ AI の出番が戻ってきます。

まとめ

Playwright は次世代のブラウザ自動化フレームワークとして、Puppeteer 時代のクロスブラウザ対応や auto-wait の課題を解決しました。playwright-cli はもっともよく使う機能を一行のコマンドに落とし込み、Claude Code のような AI エージェントとの相性が抜群です。Playwright MCP と playwright-cli は置き換え関係ではなく、「探索は MCP、固定化は CLI」という役割分担で使い分けます。

本記事の 4 つのシナリオ(自動スクリーンショット、codegen 録画、既存ブラウザに接続して SNS 操作、フローをスクリプトに固定化)は、どれも開発現場でそのまま使えるものばかりです。Web 開発者にとって Playwright は E2E テストに非常に向きますが、codegen は最初の下書きとして捉え、人間または AI がリファクタして正式なテストスイートに仕上げる、という使い方がベストです。「AI にページを見せる」ことを日常のワークフローに組み込むきっかけになれば幸いです。