ブラウザ自動操作のフレームワークとしてBrowser Use(Python ライブラリ)は広く使われるようになりましたが、同梱されているBrowser Use CLIを使うとターミナルコマンドだけでブラウザを操作できます。Pythonコードを書かずにブラウザをコマンドで動かせるため、Claude Codeによる自動化スクリプト開発のデバッグに最適です。
CLIの特徴は名前付きセッションによる状態の永続化です。コマンド間でブラウザのセッションが引き継がれるため、「URLを開く→要素を確認→クリック→テキスト取得」という一連の流れをシェルスクリプトとして記述できます。また--headedオプションでブラウザウィンドウを表示しながら操作できるので、Claude Codeがスクリプトを生成している間にターミナルで動作確認するというワークフローが自然に成立します。
この記事では、Browser Use CLIの基本コマンドから実践的なユースケースまで、Claude Codeとの連携方法を中心に詳しく解説します。
・Browser Use CLIのセットアップと基本コマンド
・名前付きセッションを使ったマルチタブ並列操作
・–headedオプションでビジュアルデバッグする方法
・競合調査・Webモニタリング・ニュース収集の実践例
・Python Agent.run() とCLIコマンドの使い分け
Python APIとCLIコマンド:何が違うのか
前回の記事ではBrowser UseのPython APIを中心に解説しました。CLIはそれと別のアプローチで、ターミナルコマンドで直接ブラウザを操作するツールです。
| 項目 | Python API(Agent) | CLIコマンド |
|---|---|---|
| 操作方法 | Pythonコードで記述 | ターミナルコマンド |
| 自律性 | LLMが自律的に判断・操作 | 開発者がコマンドで明示的に操作 |
| セッション管理 | スクリプト内のみ | 名前付きセッションで永続化 |
| マルチタブ | コードで実装 | –sessionオプションで並列化 |
| シェル統合 | pipで呼び出しが必要 | 直接コマンドで統合しやすい |
| 向いている用途 | 複雑な判断が必要な処理 | 定型的な操作・デバッグ・シェルスクリプト |
・Claude Codeと並行してブラウザを手元で確認しながら開発するとき
・シェルスクリプトやcronジョブにブラウザ操作を組み込みたいとき
・複数のサイトを名前付きセッションで同時に処理したいとき
セットアップ
Browser UseはPython 3.11+が必須です。
python --versionで確認してください。# uvを使う場合(推奨) uv tool install browser-use # pipを使う場合 pip install browser-use # ブラウザのインストール(初回のみ) playwright install chromium # インストールの確認 browser-use doctor
APIキーの設定
export ANTHROPIC_API_KEY="sk-ant-..." # 永続化する場合は ~/.bashrc や ~/.zshrc に追記
set ANTHROPIC_API_KEY=sk-ant-... # 永続化する場合はシステム環境変数に追加
基本コマンドリファレンス
Browser Use CLIのコマンドは「ナビゲーション」「状態確認」「操作」「データ取得」の4グループに整理できます。
ナビゲーション
browser-use open https://example.com # URLに移動 browser-use back # 前のページに戻る browser-use scroll down # 下にスクロール browser-use scroll up # 上にスクロール
状態確認
browser-use state # 操作可能な要素をインデックス付きで一覧表示 browser-use screenshot # スクリーンショットを保存 browser-use get title # ページタイトルを取得 browser-use get html # HTMLソース全体を取得 browser-use get text # ページ内テキストを取得 browser-use get value <番号> # 要素の値を取得
browser-use state が要となるコマンドですこのコマンドを実行すると、現在のページ上でクリック・入力できる要素が番号付きで表示されます。
例:
[0] input "検索", [1] button "送信", [2] link "ログイン"この番号を使って後続のコマンドで要素を指定します。インデックスはページが変わるたびにリセットされるため、操作の直前に必ず
state を実行して番号を確認してください。操作コマンド
browser-use click <番号> # 要素をクリック browser-use type "テキスト" # フォーカス中の要素にテキスト入力 browser-use input <番号> "テキスト" # 要素をクリックしてテキスト入力 browser-use keys "Enter" # キーボードキーを送信 browser-use select <番号> "選択肢" # セレクトボックスから選択 browser-use hover <番号> # 要素にホバー browser-use upload <番号> "/path" # ファイルをアップロード browser-use dblclick <番号> # ダブルクリック
高度なコマンド
# JavaScriptを実行(戻り値を取得できる)
browser-use eval "document.title"
browser-use eval "document.querySelectorAll('.item').length"
# Pythonコードをローカルで実行(変数が永続化される)
browser-use python "import json; data = {'key': 'value'}"
# 要素の出現・テキストを待機
browser-use wait selector ".loaded"
browser-use wait text "完了しました"
# タブ操作
browser-use switch <タブ番号>
browser-use close-tab
グローバルオプション
| オプション | 説明 | 例 |
|---|---|---|
--headed |
ブラウザウィンドウを表示 | browser-use --headed open URL |
--session NAME |
名前付きセッションを使用 | browser-use --session work open URL |
--json |
結果をJSON形式で出力 | browser-use --json get text |
--profile NAME |
Chromeプロファイルを使用 | browser-use --profile Default open URL |
--cdp-url URL |
CDP経由でChromeに接続 | browser-use --cdp-url ws://... open URL |
実践:フォーム入力のサンプル
# ① ページを開く browser-use open https://example.com/contact # ② 操作可能な要素を確認 browser-use state # 出力例: [0] input "お名前", [1] input "メールアドレス", [2] button "送信" # ③ フォームに入力 browser-use input 0 "山田 太郎" browser-use input 1 "yamada@example.com" # ④ 送信して確認 browser-use click 2 browser-use screenshot confirm.png
–headed オプション:ビジュアルデバッグ
スクリプト開発時に最も役立つのが --headed オプションです。ブラウザウィンドウを表示した状態でコマンドを実行できるため、Claude Codeがスクリプトを生成している横のターミナルで動作確認しながら開発を進められます。
# ブラウザウィンドウを表示しながら操作 browser-use --headed open https://example.com browser-use --headed state # セッションと組み合わせてウィンドウを開いたまま複数コマンド実行 browser-use --headed --session debug open https://example.com browser-use --session debug state # --headedなしでも同じセッションに接続 browser-use --session debug click 0
| ターミナル1(Claude Code) | ターミナル2(デバッグ) |
|---|---|
| 自動化スクリプトを作成中 | browser-use --headed --session debug open URL |
| 「このボタンを押すには?」 | browser-use --session debug state でインデックス確認 |
| インデックスをスクリプトに組み込む | ウィンドウを見ながら click を試す |
| エラー箇所を特定 | browser-use --session debug screenshot debug.png |
・ページ構造が複雑でセレクタの特定が難しいとき
・ログインが必要なサイトのフロー確認
・SPAや動的コンテンツが多いページのタイミング確認
・初めて触るサービスの操作手順を探索するとき
名前付きセッション:マルチタブ並列操作
CLI の特徴的な機能が名前付きセッションです。--sessionオプションで複数のブラウザセッションを独立して管理でき、並列処理が可能になります。
# セッション "research" を開始してサイトAに移動 browser-use --session research open https://siteA.com browser-use --session research state # 別セッション "monitor" を同時に使用 browser-use --session monitor open https://statuspage.io browser-use --session monitor get text # 2つのセッションは独立しており互いに影響しない browser-use --session research click 3 browser-use --session monitor screenshot monitor.png # アクティブなセッション一覧を確認 browser-use sessions # セッションを終了 browser-use close --session research # または全セッション終了 browser-use close --all
セッションごとに独立したブラウザコンテキストが管理されます。同じセッション名を使えばコマンド間でブラウザの状態が引き継がれます。環境変数
BROWSER_USE_SESSION にデフォルトのセッション名を設定することもできます。実践ユースケース
競合サイトの価格調査
複数サイトの価格情報を定期的に収集するシェルスクリプトです。--jsonで構造化出力し、jqで整形して保存します。
#!/bin/bash
# 競合3サイトの価格を収集
DATE=$(date +%Y-%m-%d)
OUTPUT_DIR="./price_data"
mkdir -p "$OUTPUT_DIR"
for SITE in "siteA.com" "siteB.com" "siteC.com"; do
echo "=== $SITE の価格を取得中 ==="
SESSION="price_${SITE//./_}"
# ページを開いて価格テーブルをスクレイピング
browser-use --session "$SESSION" open "https://$SITE/products"
browser-use --session "$SESSION" wait selector ".product-grid"
# テキストをJSON形式で取得してファイルに保存
browser-use --session "$SESSION" --json get text > "${OUTPUT_DIR}/${SITE}_${DATE}.json"
browser-use close --session "$SESSION"
echo "$SITE 完了"
sleep 3 # サーバー負荷軽減のため待機
done
echo "全サイトの収集が完了しました。"
Python Agentと組み合わせた高度な価格分析
CLIでデータを収集し、Python AgentでAI分析するパターンです。
#!/usr/bin/env python3
"""CLIで収集したデータをPython Agentで分析"""
import subprocess, json, asyncio
from browser_use import Agent
from langchain_anthropic import ChatAnthropic
def cli_get_page_text(url: str) -> str:
"""CLIコマンドで指定URLのテキストを取得"""
subprocess.run(["browser-use", "open", url], capture_output=True)
result = subprocess.run(
["browser-use", "--json", "get", "text"],
capture_output=True, text=True
)
return result.stdout
async def analyze_prices(raw_data: str) -> dict:
"""Python AgentでAI分析(CLIでは難しい判断処理を担当)"""
llm = ChatAnthropic(model="claude-sonnet-4-6")
agent = Agent(
task=f"以下のテキストから製品名と価格を抽出してJSON形式で返してください。
{raw_data[:3000]}",
llm=llm,
)
result = await agent.run()
return result.final_result()
if __name__ == "__main__":
# CLI で取得 → Agent で解析
raw = cli_get_page_text("https://example.com/products")
analysis = asyncio.run(analyze_prices(raw))
print(json.dumps(analysis, ensure_ascii=False, indent=2))
サービスステータス監視
ステータスページを定期チェックして異常があれば通知するスクリプトです。
#!/bin/bash
# サービスステータス監視(cronで毎時実行)
SERVICES=(
"https://status.example.com"
"https://app.example.com/health"
)
LOG_FILE="./status_$(date +%Y%m%d).log"
SLACK_WEBHOOK="https://hooks.slack.com/services/xxx"
for URL in "${SERVICES[@]}"; do
SESSION="monitor_$(echo $URL | md5sum | cut -c1-8)"
browser-use --session "$SESSION" open "$URL"
browser-use --session "$SESSION" wait selector "body"
STATUS=$(browser-use --session "$SESSION" --json get text)
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
# ログに記録
echo "$TIMESTAMP | $URL | $STATUS" >> "$LOG_FILE"
# 「degraded」「down」「障害」が含まれていれば Slack 通知
if echo "$STATUS" | grep -qi "degraded\|down\|障害\|停止"; then
curl -s -X POST "$SLACK_WEBHOOK" -H "Content-Type: application/json" -d "{"text":"⚠️ $URL で異常を検出"}"
fi
browser-use close --session "$SESSION"
done
ニュース収集パイプライン(SQLite保存)
テックニュースサイトから記事を自動収集してSQLiteに蓄積するパイプラインです。CLIでページテキストを取得し、Pythonで構造化して保存します。
#!/usr/bin/env python3
"""テックニュース収集パイプライン(CLI + Python処理)"""
import subprocess, json, sqlite3, asyncio
from datetime import datetime
from browser_use import Agent
from langchain_anthropic import ChatAnthropic
SOURCES = {
"hacker_news": "https://news.ycombinator.com",
"lobsters": "https://lobste.rs",
}
def fetch_page_text(url: str) -> str:
"""Browser Use CLIでページのテキストを取得"""
subprocess.run(["browser-use", "open", url],
capture_output=True, text=True)
# 動的コンテンツの読み込みを待機
subprocess.run(["browser-use", "wait", "selector", "body"],
capture_output=True, text=True)
result = subprocess.run(
["browser-use", "--json", "get", "text"],
capture_output=True, text=True
)
return result.stdout
async def extract_articles(raw_text: str, source: str) -> list:
"""Python AgentでLLMが記事情報を抽出"""
llm = ChatAnthropic(model="claude-sonnet-4-6")
agent = Agent(
task=(
f"以下は{source}のページテキストです。"
"記事のタイトル・URL・スコアを抽出してJSON配列で返してください(最大20件)。
"
+ raw_text[:4000]
),
llm=llm,
)
result = await agent.run()
try:
return json.loads(result.final_result()) if result.final_result() else []
except json.JSONDecodeError:
return []
def save_articles(db_path: str, source: str, articles: list) -> int:
"""SQLiteに保存(重複はスキップ)"""
db = sqlite3.connect(db_path)
cur = db.cursor()
cur.execute("""
CREATE TABLE IF NOT EXISTS articles (
id INTEGER PRIMARY KEY, source TEXT,
title TEXT UNIQUE, url TEXT, score TEXT,
scraped_at TEXT
)
""")
saved = 0
for a in articles:
try:
cur.execute(
"INSERT OR IGNORE INTO articles VALUES (NULL,?,?,?,?,?)",
(source, a.get("title"), a.get("url"),
str(a.get("score","")), datetime.now().isoformat())
)
if cur.rowcount: saved += 1
except Exception: pass
db.commit(); db.close()
return saved
if __name__ == "__main__":
DB = "tech_news.db"
for name, url in SOURCES.items():
print(f"収集中: {name}")
raw = fetch_page_text(url)
articles = asyncio.run(extract_articles(raw, name))
n = save_articles(DB, name, articles)
print(f" → {n}件を新規保存")
# 集計表示
db = sqlite3.connect(DB)
cur = db.cursor()
cur.execute(
"SELECT source, COUNT(*) FROM articles "
"WHERE scraped_at > datetime('now','-24 hours') GROUP BY source"
)
print("
[24時間以内の収集状況]")
for src, cnt in cur.fetchall():
print(f" {src}: {cnt}件")
db.close()
Claude Code Skillsとして組み込む
Claude Code Skillsとして登録することで、Claude Codeの会話からBrowser Use CLIを呼び出せるようになります。
#!/usr/bin/env python3
"""
Claude Code Skill: Browser Use CLI ラッパー
使い方:
python browser_cli_skill.py open https://example.com
python browser_cli_skill.py state
python browser_cli_skill.py click 0
python browser_cli_skill.py eval "document.title"
"""
import sys, json, subprocess
def run_browser_cmd(args: list[str], json_output: bool = False) -> dict:
"""browser-useコマンドを実行して結果を返す"""
cmd = ["browser-use"]
if json_output:
cmd.append("--json")
cmd.extend(args)
result = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8")
return {
"stdout": result.stdout.strip(),
"returncode": result.returncode,
"stderr": result.stderr.strip() if result.returncode != 0 else "",
}
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python browser_cli_skill.py <command> [args...]")
sys.exit(1)
command = sys.argv[1]
args = sys.argv[2:]
# get系コマンドはJSON出力
use_json = command in ("get", "state", "eval")
result = run_browser_cmd([command] + args, json_output=use_json)
print(json.dumps(result, ensure_ascii=False, indent=2))
Python AgentとCLIコマンドの使い分け
「どちらを使うべきか」の判断基準をまとめます。基本的に「判断が必要なら Agent、定型処理ならCLI」と覚えておくと迷いません。Python AgentのAPIについてはClaude Agent SDK ガイドも参照してください。
| シナリオ | 推奨 | 理由 |
|---|---|---|
| シェルスクリプトへの組み込み | CLIコマンド | コマンド1行で記述できる |
| cronジョブによる定期実行 | CLIコマンド | セッション永続化で安定動作 |
| Claude Codeでのデバッグ | CLI(–headed) | ウィンドウを見ながら確認できる |
| 複数サイトの並列処理 | CLI(名前付きセッション) | –sessionで独立管理 |
| 複雑な条件分岐ロジック | Python Agent | LLMが状況を判断して操作 |
| UIが頻繁に変わるサイト | Python Agent | AIがセレクタ変更に自動適応 |
| 構造化データの抽出 | CLI取得 + Agent解析 | 取得は高速CLI・解析はAI |
トラブルシューティング
ブラウザが起動しない
# まず診断コマンドを実行 browser-use doctor # Chromiumを再インストール playwright install chromium # 既存のChromeプロファイルを使う browser-use --profile "Default" open https://example.com # リモートのCDPに接続 browser-use --cdp-url ws://localhost:9222 open https://example.com
セッションが応答しない
# アクティブなセッションを確認 browser-use sessions # 全セッションを強制終了して再起動 browser-use close --all browser-use open https://example.com
要素が見つからない(インデックスがずれる)
# 毎回 state で最新インデックスを取得してから click する
browser-use state # 必ず直前に実行
browser-use click 5 # 確認した番号を使う
# 動的コンテンツはセレクタ待機を入れる
browser-use wait selector ".product-list"
browser-use state # 待機後に再取得
# JavaScriptで直接セレクタを指定する
browser-use eval "document.querySelector('[data-id="submit"]').click()"
browser-use state で取得した番号はページの再読み込みや動的コンテンツの更新があるとずれます。操作の直前に必ず state を実行して番号を確認してください。よくある質問
Qbrowser-use CLIとPython ライブラリは同時にインストールできますか?
Aはい。pip install browser-use で両方が使えるようになります。CLIコマンド(browser-use open等)とPython API(from browser_use import Agent)は同じパッケージに含まれており、用途に応じて使い分けることができます。
Q名前付きセッションはいつ終了しますか?
Aセッションは browser-use close --session 名前 で明示的に終了するか、browser-use close --all で全セッションを一括終了できます。システムを再起動した場合もセッションはリセットされます。
Qログインが必要なサイトはどう扱えばよいですか?
A--profile "Default" オプションで既存のChromeプロファイルを使うと、ブラウザに保存されたログイン情報をそのまま使用できます。またはCDPで既に起動中のChromeに接続して(--cdp-url)、ログイン済みのブラウザを操作することも可能です。
Q大量のページを処理する場合に注意することは?
Aセッションを使い終わったら close コマンドで必ず終了してください。セッションを開きっぱなしにするとメモリ消費が増えます。また並列処理の際はサーバーへの礼儀として sleep コマンドで待機時間を設けることを推奨します。
Q–json オプションを使ってもJSONが返ってこない場合の対処法は?
Aまず browser-use doctor で環境を確認してください。コマンドが失敗している場合は標準エラー出力にエラーが出ているため、シェルスクリプト内では 2>&1 でエラーをキャッチして診断するのが有効です。
まとめ
Browser Use CLIはコマンドラインからブラウザを直接操作できるツールで、Claude Codeとの組み合わせで大きな力を発揮します。
| 機能 | ポイント |
|---|---|
| browser-use state | 要素を番号付きで確認、操作の起点となるコマンド |
| –headed オプション | ブラウザ表示でリアルタイムデバッグ |
| 名前付きセッション | 複数サイトをマルチタブで並列処理 |
| –json オプション | 取得データをJSON形式でシェルに渡せる |
| eval / wait コマンド | 動的コンテンツへの柔軟な対応 |
定型的な操作はCLIコマンドで高速処理し、判断が必要な処理はPython Agentに委ねるハイブリッドなアプローチが実務での最適解です。シェルスクリプトとの組み合わせや、cronジョブへの組み込みにも積極的に活用してみてください。
Browser UseのPython APIとPlaywrightを組み合わせたハイブリッドアプローチについては、PlaywrightとBrowser Useのブラウザ自動操作ガイドもあわせてご覧ください。
