AI自動化

Playwright Mac 入門 2026——ブラウザ自動化を最速で動かすセットアップ

Playwright Mac 入門 2026——ブラウザ自動化を最速で動かすセットアップ

この記事は約 8 分で読めます

📖 目次
  1. 📌 この記事でわかること
  2. 📌 Playwright インストール手順(Mac + Python)
  3. 📌 よくある詰まりポイント3つ
  4. 📌 CDP 経由でブラウザ接続する実装
  5. 📌 launchd で定期実行する(Mac 限定)
  6. 📌 Playwright vs Selenium チェックリスト(2026 時点)
  7. 📌 まとめ

この記事でわかること

Mac に Playwright を入れてブラウザ自動化を動かすまでの手順、詰まりポイント、そして「CDP 経由で既存セッションを流用する」という僕が行き着いた実用構成——この3つを書く。公式チュートリアルをなぞるだけだと実務で詰まるところがあるので、そこを重点的に補足する。


Playwright インストール手順(Mac + Python)

まず環境の話。Python 3.11 以上を前提にしている。3.10 以下だと async 周りで微妙に動きが変わることがあるので注意。

pip install playwright
playwright install chromium

playwright install を実行すると Chromium, Firefox, WebKit のバイナリを全部落とそうとする。全部いらないなら chromium だけ指定するのが正解。容量もインストール時間も減る。

最小動作確認はこれだけ。

from playwright.sync_api import sync_playwright

with sync_playwright() as pw:
    browser = pw.chromium.launch(headless=False)
    page = browser.new_page()
    page.goto("https://example.com")
    print(page.title())
    browser.close()

headless=False にしてブラウザが目の前で開けば成功。この時点で詰まる人は大体 playwright install を忘れてるか、Python の仮想環境が噛み合ってないかのどちらか。


よくある詰まりポイント3つ

headless モードで動かない・要素が取れない

headless=True にすると JavaScript の実行タイミングがズレることがある。特に SPA(React / Vue 系)のページは page.wait_for_load_state("networkidle") を挟まないと要素取得に失敗する。

page.goto("https://example.com")
page.wait_for_load_state("networkidle")
element = page.locator("div.content")

networkidle は厳密には「500ms 間ネットワークリクエストが2件以下の状態が続いた」という定義。SPAではほぼ必須と思っていい。

ログインが毎回切れる

Playwright をデフォルトで使うと、実行のたびに新しいブラウザプロファイルが作られる。つまり毎回ログイン状態がゼロになる。これが地味に面倒で、X や note を自動化しようとするとセッション維持が必須になる。

対策は2通りある。

方法 メリット デメリット
storage_state を保存して再読み込み 手軽 ログイン切れで再取得が必要
CDP 経由で既存ブラウザに接続 日常使いのセッションをそのまま流用 ブラウザを CDP モードで起動する必要あり

僕は後者の CDP 方式に統一した。理由は単純で、Brave を CDP モードで起動しておけば Amazon も X も note も「普段使ってるままのセッション」で繋げられるから。ログインし直しがほぼ発生しない。

timeout エラーが頻発する

ネットワークが遅い環境や、要素の出現に時間がかかるページで TimeoutError が出る。デフォルトのタイムアウトは 30 秒だが、これは page.set_default_timeout(60000) で伸ばせる。

もしくは要素ごとに指定する。

page.locator("button.submit").click(timeout=60000)

むやみに伸ばすのも良くないが、5〜10秒で TimeoutError が出てるなら要素の出方に問題があることが多い。セレクタが正確かどうかを先に疑う方がいい。


CDP 経由でブラウザ接続する実装

ここが僕の構成の核心。Brave を --remote-debugging-port=9222 で起動して、Python からそのブラウザに接続する。

# Brave を CDP モードで起動(launchd か手動で一度だけ)
/Applications/Brave\ Browser.app/Contents/MacOS/Brave\ Browser \
  --remote-debugging-port=9222 \
  --no-first-run \
  --no-default-browser-check

接続コード。

from playwright.sync_api import sync_playwright

with sync_playwright() as pw:
    browser = pw.chromium.connect_over_cdp("http://localhost:9222")
    ctx = browser.contexts[0]  # 既存コンテキストを流用
    page = ctx.new_page()
    page.goto("https://x.com")
    # ← ここで既にログイン済み状態
    browser.close()

connect_over_cdp を使うと、今開いているブラウザにそのまま乗っかれる。セッションが切れても Brave でブラウザを開いて手動ログインするだけで即復旧する。この設計にしてから「今日はセッション切れで自動化失敗してた」という事故がほぼゼロになった。


launchd で定期実行する(Mac 限定)

cron は macOS でスリープ中に止まる。launchd なら起動後に補完実行してくれる。簡単な plist の例。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>com.taito.playwright-autopost</string>
  <key>ProgramArguments</key>
  <array>
    <string>/usr/b​in/python3</string>
    <string>/Users/taito/scripts/autopost.py</string>
  </array>
  <key>StartCalendarInterval</key>
  <dict>
    <key>Hour</key>
    <integer>7</integer>
    <key>Minute</key>
    <integer>0</integer>
  </dict>
</dict>
</plist>

~/Library/LaunchAgents/ に置いて launchctl load するだけ。ログを残したいなら StandardOutPathStandardErrorPath を追加する。これを入れないとエラー原因が全く追えなくなるので入れた方がいい。


Playwright vs Selenium チェックリスト(2026 時点)

どちらを使うか迷っている人向けに整理しておく。

  • [ ] 新規プロジェクト → Playwright 一択。Selenium は負債
  • [ ] Python + async が使えるか → Playwright async API の方が高速(並列でページを開ける)
  • [ ] headless Chrome が必要 → Playwright の Chromium は最新版が自動でついてくる
  • [ ] 既存の Selenium テストがある → 移行コスト次第。急がないなら Playwright に移行推奨
  • [ ] CDP 接続が必要 → Playwright のみ対応。Selenium はできない

Selenium が今も使われる理由はほぼ「昔のコードがそのままある」からだけだと思っている。新しく始めるなら理由なく Playwright でいい。


まとめ

Mac で Playwright を動かすのは pip install playwright && playwright install chromium の2行で終わる。詰まるのはその後——ログイン維持、タイムアウト、headless でのレンダリング待ち、この3点が大半を占める。

CDP 方式は最初の設定だけ少し面倒だが、一度構成を固めてしまえば運用がかなり楽になる。僕は今8本のスクリプトを全部この方式で統一していて、セッション切れ起因の障害がほぼ消えた。

「動く最小構成」から始めて、詰まったら一個ずつ解決する。Playwright はエラーメッセージが比較的親切なので、焦らず読めば大体解決できる。✨



👨‍💻
一ノ瀬泰斗
AI自動化エンジニア / Python個人開発者

Claude Code × Ollama × launchd で SNS・ブログ・KDPを全自動化。実測データと失敗談を軸に、月5万円収益化のリアルな記録を発信中。