この記事でわかること
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/bin/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 するだけ。ログを残したいなら StandardOutPath と StandardErrorPath を追加する。これを入れないとエラー原因が全く追えなくなるので入れた方がいい。
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 はエラーメッセージが比較的親切なので、焦らず読めば大体解決できる。✨