AI agent にブラウザをつなぐと、最初はだいたい順調です。ページを開く、内容を読む、検索ボックスに入力する。本当に人を詰まらせるのは、クロスオリジン iframe の中に隠れたフォームです——Google Payments の受取情報、さまざまな決済コンポーネント、KYC コントロール。agent はその中の文字を読めるし、値も入力できる。でも、あの「保存」ボタンだけはクリックできない。読めるのに、完了できない。

この記事は、この壁を乗り越えた過程の記録です。主役は chrome-use——Rust で書かれた、agent 向けのブラウザ自動化 CLI です。Playwright も headless も使わず、あなたが**実際にログインしている**その Chrome を直接操作します。
プロジェクトページ:https://chrome-use.leeguoo.com/
なぜクロスオリジン iframe はこんなに難しいのか
普通のページなら簡単です。アクセシビリティツリーを取得し、要素の参照を取り、クリックすれば終わりです。しかしクロスオリジン iframe(たとえば adsense.google.com のページに payments.google.com の iframe が埋め込まれている場合)では、一度に3つの地雷を踏みます。
- セレクタが中に入れない。同一オリジンポリシーのもとでは、外側のドキュメントで実行する CSS セレクタや
evalは、iframe 内部の DOM に一切触れられません。ここではdocument.querySelectorは役に立ちません。 - スクロールが外れる。ページをスクロールしているつもりでも、実際にスクロールできるのは iframe 内部のスクロールコンテナです。wheel イベントは外側のドキュメントに送られ、中は微動だにしません——目標の行はいつまでも「画面外」にあり、見ることすらできません。
- 座標を推測してクリックするしかなくなる。前の2つの問題により、「スクリーンショット + ピクセル座標の推測」へ戻らざるを得ません。これはもっとも不正確で、隣のフィールドを誤ってクリックしやすい方法です。**全体の支払い情報**を変更するフォームでは、クリック一回の間違いの代償は小さくありません。
chrome-use の基盤:agent に渡すのは HTML ではなく「参照」
突破方法を話す前に、まず chrome-use の基本を説明する必要があります。これは、「HTML をモデルに食べさせる」派との根本的な違いでもあります。

chrome-use はページのソースコードを agent に投げません。かわりにアクセシビリティツリーのスナップショットを取得し、操作できる各要素に短い参照を付けます。
- textbox "メール" [ref=e2]
- listbox "国/地域" [ref=e60]
- button "保存" [ref=e41]
agent はその参照を直接操作します。fill @e2 "..."、click @e41 のように。1ページはだいたい 200–400 token で済み、DOM ノイズで画面全体が埋まることはありません。この参照仕組みこそが、あとで iframe を貫通できる前提になります——スナップショットが iframe 内部のノードを「見られる」なら、参照も取得できます。
3つの壁を一つずつ越える
第一の壁: スナップショットに iframe 内部を見せる。
アクセシビリティツリーがクロスオリジン iframe を貫通し、内部のノードにも参照を付けて持ってこられるようにします。修正すると、snapshot が直接こう列挙します。
- textbox "電話番号 (任意)" [ref=e59]
- listbox "国/地域コード:日本 (+81)" [ref=e60]
——セレクタが入れない場所にも、参照は入れます。
第二の壁: スクロールを iframe のスクロールコンテナに効かせる。 wheel を外側のドキュメントへまとめて送るのをやめ、本当にスクロールすべきコンテナをスクロールします。これで下のフォーム行がようやく視野に入り、参照も取れるようになります。
第三の壁(もっとも硬い): クロスオリジン iframe 内の「有効」な送信ボタンをクリックしても反応しない。 この段階がいちばん苦しいところでした。なぜなら、見た目にはすべて正しいからです。
- 実際のキー入力で番号を入れた。
get valueで読むと、たしかに入っている。 - 「保存」ボタンは有効になるべきタイミングで有効になった(正しい値を入れる前は disabled で、入力後に現れる)。
- そして
click @e41——フォームは微動だにしない。find text "保存"?クロスオリジンなので取れない。フォーカスして Enter / Space を押す?それでも反応なし。
合っているのに、どこもかしこも合っていない。根本原因は、クロスオリジン iframe 内の Material/フレームワーク系ボタンが、合成クリックを受け付けないことでした。さらに、fill は入力フィールドの値だけを変え、フレームワークが必要とする input/change イベントを発火していませんでした。そのためフォーム側は「変化していない」と思い、保存ボタンは無効のまま、またはクリックしても何も起きない状態になります。
解決は2つに分かれます。値の入力は**実際のキー入力に切り替える(各文字が本物のイベントを発生させるので、フレームワークが認識する)。クリックは、iframe 内のコンテンツノードに対して、ただ click() を被せるのではなく、本物のマウス/キーボード起動**を一式送る必要があります。
仕上げ: 中にクリックして、保存する

3つの壁を越えると、全体の流れがつながります。開く → 目標行までスクロール → スナップショットで参照を取得 → 実際のキー入力で値を入れる → 保存を押す。あの「読めるのに、完了できない」詰みは、ここで終わりです。
同じように agent ブラウザ自動化をしている人へ、血で得た経験
- まずアクセシビリティ参照を使い、デフォルトでスクリーンショットの座標クリックに逃げない。スナップショットが iframe を見られるなら、参照はピクセル推測よりずっと安定します。スクリーンショットは canvas/WebGL のように、本当に構造がない場面に残します。
- クロスオリジン iframe は明確な境界です。セレクタと
evalはそこで終わりです。ツールに a11y ツリーを貫通させるか、そうでなければ座標を盲目的にクリックするしかありません。 - 「入力できるか」だけでなく、「送信できるか」を測る。値が入ったこと ≠ フレームワークが受け取ったこと、です。
fillがイベントを発火しないような落とし穴は、実際に保存をクリックしてはじめて露呈します。 - 実際にログインしたブラウザを使えるなら、headless は避ける。ログイン状態、cookie、拡張機能がすべてそのままあり、自動化フィンガープリントもありません——これが chrome-use が「あなた自身の Chrome を操作する」道を選ぶ理由でもあります。
試す
curl -fsSL https://raw.githubusercontent.com/leeguooooo/chrome-use/main/install.sh | sh
リポジトリは github.com/leeguooooo/chrome-use にあります。私はずっと、このような「あなた自身のサブスクリプションを使い、agent を実際のブラウザ/端末につなぐ」ツールを作っています。進捗は X @leeguooooo に投稿しています。

微信
支付宝
コメント
コメントは即時公開されますが、ポリシー違反時は非表示になる場合があります。