CC for Biz
2026/05/05Claude Code
Skills活用ツール比較AI活用

ブラウザ自動化|Playwrightとbrowser-use比較

ブラウザ自動化|Playwrightとbrowser-use比較

「browser-use」と「Playwright」、ブラウザ自動化のツール選定で迷っている方は多いのではないでしょうか。私自身、AIネイティブを謳う browser-use CLI 2.0 を1ヶ月運用した結果、突然動かなくなり、Playwright Python SDK へ全面的に書き直すという痛い経験をしました。この記事では、その過程で得た「ツールを使い分ける」という結論と、移行で見つかった具体的なノウハウを共有します。

1ヶ月前、なぜ私は browser-use CLI 2.0 を選んだのか

2026年4月の段階で、私は note への記事自動投稿スキルを構築する必要がありました。複数の候補を比較した結果、選んだのは browser-use CLI 2.0。当時、AIネイティブなブラウザ自動化ツールとして高い評価を受けていたものです。

採用理由はシンプルでした。

  • 自然言語で「note にログインして、タイトルを入力して、本文を貼り付けて」と指示できる
  • サイトの DOM 変化に LLM が追従するため、セレクタの保守が不要
  • 未知サイトでも「とりあえずやってみて」が通用する
  • 私の判断軸である「複雑さの排除」に合致していた

結果として、1325行の Python スクリプトを書き上げました。ログイン、タイトル入力、本文挿入、サムネイルアップロード、挿絵2枚、CTAバナー3枚、下書き保存まで、フル機能で動かすコードです。本文中には <!-- IMAGE: --><!-- CTA: top|middle|bottom --> といったマーカーを埋め込み、画像挿入位置をテキストレベルで指定できる設計にしました。

1ヶ月、数本の記事はちゃんと動きました。問題が起きるまでは。

突然壊れた日の症状 — synthetic event が弾かれる

2026年5月4日、note への記事投稿が突如機能しなくなりました。症状は次の通りです。

  • 本文挿入を担う set_body() 関数が3つの戦略すべてで失敗
  • 1つ目: 合成 ClipboardEvent を発火 → 失敗
  • 2つ目: document.execCommand('insertHTML') を直接呼ぶ → 失敗
  • 3つ目: innerHTML 直接書き換え + input イベント発火 → 失敗
  • 結果として、タイトルとサムネイルだけ入った「本文0文字」の空ドラフトが5件以上量産
  • 挿絵もCTAバナーも全滅

この症状にはどこか既視感がありました。記憶を辿ると、過去に Substack のエディタで同じ問題に遭遇していたのです。Substack には「pbcopy + Cmd+V 経由でしか動かない」というメモが残っていました。それと同じ事象が note にも適用されたタイミングだった、というのが結論です。

原因は note のエディタが ProseMirror ベースに移行した(または既存の検証強化が効いた)こと。ProseMirror は現代的なリッチテキストエディタフレームワークで、note・Notion・Substack・Linear・Confluence などで採用されています。このフレームワークは、JavaScript で生成された 合成イベント(synthetic event)を「本物のユーザー操作ではない」と判定して黙殺する仕様を持っているのです。

browser-use から Playwright への移行経緯(2026年4月〜5月のタイムライン)

4時間の試行錯誤と claude-in-chrome MCP での部分成功

仮説検証に4時間以上かけました。順番に潰していった可能性は次のようなものです。

  • プロセス競合? → 全プロセスをクリーンアップしても症状変わらず
  • note の仕様変更? → 確実にエディタ側の挙動変更があった
  • JavaScript injection の根本問題? → これが正解だった

仮説2と3を切り分けるため、寄り道として claude-in-chrome MCP を試しました。これは Anthropic 公式の Chrome 拡張ベースの MCP で、私が普段使っている Chrome をそのまま操作できます。ヘッドレスブラウザではなく、実際のユーザーセッションで動くため、本物の userActivation コンテキストを持っているはずでした。

結果は半分成功、半分失敗でした。

  • 本文挿入は成功: document.execCommand('insertHTML', false, html) が一発で通り、4650文字が入った
  • file_upload は失敗: Desktop / Downloads / Home の全パスで -32000 "Not allowed" エラー

原因は claude-in-chrome MCP のサンドボックス層が file_upload を弾いていたことでした。本文とタイトルは入るのに、画像(サムネ・挿絵・CTAバナー)が一切入らない。結局、画像配置だけ手動で行う必要があり、自動化としては未完成のまま停滞しました。

ただ、この4時間は無駄ではありませんでした。「本物のキーイベント・本物の userActivation があれば execCommand は通る」という事実が確認できたからです。これが後の Playwright 移行の判断材料になりました。

抜本調査の結果 — Playwright が推奨される4つの理由

停滞を脱するために、私はいったん手を止めて30分ほど業界調査をしました。「これは私のコードの問題ではなく、ツールの問題かもしれない」と疑い直したのです。結果、いくつかの重要なファクトが見つかりました。

① browser-use 自身が Playwright を捨てて CDP 直叩きに移行している

browser-use の公式ブログ「Closer to the Metal」で、2025年末に Playwright ラッパー層を捨てて Chrome DevTools Protocol(CDP)を直接叩くアーキテクチャに移行したと宣言されています。理由は、Playwright のラッパー層がパフォーマンスと信頼性のボトルネックになっていたから。これはつまり「AIネイティブツールも結局、原始的な CDP に戻っていく」という業界トレンドの表れです。

② ProseMirror 突破の確定解が存在する

「How I Defeated ProseMirror」という海外の検証記事で、document.execCommand('insertText', false, text) だけは beforeinput イベントをネイティブに発火させるため、note・Substack・Notion・Linear・Confluence のすべてで動く確定解だと示されています。ただしこれを userActivation を持った状態で呼ぶ必要があり、合成イベント由来の呼び出しでは弾かれます。

③ Playwright の set_input_files() は CDP 直叩き

Playwright の locator.set_input_files() は、内部で DOM.setFileInputFiles という CDP コマンドを直接発行します。ラッパー層を経由しないため、ファイルアップロードの信頼性が高い。これが claude-in-chrome MCP で失敗していた file_upload の代替になります。

④ Playwright のキーボードイベントはハードウェアレベル相当

page.keyboard.press('Meta+V') は、CDP の Input.dispatchKeyEvent を呼びます。これはブラウザから見て「ハードウェアキーボードからの入力」とほぼ同等に扱われ、userActivation を獲得した状態でクリップボード paste を実行できます。これが ProseMirror の権限ゲートを通過する鍵でした。

調査結果として、推奨ツールの優先順位は以下のように整理されました。

  • 第1候補: Playwright Python SDK 直叩き(同じサイトを毎日叩く決定論タスク向け)
  • 第2候補: Playwright MCP(Claude Code から保険的に呼ぶ用途、GitHub 32k stars)
  • 第3候補: Chrome DevTools MCP(upload_file ツールを持つ代替、GitHub 38.1k stars)

Playwright で書き直した結果と発見した7つのノウハウ

2026年5月5日、note 投稿スクリプトを Playwright Python SDK で書き直しました。結果、コード行数は 1325行 → 1037行(22%削減)。削減率が控えめなのは、各非自明判断の理由をドキュメント文字列で残したからで、実態のロジックは劇的にシンプルになりました。3〜4戦略の fallback チェーンが、単一メソッドに集約されています。

テスト結果は全項目 PASS。ログイン(永続プロファイル)、本文挿入(4544文字)、サムネアップロード(クロップ保存込み)、挿絵2枚、CTAバナー3枚、全リンク検証、すべて動きました。

移行作業の中で見つかった、ドキュメントには載っていない7つのノウハウを共有します。

Playwright 移行で発見した7つの非自明ノウハウ一覧

page.expect_file_chooser() が正解

note のファイル input は React popover の中で動的に生成されます。静的な locator.set_input_files ではセレクタが捕捉できません。代わりに、ネイティブのファイル選択ダイアログを横取りする expect_file_chooser を使います。

with page.expect_file_chooser() as fc_info:
    page.locator('button:has-text("画像を追加")').click()
file_chooser = fc_info.value
file_chooser.set_files('/path/to/image.png')

② クリップボード paste で ProseMirror を突破する

本文挿入は、HTMLをクリップボードに書き込んだ後、Meta+V でペーストするのが確実です。Playwright のキーボードイベントが userActivation を獲得しているため、ProseMirror の権限ゲートを通過します。

context.grant_permissions(
    ['clipboard-write'],
    origin='https://editor.note.com'
)
page.evaluate('''
    navigator.clipboard.write([
        new ClipboardItem({"text/html": new Blob([html], {type: "text/html"})})
    ])
''')
page.keyboard.press('Meta+V')

③ 物理 mouse.click(x, y) が JS の Range/Selection より確実

ProseMirror の reconciler は、JavaScript で設定した Selection を黙殺する場面があります。要素の bounding-rect を取得して右端を物理クリックし、その後 End キーを押すことで、確実にカーソルを末尾に配置できます。

④ figure id を Set で diff 追跡する

挿入した画像の figure 要素を特定したいとき、locator('figure').last は DOM 順で「最後の figure」を返しますが、後続の挿入で位置が変わると別物を指してしまいます。挿入の前後で Set<figure id> を取得して差分を取れば、新規追加された figure を確実に特定できます。

⑤ 属性セレクタ figure[id="..."] を使う

CSS 形式の figure#fig-abc はハイフンや特殊文字のエスケープ問題が起きます。属性セレクタに切り替えれば、id にどんな文字が入っていても安全に参照できます。

⑥ 検証パスを最後に必ず通す

初回の CTA リンク設定で、リンクが silently fail する場面が時々あります。最終スキャンで figcaption に「¥6,000」のようなキャプション文字列が含まれているかを確認し、欠けていれば再付与する検証パスを入れておくと、自動化の信頼性が一段上がります。

⑦ note のリンクUIは textarea + 適用ボタン

意外な落とし穴ですが、note のリンク挿入UIは <input> ではありません。<textarea placeholder="https://"> に URL を入力し、隣の「適用」ボタンをクリックする構造です。Enter キーでは確定しないので、ボタンクリックを忘れずに。

結論 — ツールを捨てるのではなく、サイト別に使い分ける

ここで重要なのは、browser-use を捨てるべきではないということです。私が下した結論は「ツールを使い分ける」というアーキテクチャ判断でした。

Playwright と browser-use 2.0 の使い分け基準(タスク特性別の判断軸)

NGパターン: 1スクリプト内で混在

browser-use と Playwright を同じスクリプトで併用すると、セッション管理が複雑化し、デバッグ地獄に陥ります。プロファイルの取り合い・cookie の扱い・並列実行時のロック競合など、解決すべき問題が指数的に増えていきます。

OKパターン: スキル単位でツールを選ぶ

私の現状のスキル構成は次のようになっています。

  • note 投稿スキル: Playwright(リッチエディタ + ファイルアップロード)
  • Substack 投稿スキル: Playwright(同様の理由、書き直し検討中)
  • X 投稿スキル: browser-use(通常フォーム、自然言語指示で十分)
  • ココナラ出品管理スキル: browser-use(フォーム + 通常UI)
  • 業種特化スクレイピング: browser-use(未知サイトへの AI 判断が強み)

判断軸 — Playwright を選ぶ場面

  • React / ProseMirror 系のリッチエディタ操作(note / Substack / Notion / Linear / Confluence / Medium / Ghost など)
  • Hidden file input への画像・動画アップロード
  • ネイティブキーイベントを要求する操作(クリップボード paste など)
  • 同じサイトを毎日叩く決定論タスク(コスト重視)

判断軸 — browser-use 2.0 を選ぶ場面

  • 通常フォーム・ボタン操作(user activation のゲートがない)
  • データ抽出・スクレイピング(DOM 構造が頻繁に変わる)
  • 未知サイトの探索(事前にセレクタを書けない)
  • DOM 変化への自己修復が必要
  • 自然言語で「○○して××して」と複雑指示を出したい

1ヶ月前の判断は間違っていなかった

browser-use 2.0 自体は依然として優秀なツールです。失敗の本質は「現代的リッチエディタには合成イベントが効かない」というエッジケース知見が抜けていただけ。スキル全体の再構築は不要で、note まわりだけ書き直せば済みました。「全部捨ててやり直し」より「壊れた部分だけ書き直し」のほうが、健全な投資判断だと考えています。

業界全体の構造変化 — AI ネイティブツールの限界と回帰

この経験から、ブラウザ自動化ツール業界の構造変化が見えてきました。

browser-use は元々 Playwright + LLM のラッパーでした。それが2025年末に Playwright を捨てて CDP 直叩きに移行しました。背景には、ラッパー層が信頼性とパフォーマンスの両方でボトルネックになっていたという現実があります。

競合となる Stagehand v3、Skyvern、Computer Use Agent のような AI ネイティブツール群は、未知サイトを横断するタスクには強いものの、同じサイトを反復する用途では「LLM 課金 + 推論遅延」がオーバースペックになります。

一方で Playwright は Microsoft 公式・無料・Apache 2.0 ライセンス。2026年5月時点の業界調査でも信頼性スコア 92% という高水準です。AI ネイティブの「魔法」が剥がれた後、結局 deterministic(決定論的)なツールが残るというのが、この1年で起きていることだと感じています。

Claude Code Skills を活用した自動化全般の設計指針については、こちらの記事で詳しく整理しています。

Claude Code Skillsの作り方と使い方|業務自動化の実践ガイド【2026年版】
Claude CodeClaude Code Skillsの作り方と使い方|業務自動化の実践ガイド【2026年版】

これから始める人への即実行アドバイス

最後に、ブラウザ自動化を始める方・既に運用している方へ、具体的な行動指針を共有します。

既に browser-use を使っている方へ

  • note / Substack / Notion / Linear などのリッチエディタを叩いている箇所を特定する
  • その箇所だけ Playwright Python SDK に書き直す
  • 他の部分(X、通常フォーム、スクレイピング)は browser-use を継続して問題ない

これから始める方へ

  • 同じサイトを反復するタスクなら、Playwright Python SDK を最初から選ぶ
  • セットアップは pip install playwright && playwright install chromium で完了
  • セレクタは playwright codegen <URL> でブラウザ操作を録画して自動生成できる
  • ログイン状態の維持は launch_persistent_context でプロファイルを永続化する
  • リッチエディタへの本文挿入は execCommand insertText 経路を最初から組み込む

4つのメタ学習 — ツール選定で繰り返したくない判断ミス

この一連の試行錯誤から得たメタな教訓を、最後に整理しておきます。

① ツール選定は「実装でぶつかってから」変える

1ヶ月前の判断時点で、ProseMirror 系エディタのエッジケースは予測できませんでした。新しいツールには必ず「使ってみないと分からないエッジケース」が存在します。事前の完璧な選定を目指すより、ぶつかってから抜本調査して書き直すほうが、結果的にコストが低いことが多いです。

② AI ネイティブツールにも限界がある

browser-use の自己修復能力は強力です。しかし、user activation を必要とするフレームワーク(React の合成イベント検証、ProseMirror の権限ゲート、Web Authentication API など)には届きません。「LLM が解釈する層」と「ブラウザが実行する層」の間に、原理的な隙間が存在することを覚えておくべきです。

③ 抜本調査は早めに

4時間以上のデバッグ前に、Playwright との比較調査をすべきでした。「これは私のコードの問題ではなく、ツールの問題かもしれない」と疑う判断が、私は遅れました。30分試して動かなかったら、その後の3.5時間は同じ場所で堂々巡りになる可能性が高いです。手を止めて業界調査に振り直す勇気が必要です。

④ AI ネイティブと deterministic を意識的に使い分ける

  • 同じサイトを毎日叩く → deterministic(Playwright)
  • 未知サイトを探索する → AI ネイティブ(browser-use)

この使い分けを意識的に行うと、トークン課金と信頼性の両方を最適化できます。「全部 AI で」「全部スクリプトで」のどちらかに振り切るのではなく、タスク特性に応じて適材適所で配置するのが、現時点での最適解だと考えています。

まとめ

browser-use CLI 2.0 から Playwright Python SDK への部分的な移行を通じて、私が学んだことは「ツールを捨てるのではなく、サイト別に使い分ける」というアーキテクチャ判断でした。リッチエディタ + ファイルアップロードは Playwright、通常フォーム + スクレイピング + 未知サイトは browser-use、という棲み分けが現時点の最適解です。

1ヶ月前の判断は間違っていませんでした。間違っていたのは「すべてのサイトに同じツールが効く」という前提です。AI ネイティブと deterministic、それぞれの強みが活きる場面を意識的に選ぶことで、自動化スキルの保守コストと信頼性を両立できます。

ブラウザ自動化ツールの選定で迷っている方は、まず「対象サイトのエディタが ProseMirror か」「ファイルアップロードが Hidden input か」を確認するところから始めてみてください。それだけで、最初の選択ミスを大きく減らせるはずです。

本気のAI活用、その最初の一歩 — AI業務効率化のスポット相談

「AIで何ができるか分からない」「興味はあるが業務に活かせていない」
── そんな方は、まず1回お話ししてみませんか。
→ AI業務効率化のスポット相談(30分 ¥6,000〜・初回限定)

← 記事一覧に戻る

御社の業務に合わせたClaude Code導入支援

「AIツールを導入したが、現場で使われない」を終わらせる。
業務課題のヒアリングから設計、ハンズオン実践、運用定着まで一貫して支援します。

無料AI活用診断を受けるサービス詳細を見る →
© 2025 Fyve Inc. All rights reserved.