※本記事には広告(A8・楽天アフィリエイト)リンクが含まれる場合があります。

「毎回手動でブラウザを操作してテストするのが面倒」「JavaScriptで動くサイトをスクレイピングしたい」「リリース前のチェックを自動化したい」——そんな悩みをすべて解決してくれるのが Playwright です。

Microsoftが開発するPlaywrightは、2020年のリリース以来急速に普及し、2026年現在では個人開発者から大規模チームまで幅広く使われるブラウザ自動化の事実上のスタンダードになっています。Seleniumに代わる新世代のツールとして、Chromium・Firefox・WebKit(Safari相当)の3ブラウザをTypeScript/JavaScript・Python・C#・Javaで操作できます。

この記事では、個人開発者の視点で「Playwrightでできること」を実践コード付きで解説します。E2Eテストのセットアップ、Webスクレイピング、スクリーンショット自動取得、CI(GitHub Actions)への組み込みまで、ゼロから始めて実務に使えるレベルまで持っていきます。

Playwrightとは?Seleniumとの違い

Playwrightの特徴

Playwrightが既存ツールより優れている点は次の4つです:

  • 自動待機(Auto-wait) — 要素が操作可能になるまで自動的に待つため、sleep()や手動の待機処理がほぼ不要
  • ネットワーク傍受 — APIレスポンスのモック・リクエストのブロック・レスポンスの書き換えが可能
  • マルチブラウザ対応 — Chromium/Firefox/WebKitを同一APIで操作できる
  • codegen(コード自動生成) — ブラウザ操作を録画してテストコードを自動生成する強力なデバッグツール

Seleniumからの移行はすべきか?

新規プロジェクトなら迷わずPlaywrightを選ぶべきです。既存のSeleniumプロジェクトについては、テストの規模と移行コストを比較しながら判断するのが現実的です。

Playwrightは特にSPA(React/Vue/Next.js等)や動的に要素が生成されるサイトに強く、個人開発でよく使われるモダンなスタックとの相性が抜群です。

インストールと初期設定

TypeScript/JavaScriptの場合

Node.js 18以上が必要です(推奨はv22)。

# プロジェクトを初期化
npm init -y

# Playwright本体とブラウザをインストール
npm init playwright@latest

インタラクティブなセットアップが始まります。言語(TypeScript推奨)・テストディレクトリ・GitHub Actionsワークフローの生成有無などを選択すると、設定ファイル playwright.config.ts とサンプルテスト tests/example.spec.ts が自動生成されます。

ブラウザ本体のインストールには少し時間がかかります(Chromium・Firefox・WebKitの3つがダウンロードされます)。ディスク容量は約600MBほど確保してください。

Pythonの場合

pip install playwright
playwright install

PythonはTypeScript版より後発ですが、スクレイピング・データ収集用途には十分実用的です。以降の例はTypeScript中心で進めますが、APIの構造はほぼ同じです。

生成された設定ファイルを確認する

// playwright.config.ts(抜粋)
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests',
  fullyParallel: true,           // テストを並列実行
  retries: process.env.CI ? 2 : 0, // CI環境では2回リトライ
  reporter: 'html',              // HTMLレポートを生成
  use: {
    baseURL: 'http://localhost:3000',
    trace: 'on-first-retry',     // 失敗時にトレースを記録
  },
  projects: [
    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
    { name: 'firefox',  use: { ...devices['Desktop Firefox'] } },
    { name: 'webkit',   use: { ...devices['Desktop Safari'] } },
  ],
});

個人開発で手早く動かしたい場合は、projectsをChromiumだけに絞ると起動が速くなります。CIに組み込む前の開発フェーズでは十分です。

広告・楽天アフィリエイト

開発者向けガジェット

PC周辺機器を楽天市場でチェック。

楽天ポイント還元

楽天市場を見る →

広告・楽天アフィリエイト

メカニカルキーボード

打鍵感で選ぶ開発者向けキーボード。

楽天ポイント還元

キーボードを楽天で見る →

codegenでテストコードを自動生成する

Playwrightの目玉機能がこのcodegenです。ブラウザを操作するだけでテストコードが自動生成されます。

npx playwright codegen https://example.com

コマンドを実行するとPlaywright用のブラウザが開き、操作を録画しながらコードを生成するInspectorウィンドウが隣に表示されます。

  • ページを開いて要素をクリックすると page.getByRole('button', { name: '...' }).click() が生成
  • テキストを入力すると page.fill('input[name="..."]', '...') が生成
  • URLが変わると await expect(page).toHaveURL(...) が生成

生成されたコードをそのままファイルに貼り付けて実行すれば、6割程度はそのまま動きます。残り4割は要素セレクタの微調整が必要ですが、ゼロから書くより圧倒的に速い。

スマートフォン表示でコード生成したい場合:

npx playwright codegen --device "iPhone 15" https://example.com

E2Eテストを書く:実践例

ログインフローのテスト

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

test('ログインして管理画面に遷移できる', async ({ page }) => {
  await page.goto('/login');

  // フォームに入力
  await page.fill('input[name="email"]', 'test@example.com');
  await page.fill('input[name="password"]', 'password123');

  // ログインボタンをクリック
  await page.click('button[type="submit"]');

  // ダッシュボードに遷移したことを確認
  await expect(page).toHaveURL('/dashboard');
  await expect(page.locator('h1')).toHaveText('ダッシュボード');
});

動的に生成される要素の待機

SPAでよくある「ボタンを押したら要素が非同期で出てくる」パターン:

test('データ読み込み後に一覧が表示される', async ({ page }) => {
  await page.goto('/items');

  // ローディングスピナーが消えるまで待つ
  await expect(page.locator('.loading-spinner')).not.toBeVisible();

  // 一覧アイテムが3件以上あることを確認
  const items = page.locator('.item-card');
  await expect(items).toHaveCount(3);
});

Playwrightの自動待機はデフォルト5秒でタイムアウトします。APIが遅い場合は { timeout: 15000 } のように個別に延長できます。

APIレスポンスをモックする

外部APIへの依存をなくしてテストを安定させたい場合:

test('APIエラー時にエラーメッセージが表示される', async ({ page }) => {
  // /api/items へのリクエストをインターセプト
  await page.route('/api/items', route =>
    route.fulfill({
      status: 500,
      contentType: 'application/json',
      body: JSON.stringify({ error: 'Internal Server Error' }),
    })
  );

  await page.goto('/items');
  await expect(page.locator('.error-message')).toBeVisible();
  await expect(page.locator('.error-message')).toContainText('エラー');
});

この機能は個人開発ツール(PagePulseのようなWeb監視ツールStatusCraftのようなステータスページ)のテストで特に役立ちます。外部サービスがダウンしていても、テストを安定して実行できます。

広告・楽天アフィリエイト

PCモニター

デュアルディスプレイや高解像度モデルをチェック。

楽天ポイント還元

モニターを楽天で見る →

広告・楽天アフィリエイト

プログラミング技術書

実践寄りの技術書・参考書を探す。

楽天ポイント還元

技術書を楽天で見る →

Webスクレイピング:動的サイトのデータ収集

Playwrightスクレイピングの基本パターン

Puppeteerより簡潔なAPIで同等以上のことができます:

import { chromium } from 'playwright';

(async () => {
  const browser = await chromium.launch({ headless: true });
  const page = await browser.newPage();

  await page.goto('https://example.com/news');

  // ニュース一覧の取得
  const articles = await page.$$eval('.news-item', elements =>
    elements.map(el => ({
      title: el.querySelector('h2')?.textContent?.trim(),
      url:   el.querySelector('a')?.href,
      date:  el.querySelector('.date')?.textContent?.trim(),
    }))
  );

  console.log(JSON.stringify(articles, null, 2));

  await browser.close();
})();

ページネーション対応のスクレイピング

const results = [];
let page_num = 1;

while (true) {
  await page.goto(`https://example.com/list?page=${page_num}`);

  // 現在ページのアイテムを取得
  const items = await page.$$eval('.item', els =>
    els.map(el => el.textContent?.trim())
  );

  if (items.length === 0) break;
  results.push(...items);

  // 次ページボタンがなければ終了
  const nextBtn = page.locator('a[aria-label="次のページ"]');
  if (!(await nextBtn.isVisible())) break;

  page_num++;
  await page.waitForTimeout(1000); // サーバー負荷軽減のため1秒待つ
}

console.log(`取得件数: ${results.length}件`);

注意: スクレイピングを行う際は、対象サイトの利用規約とrobots.txtを必ず確認してください。禁止されているサイトへのスクレイピングは法的問題になる場合があります。

ログイン必須のサイトでの認証維持

ログイン済みのセッション情報(Cookie)を保存して再利用できます:

// 初回:ログインしてセッションを保存
const context = await browser.newContext();
const page = await context.newPage();

await page.goto('/login');
await page.fill('input[name="email"]', 'user@example.com');
await page.fill('input[name="password"]', 'mypassword');
await page.click('button[type="submit"]');
await page.waitForURL('/dashboard');

// セッション状態をファイルに保存
await context.storageState({ path: 'session
        .json' });

// 次回以降:保存済みセッションで起動
const context2 = await browser.newContext({
  storageState: 'session.json',
});
const page2 = await context2.newPage();
await page2.goto('/protected-page'); // ログイン済み状態で開ける

スクリーンショット・PDF生成の自動化

スクリーンショットの取得

// ページ全体のスクリーンショット
await page.screenshot({
  path: 'screenshot-full.png',
  fullPage: true,
});

// 特定要素だけを切り抜く
await page.locator('.chart-container').screenshot({
  path: 'chart.png',
});

// スマートフォンサイズで撮影
const mobile = await browser.newContext({
  ...devices['iPhone 15'],
});
const mobilePage = await mobile.newPage();
await mobilePage.goto('https://example.com');
await mobilePage.screenshot({ path: 'mobile.png' });

この機能を定期実行と組み合わせると、サイトの視覚的変化を記録する監視ツールが作れます。ブラウザエージェント自動化と組み合わせれば、さらに高度な監視が可能です。

PDFとして保存

// Chromiumのみ対応(Headless時)
await page.pdf({
  path: 'report.pdf',
  format: 'A4',
  printBackground: true,
});

レポートの自動生成、請求書の作成、ダッシュボードのスナップショット保存などに活用できます。

GitHub Actionsに組み込む:CI自動テスト

個人開発でも、プッシュするたびに自動でテストが走る仕組みを作っておくと、デプロイ後の不具合を防げます。

# .github/workflows/playwright.yml
name: Playwright Tests

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '22'

      - name: Install dependencies
        run: npm ci

      - name: Install Playwright browsers
        run: npx playwright install --with-deps

      - name: Run Playwright tests
        run: npx playwright test

      - name: Upload test report
        uses: actions/upload-artifact@v4
        if: failure()
        with:
          name: playwright-report
          path: playwright-report/
          retention-days: 7

ポイントは--with-depsフラグです。Ubuntu環境でブラウザが依存するライブラリも合わせてインストールされます。これを忘れるとCIでブラウザが起動しません。

テスト失敗時にHTMLレポートをアーティファクトとして保存しているので、失敗の原因をビジュアルで確認できます。GitHub ActionsでのCI/CD全般については別記事でも詳しく解説しています。

広告・楽天アフィリエイト

ガジェット・オーディオ

イヤホン・便利ガジェットをポイント還元で。

楽天ポイント還元

ガジェットを楽天で見る →

実践的なTips:ハマりポイントと解決策

要素が見つからないエラー(Locator Error)

最もよくあるエラーです。原因は主に3つ:

  • 要素が非同期で生成されるawait expect(locator).toBeVisible()で待つ
  • セレクタが間違っている → codegenで実際の要素セレクタを確認する
  • iframeの中にあるpage.frameLocator('iframe').locator('...')を使う

CI環境でタイムアウトが多発する

CIマシンはローカルより遅いため、グローバルなタイムアウトを延長します:

// playwright.config.ts
export default defineConfig({
  timeout: 30000,          // テスト1件あたり30秒
  expect: {
    timeout: 10000,        // assertionのタイムアウト10秒
  },
});

        

ヘッドレスとヘッドありを切り替える

const browser = await chromium.launch({
  headless: process.env.CI === 'true',  // CIではヘッドレス、ローカルでは表示
});

デバッグ時はheadless: falseにして実際の動作を目視確認するのが最速の方法です。

テスト間の状態分離

// 各テストで独立したブラウザコンテキストを使う
test.beforeEach(async ({ page }) => {
  // 各テスト前にローカルストレージをクリア
  await page.evaluate(() => localStorage.clear());
});

AIとPlaywrightを組み合わせた次世代自動化

2026年現在、PlaywrightをAIエージェントのブラウザ操作ツールとして使うパターンが急速に普及しています。

MCPサーバーとPlaywrightを組み合わせると、「このサイトを開いて〇〇のデータを取ってきて」という自然言語指示でブラウザ操作が実行できます。MCP(Model Context Protocol)サーバーの作り方と組み合わせることで、Claudeなどの LLMに直接ブラウザ操作権限を与えた自律エージェントが作れます。

また、QuickSummaryのようなAI要約Chrome拡張の品質テストにも、Playwrightによる自動化は有効です。拡張機能をChromiumに読み込ませてE2Eテストを実行する方法も公式にサポートされています。

まとめ:Playwrightは個人開発の必須ツール

Playwrightが個人開発者に刺さる理由を整理すると:

  • codegenで学習コストが低い — テストを書いたことがない人でも、録画→コード生成で始められる
  • 自動待機で安定したテスト — SPA・動的サイトでも壊れにくいテストが書ける
  • スクレイピング・スクリーンショット・PDFまで1ツールで完結
  • GitHub Actionsに無料で統合できる — CIの無料枠内で十分動く

「テスト書くのは大企業がやること」と思っていた個人開発者も、Playwrightなら手軽に始められます。まずはcodegenで自分のサービスの操作を録画して、テストコードを見てみる——そこから始めれば十分です。

「動いていると思っていたら壊れていた」を防ぐ一番の投資は、自動テストです。あなたの個人開発をより堅牢にするために、今日からPlaywrightを試してみてください。

🎭 自動テストで個人開発をもっと強くしよう

Playwrightと組み合わせると効果的なツール:Web監視ならPagePulseでサイト変化を検知、ステータス管理はStatusCraftでユーザーに状況を伝える。CI/CDの基礎はGitHub Actionsガイドで学べます。