0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LangChain × Playwright MCP vs Browser-use:同じタスクでも消費トークンが10倍違う理由

Posted at

はじめに

LLM (大規模言語モデル) をブラウザ操作エージェントから呼び出すとき、「どのミドルウェアを選ぶか」 で消費 token 数が劇的に変わります。

本稿では LangChain + Playwright MCP と Browser-use の 2 つのブラウザ自動化スタックを対象に、同一タスクで実際に発生した token 数を比較しました。

トークン使用量の比較:Playwright MCP vs Browser-use

テスト環境と測定方法

項目 Playwright MCP  Browser-use
LLM gemini-2.5-flash gemini-2.5-flash
token 計測方法 LangSmith ダッシュボード history.usage

テストシナリオ

  1. youtubeでサンドイッチマンの漫才の動画を検索して動画を再生して
  2. yahoo.co.jpでニュース一覧を取得してTOP3のニュースの内容を調べて
  3. Amazonで2024年の話題の小説を検索して、レビュー評価が高い順に上位3冊を教えて
  4. 食べログで東京都内のラーメン店を検索して、評価の高い順にTOP3の店舗情報とレビューを教えて
  5. 楽天市場で「ワイヤレスイヤホン」を検索して、売れ筋ランキング上位3商品の価格とレビューを調べて

実測 token 数

テスト内容 Playwright MCP Browser-use
YouTube 動画再生 193,432 30,100
Yahoo ニュース TOP 3 287,521 21,102
Amazon TOP 3 (quota error) 2,600,115 70,046
食べログ TOP 3 521,718 98,915
楽天イヤホン TOP 3 310,305 83,320
  • Amazon TOP 3 : Playwright MCP はトークン上限に達してエラーとなった

ブラウザ操作の違い

Playwright MCP Browser-use
playwright-youtube.gif browser-use.gif

Playwright MCP が大量のトークンを消費する理由

Playwright MCP のログは 「ページ全体の DOM スナップショット+付帯メタ情報」をほぼそのままテキスト化 しているため、Browser-use のログよりも必然的にトークン数(=LLM が扱うサブワード単位の総量)が桁違いに多くなるようだ。

下記のように PlaywrightBrowser-use のDOMの出力方法を比較する。

Playwright の出力

- Page URL: https://www.youtube.com/watch?v=r9B5VehoJ9E
- Page Title: 【広告無し】 サンドウィッチマン コント・漫才 「今年一番ウケたネタ大賞」「お笑い王者」 #4 - YouTube
- Page Snapshot
- generic [ref=e2]:
  - generic:
    - dialog
  - generic [ref=e23]:
    - banner [ref=e26]:
      - generic [ref=e29]:
        - generic [ref=e30]:
          - button \"ガイド\" [ref=e32] [cursor=pointer]:
            - generic [ref=e35] [cursor=pointer]:
              - img
          - generic [ref=e41]:
            - link \"YouTube ホーム\" [ref=e42] [cursor=pointer]:
              - /url: /
              - generic [ref=e47] [cursor=pointer]:
                - img
            - generic [ref=e60]: JP
          - button \"ナビゲーションをスキップ\" [ref=e64] [cursor=pointer]:
            - generic [ref=e66] [cursor=pointer]: ナビゲーションをスキップ
        - generic [ref=e72]:
          - search [ref=e73]:
            - generic [ref=e74]:
              - combobox \"検索\" [expanded] [ref=e76]: サンドイッチマンの漫才
              - button \"検索クエリをクリア\" [ref=e1735] [cursor=pointer]:
                - generic [ref=e1738] [cursor=pointer]:
                  - img
            - button \"Search\" [ref=e77] [cursor=pointer]:
              - generic [ref=e80] [cursor=pointer]:
                - img
          - generic [ref=e84]:
            - button \"音声で検索\" [ref=e86] [cursor=pointer]:
              - generic [ref=e1759] [cursor=pointer]:
                - img
            - tooltip \"tooltip\"
        - generic [ref=e95]:
          - button \"設定\" [ref=e100] [cursor=pointer]:
            - generic [ref=e1762] [cursor=pointer]:
              - img
          - link \"ログイン\" [ref=e108] [cursor=pointer]:
            - /url: https://accounts.google.com/ServiceLogin?service=youtube&uilel=3&passive=true&continue=https%3A%2F%2Fwww.youtube.com%2Fsignin%3Faction_handle_signin%3Dtrue%26app%3Ddesktop%26hl%3Dja%26next%3D%252Fwatch%253Fv%253Dr9B5VehoJ9E%2526pp%253DygUh44K144Oz44OJ44Kk44OD44OB44Oe44Oz44Gu5ryr5omN&hl=ja&ec=65620
            - generic [ref=e1766] [cursor=pointer]:
              - img
            - generic [ref=e112] [cursor=pointer]: ログイン
<<<以下省略>>>

Browser-use の出力

[Start of page]
[0]<ytd-masthead role=banner>戻る
JP
ナビゲーションをスキップ
検索 />
	[1]<yt-icon-button  />
		[2]<button aria-label=ガイド />
			[3]<yt-icon  />
				[4]<span  />
	[5]<a title=YouTube ホーム />
		[6]<div  />
			[7]<ytd-logo  />
				[8]<yt-icon  />
					[9]<span  />
	[10]<div  />
		[11]<input name=search_query aria-expanded=true type=text role=combobox placeholder=検索 />
		[12]<button aria-label=検索クエリをクリア />
			[13]<div  />
	[14]<button aria-label=Search title=検索 />
		[15]<yt-icon  />
			[16]<span  />
	[17]<ytd-button-renderer >音声で検索 />
		[18]<button aria-label=音声で検索 />
			[19]<div  />
	[20]<ytd-topbar-menu-button-renderer  />
		[21]<a  />
			[22]<yt-icon-button  />
				[23]<button aria-label=設定 />
					[24]<yt-icon  />
						[25]<span  />
	[26]<ytd-button-renderer  />
		[27]<a >ログイン />
<<<以下省略>>>

DOM 情報の構造化とトークン数への影響

Browser-use がDOM情報を極力圧縮していることが確認できる。Browser-use はDOM情報の前に毎回長大なプロンプトを付加してLLMに情報を送っているが、DOM情報の大きさがその差を逆転してしまうため、Playwright が消費する token が大きくなると推察される。

項目 Playwright MCP Browser-use
取得範囲 ページ全 DOM(shadow-DOM 含む)を逐次 YAML 風ツリーで保存 可視ビュー + クリック可能要素のみを番号付きリストで保存
含まれる属性 role, aria-label, title, ref, cursor, expanded など多数 type, text など最小限
階層表現 インデントで深さをそのまま保持(ネストが深いほど行数増) 1 要素 1 行で完結
重複データ 同一画像やリンクでもノードごとに繰り返し記録 インデックス管理なので重複ほぼなし

結果: 同じページでも Playwright MCP は数千〜数万行、Browser-use は数百行で済む

ソースコード (抜粋) と token 集計方法

Langchain + Playwright MCP

LangSmith で token 数を取得

main.py
import asyncio
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain_mcp_adapters.tools import load_mcp_tools
from langgraph.prebuilt import create_react_agent

# Playwright MCPサーバーの設定
# npxコマンドを使用して@playwright/mcpパッケージを実行
client = MultiServerMCPClient(
    {
        "playwright": {
            "command": "npx",
            "args": [
                "@playwright/mcp@latest",
            ],
            "transport": "stdio",
        }
    }
)

async def run_agent():
    """
    セッション管理を使用してエージェントを実行する関数
    """
    # セッションを使用してMCPクライアントとの接続を管理
    async with client.session("playwright") as session:
        # セッションからツールを読み込み
        tools = await load_mcp_tools(session)
        
        # ReAct エージェントを作成(Google Geminiモデルを使用)
        agent = create_react_agent("google_genai:gemini-2.5-flash", tools)
        
        # YouTubeでサンドイッチマンの漫才動画を検索・再生するタスクを実行
        response = await agent.ainvoke(
            {"messages": [{"role": "user", "content": "youtubeでサンドイッチマンの漫才の動画を検索して動画を再生して"}]}
        )
        
        # レスポンスメッセージの内容を出力
        print("Agent response:", response["messages"][-1].content)

if __name__ == "__main__":
    # メイン実行部:非同期関数を実行
    asyncio.run(run_agent())

Browser-use

Browser-usehistory.usage から token 数を取得

basic_example.py
import asyncio

from browser_use import Agent
from browser_use.browser import BrowserProfile
from browser_use.llm import ChatGoogle

async def main():
    # より簡単なタスクでテスト
    task = "youtubeでサンドイッチマンの漫才の動画を検索して動画を再生して"

    llm = ChatGoogle(
        model="gemini-2.5-flash",  # より安価なモデル
        temperature=0.1,
    )
    
    # ブラウザプロファイルでwindowサイズを指定
    browser_profile = BrowserProfile(
        window_size={'width': 1280, 'height': 720},  # HD解像度
        headless=False,  # ブラウザを表示する
        viewport={'width': 1280, 'height': 720},  # コンテンツエリアのサイズ
        # no_viewport=True,  # viewportを無効にする場合
    )
    
    # エージェント作成(タイムアウト設定とブラウザプロファイル指定)
    agent = Agent(
        task=task,
        llm=llm,
        browser_profile=browser_profile,  # ブラウザプロファイルを指定
        max_time=60,  # 60秒でタイムアウト
        max_steps=5,  # 最大5ステップ
    )
    
    print(f"🚀 Starting task: {task}")
    print(f"🤖 Using model: {llm.model}")
    print(f"📐 Window size: {browser_profile.window_size}")
    print("⏱️ Max time: 60 seconds, Max steps: 5")
    
    try:
        # エージェント実行
        history = await agent.run()
        
        print(f"✅ Task completed! Steps taken: {len(history.history)}")
        
        # トークン使用量を表示
        if history.usage:
            print(f"💰 Token usage: {history.usage}")
        
        # 最終結果を表示
        if history.final_result():
            print(f"📋 Final result: {history.final_result()}")
            
    except Exception as e:
        print(f"❌ Error occurred: {e}")
        print("This might be normal if the task completed successfully")

if __name__ == '__main__':
    print('🌐 Browser-use Basic Example')
    print('=' * 30)
    asyncio.run(main())

まとめ

今回の比較により、同じタスクを実行してもミドルウェアの選択によってトークン使用量が大きく異なることがわかりました。特に Playwright MCP は DOM 全体を詳細に渡って出力するため、モデルの処理コストが高騰する傾向があります。

一方、Browser-use は DOM 情報を圧縮し、トークン消費を抑える設計になっており、実運用でのコスト最適化が期待できます。エージェント設計時には、必要な精度とトークンコストのバランスを慎重に見極めることが重要です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?