
Vercel Labs の agent-browser で出力量と所要時間がどれだけ変わるか測ってみた
はじめに
ページの表示が意図どおりかを確かめるだけなら、人が目で見れば済みます。手間になるのは、その確認を AI エージェントに任せようとしたときです。エージェントは画面を見られないため、ページの中身を文字として受け取る必要があります。 HTML をそのまま渡してみたところ、試しに用意した小さなページでも 11,498 トークンありました。これでは数ページ分を読ませただけでも、エージェントが一度に扱える量を使い切ってしまうでしょう。
Vercel Labs が提供する agent-browser は、この受け渡しを小さくするためのブラウザ自動化 CLI です。ページの中身を HTML ではなく、アクセシビリティツリーの形で返します。
どこまで小さくなるのかを知りたかったので、移行前と移行後のページを見比べる確認を題材に、同じ判定を 6 通りの取り方で測りました。出力量は取り方によって 160 倍、所要時間は待機条件の指定によって 3 倍の開きがありました。
Vercel Labs とは
Vercel Labs とは、Vercel が開発者向けのツールと実験的なプロジェクトを公開している場です。ツールやプロジェクトは Vercel 本体とは切り離されています。Vercel Labs は、ツールがどのように使用されているかを見つつ、役に立ちそうなものに力を入れるという方針を掲げています。agent-browser のほかに、skills・portless・just-bash・json-render などが公開されています。
対象読者
- ページの表示の確認を AI エージェントに任せたい方
- エージェントにブラウザを操作させたときの、読み込む量を抑えたい方
- agent-browser と Playwright のどちらを使うか迷っている方
検証環境
| 項目 | 値 |
|---|---|
| agent-browser | 0.38.1 |
| Chrome for Testing (agent-browser) | 153.0.8010.47 |
| Playwright | 1.59.1 |
| Chrome Headless Shell (Playwright) | 153.0.8010.12 |
| Next.js (検証対象) | 16.3.5 |
| Node.js | v24.15.0 |
| OS | macOS (Darwin 25.6.0, arm64) |
| トークナイザー | tiktoken の o200k_base |
参考
検証方法
検証対象として、利用者の一覧を持つコンソール画面を Next.js で用意しました。同じサーバーの /before と /after が、移行前と移行後に相当する表示を返します。(※コードは付録に掲載しました。)

/before のページ

/after のページ
2 つの表示の間には、次の差を入れてあります。
| 差 | /before | /after |
|---|---|---|
| 一覧の見出しのレベル | 2 | 3 |
| 名前のセルの中のリンク | ある | ない |
| 操作という列 | ない | ある |
カードの padding |
24px | 16px |
数値列の text-align |
right | left |
カードの見出しの text-align |
center | left |
カードの見出しは、移行前も移行後も class="card-title text-center" です。クラス名を読んでも text-align は判別できず、描画された値を測る必要があります。
期待する差分と成功条件については、測定を始める前に JSON へ書き出して固定しました。(結果を見てから基準を決めると、都合のよい結論に近づけられるため)
以下は、カードの見出しの text-align について書いた部分の抜粋です。
{
"grading": {
"detected": "期待した差分をすべて、期待した値で検出した",
"partial": "期待した差分の一部だけを検出した。値が違う場合もここに含める",
"failed": "期待した差分を 1 つも検出できなかった。手段の制約で実行できなかった場合もここに含め、理由を記録する"
},
"tasks": {
"T2": {
"name": "見た目の計測",
"expected": [
{
"id": "title-align",
"selector": ".card-title",
"property": "textAlign",
"before": "center",
"after": "left"
}
]
}
}
}
測ったのは次の 6 通りです。
| 記号 | 取り方 |
|---|---|
| ab-html | agent-browser の get html body をそのまま読む。基準値として測る |
| ab-snapshot | agent-browser の snapshot -s .panel をそのまま読む |
| ab-styles | agent-browser の get styles をそのまま読む |
| ab-eval | agent-browser の eval で判定結果だけを受け取る |
| pw | Playwright で判定結果だけを受け取る (waitUntil は networkidle) |
| pw-load | 同上だが waitUntil を load にしたもの |
waitUntil は、ページの読み込みをどこまで待ってから次の処理へ進むかを指定する Playwright のオプションです。networkidle は通信が落ち着くまで、load はページの読み込みが終わるまで待ちます。
所要時間は 5 回試行の中央値です。実行順はラウンドごとに交互にしました。
検証結果
ab-eval と pw は、固定しておいた 6 項目すべてが期待値でした。
| 取り方 | 所要時間 | トークン | 文字数 |
|---|---|---|---|
| ab-html | 0.282 秒 | 11,498 | 32,444 |
| ab-snapshot | 0.304 秒 | 1,806 | 4,193 |
| ab-styles | 0.359 秒 | 13,568 | 46,567 |
| ab-eval | 0.316 秒 | 85 | 328 |
| pw | 1.506 秒 | 85 | 328 |
| pw-load | 0.507 秒 | 85 | 328 |
ab-eval のコールドスタート、つまり agent-browser close --all の直後に実行した 1 回目は 1.904 秒でした。
Playwright の 1 回あたりの処理を分けて測った結果です。
| 処理 | waitUntil が networkidle | waitUntil が load |
|---|---|---|
| ブラウザの起動 | 0.296 秒 | 0.296 秒 |
page.goto |
0.556 秒 | 0.047 秒 |
page.evaluate |
0.002 秒 | 0.008 秒 |
agent-browser の同じ処理は、open --wait-until networkidle が 0.10 から 0.13 秒、eval が 0.03 から 0.04 秒でした。
見出しのレベル、リンクの有無、列の増減は、ab-html と ab-snapshot のどちらからも読み取れます。snapshot の出力は次のように並びます。
- heading "利用者の一覧" [level=2, ref=e1]
- row
- cell "青木 一郎" [ref=e12]
- link "青木 一郎" [ref=e36]
padding と text-align は、HTML にも snapshot にも出ません。CSS を適用した結果だからです。ab-styles には含まれますが、1 要素あたり 664 行になります。
分かったこと
出力量は、同じ判定でも取り方によって 160 倍変わりました。 所要時間は、ページの読み込みをどこまで待つかの指定で 3 倍変わり、待ち方を揃えたあとに残る差はブラウザを起動し直すかどうかでした。判定に必要な値だけを受け取る取り方では、agent-browser と Playwright のどちらも同じ 85 トークンで同じ結果に到達しています。
考察
何を確認すべきかがまだ決まっていない段階では、agent-browser の snapshot が向いていると考えています。短いトークン量でエージェントにページの構造を読ませることができるためです。一方、確認する項目が決まっているなら、遷移の完了を待つ仕組みが揃っている Playwright を選ぶのがよいでしょう。
まとめ
agent-browser で同じ判定を 6 通りの取り方で測ったところ、出力量は 160 倍、所要時間は 3 倍の開きがありました。差を生んでいたのは、ツールの違いよりも、何を読むか、および、どこまで待つかの指定でした。エージェントにページを確認させるときは、まず取り方から見直すと効果が大きいと考えています。本記事が、エージェントにページを確認させるときの手段を選ぶ際の参考になれば幸いです。
付録
検証に使ったコード
ブラウザの中で動く判定コードです。
(() => {
const heading = document.querySelector('.panel h2, .panel h3');
const card = document.querySelector('.card');
const num = document.querySelector('td.num');
const title = document.querySelector('.card-title');
return JSON.stringify({
headingLevel: heading ? Number(heading.tagName.slice(1)) : null,
nameLink: !!document.querySelector('tbody tr td:first-child a'),
actionColumn: [...document.querySelectorAll('thead th')].some((th) => th.textContent === '操作'),
cardPadding: getComputedStyle(card).padding,
numAlign: getComputedStyle(num).textAlign,
titleAlign: getComputedStyle(title).textAlign,
titleClass: title.className,
});
})()
移行前と移行後の差を作っている CSS です。
.v-before .card { padding: 24px; }
.v-after .card { padding: 16px; }
.v-before .num { text-align: right; }
.v-after .num { text-align: left; }
.text-center { text-align: center; }
.v-after .card-title.text-center { text-align: left; }
画面は Next.js の App Router で作り、app/[variant]/layout.tsx が className={shell v-${variant}} を付けています。
見出しのレベルとリンクのつけ方は、一覧のページで variant を見て切り替えています。







