投稿

ブラウザ操作を AI に任せるとき、どの層に投資すると速いか

ブラウザ操作を AI に任せるとき、どの層に投資すると速いか

まとめ

  • 決まった手順を繰り返すなら、Playwright のスクリプトが最も速く安い。実測で 1 タスク 0.16〜0.87 秒、LLM の呼び出しは 0 回だった。
  • AI にブラウザを操作させるツールの差は、ドライバの性能ではなくモデルの往復回数で決まる。Playwright 系の browse は、生の CDP を使う browser-use より 2 倍遅かった。
  • 探索は browser-use、固まった手順はスクリプト、夜間の反復はそのスクリプト。この 3 層に分けると、どの層も無駄にならない。

測ったこと

自宅の Ubuntu で、ブラウザ操作を AI に任せる手段を 3 つ用意した。

1 つは Playwright のスクリプト。モデルを介さず、決め打ちのセレクタで操作する。 2 つめが browser-use 1.0.2。モデルが Python を書き、生の CDP で操作する。MCP 経由なら追加の LLM は要らない。 3 つめが browse 0.0.16。こちらもモデルがコードを書くが、実行は Playwright 系のドライバ(Patchright)で、専用の拡張機能を入れたブラウザに繋ぐ。

テスト用に、ローカルで 5 ページのアプリを用意した。 JS で 800ms 後に描画される一覧、JS で動くフォーム、3 ページの遷移、cookie で守られたログイン、3 秒かかる応答。

AI に任せる 2 つは、同じモデル(DeepSeek V4.1 Flash)、同じプロンプト、同じデータで、5 ケースを 3 回ずつ回した。 合計 30 回。ブラウザはどちらも専用プロファイルの headless Chrome で、常用のプロファイルには触れていない。

同じタスクを 3 つの手段で測った結果

表1: 同一タスクの所要時間

ケース Playwright スクリプト browser-use browse 呼び出し回数(browser-use / browse)
JS 描画後の値を取る 0.87 秒 27.3 秒 125.4 秒(3 回中 1 回失敗) 2.7 / 15.0
JS のフォームを送信する 0.16 秒 33.3 秒 75.1 秒 6.3 / 6.7
3 ページ遷移とスクリーンショット 3 枚 0.26 秒 67.8 秒 104.6 秒 9.3 / 13.3

Playwright の列は、私が書いたスクリプト 1 本を 1 回実行した時間で、モデルは介していない。3 ケース合わせて 1.3 秒。

5 ケース 15 回の通しでは、browser-use が 15 回すべて成功し、平均 38.9 秒。browse は 14 回成功で平均 78.4 秒だった。 1 回あたりの文脈消費は、browser-use が約 45 万トークン、browse が約 80 万トークン。

速さを決める往復回数と、スクリプトに替える時期

ブラウザ操作の速度を決めているのは、ドライバの速さではない。

browse は Playwright 系のドライバを使っているのに、生の CDP を叩く browser-use より遅い。 理由は往復の数にある。15 回の実行で、browser-use は 75 回、browse は 138 回モデルとツールが往復した。

モデルは 1 回ツールを呼ぶたびに、会話の文脈を丸ごと送り直す。 だから往復が 2 倍になれば、時間もトークンもほぼ 2 倍になる。ドライバを速くしても、この構造は変わらない。

browse が往復を重ねたのは、セッション名の解決と、スナップショットの読み直しだった。 加えて、OpenCode 側のコード実行ツールと browse の execute が同名で、モデルが入口を選び間違える場面があった。失敗した 1 回は、MCP ではなくシェルから CLI を叩き始め、引数を間違えて 31 回往復している。

スクリプトを書く手間と、AI に毎回任せる時間を比べる。

この記事の 3 ケースを書くのに、私は 3 分から 4 分かけた。 browser-use の 1 回が 27 秒から 68 秒なので、同じ操作を 3 回から 5 回やれば、書く手間は回収できる計算になる。

これは概算で、ケースの複雑さで動く。分岐や待ち条件が多いフローだと、スクリプトの執筆は 10 分を超える。その場合は 10 回前後が分岐点になる。 逆に、一度書いてしまえば実行の限界費用はゼロに近い。夜間に毎日回すなら、初日に書く方が安い。

ただし速さだけでは決められない。画面が変わり続けている開発中は、セレクタの保守が発生する。スクリプトは壊れるが、AI はその場で画面を見て操作を選び直せる。 壊れるコストが高い段階では AI、固まってからの反復はスクリプト、という順番になる。

見落としやすい非対称、権限

速さの比較だけを見ていると、権限の差を見落とす。

表2: 実行環境と権限

項目 browser-use browse
実行されるコード ユーザー権限の Python 制限付きの JavaScript
環境変数 読める 読めない
ファイル すべて読める 作業ディレクトリと一時領域だけ
cookie 生の CDP で全件 セッションのページのホストだけ
遷移先の制限 MCP 経由では無い セッションごとに指定できる

browser-use のモデルは Python をそのまま実行するので、os.environ から API キーを読める。実際に読めた。 MCP サーバは OpenCode の子プロセスなので、OpenCode が持つ秘密をそのまま引き継ぐ。

この構成にしたとき、systemd のユーザー環境にすでに 3 つの API キーが入っていた。 そのため常駐ブラウザの unit は env -i で環境を作り直し、Chrome には秘密を渡さないようにした。

夜間のジョブも同じで、鍵を落とした環境から起動しないと、モデルが書いたコードに鍵が渡る。 ここは速度と関係なく、運用で塞ぐしかない部分になる。

運用に落とす

OpenCode の MCP に browser-use を登録し、専用プロファイルの headless Chrome を systemd で常駐させた。

"mcp": {
  "servers": {
    "bu": {
      "type": "local",
      "command": ["/home/takuya/.local/bin/browser-use", "--cli-mcp"],
      "environment": { "BU_NAME": "opencode", "BU_CDP_URL": "http://127.0.0.1:9334" }
    }
  }
}

ブラウザ側は、落ちても 3 秒で戻るようにしてある。 起動時に browser-use-smoke でバージョンと疎通を確かめ、失敗したらジョブをブラウザ起因の失敗として扱う。再試行してよい失敗と、内容の問題を分けるためだ。

browse は採用しなかったが、捨ててはいない。常用 Chrome のログインをそのまま使いたい場面では、cookie の読み出しをホスト単位に絞れる browse の方が安全だからだ。

3 層に分けると、それぞれの層が短い時間で終わる。

新しい画面を触るときは browser-use に任せる。セレクタを書かずに済み、画面を見ながら操作を選んでくれる。 操作が固まったら、その手順を Playwright のスクリプトに写す。モデルが書いたコードをそのまま資産にしてもよい。 夜間はスクリプトを回す。1 秒未満で終わり、失敗したときに原因がログに残る。

AI に任せたままにするのは、手順がまだ無い作業だけになる。 逆に言えば、手順があるのに毎回 AI に頼むのは、同じ設計を毎日やり直しているのと同じだった。

トレンドのタグ