agent-browser:AI 时代的浏览器自动化神器,从入门到精通

GitHub: vercel-labs/agent-browser | ⭐ 14k | Apache-2.0


为什么是 agent-browser?

Selenium 太重、Puppeteer API 太啰嗦、Playwright 对 Shell 脚本不友好……当你需要让 AI Agent 自主操控浏览器时,这些问题被放大了 10 倍:LLM 的上下文有限,每次调用都要序列化整个 DOM,效率极差。

agent-browser 是 Vercel Labs 开源的浏览器自动化 CLI,底层基于 Playwright,但做了专门的 AI-first 设计:

  • Rust 原生 CLI + Node.js Daemon 架构,首命令冷启动,后续命令毫秒响应
  • **Accessibility Tree(Snapshot)**代替 DOM,天然适合 LLM 解析
  • @ref 机制让 AI 可以精确操作页面元素,无需反复查询 DOM
  • --json 输出直接给 Agent 消费
  • 多 Session、持久 Profile、云端浏览器一应俱全

安装

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 推荐:npm 全局安装(macOS/Linux/Windows 均有原生 Rust 二进制)
npm install -g agent-browser
agent-browser install          # 下载 Chromium(首次)

# macOS 也可用 Homebrew
brew install agent-browser
agent-browser install

# 不想安装?npx 直接跑(走 Node.js,稍慢)
npx agent-browser open example.com

Linux 额外装系统依赖:

1
agent-browser install --with-deps

快速上手:5 分钟跑通第一个自动化流程

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 1. 打开页面
agent-browser open https://news.ycombinator.com

# 2. 拍张截图看看
agent-browser screenshot hn.png

# 3. 抓一下可交互元素(Snapshot)
agent-browser snapshot -i

# 4. 用 ref 点击第一条新闻
#    Snapshot 输出中会有 [ref=e1] 这样的标注
agent-browser click @e1

# 5. 查看当前 URL
agent-browser get url

# 6. 关闭
agent-browser close

你会看到类似这样的 Snapshot 输出:

- link "Ask HN: Who is hiring? (March 2025)" [ref=e1]
- link "Show HN: I built a Rust-based HTTP/3 server" [ref=e2]
- button "more" [ref=e3]
...

@e1@e2 就是你的"遥控器",后续命令直接用,不需要再查 DOM。


架构原理

┌──────────────┐   Unix Socket / HTTP   ┌──────────────────────┐
│  Rust CLI    │ ──────────────────────▶│  Node.js Daemon      │
│  (agent-     │                        │  (Playwright + Chrome)│
│   browser)   │ ◀──────────────────────│                      │
└──────────────┘   JSON Response        └──────────────────────┘

Daemon 在第一条命令时自动启动,之后常驻内存。每次 CLI 调用只是 IPC 通信,所以链式命令极快:

1
2
3
agent-browser open example.com && \
  agent-browser wait --load networkidle && \
  agent-browser snapshot -i

核心命令详解

导航与等待

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
agent-browser open https://example.com        # 打开 URL
agent-browser reload                          # 刷新
agent-browser back / forward                  # 前进后退

# 等待:支持元素、毫秒、文本、URL、JS 条件、加载状态
agent-browser wait "#loading"                 # 等元素出现
agent-browser wait 2000                       # 等 2 秒
agent-browser wait --text "Welcome"           # 等文字出现
agent-browser wait --url "**/dashboard"       # 等 URL 匹配
agent-browser wait --load networkidle         # 等网络空闲
agent-browser wait --fn "window.ready===true" # 等 JS 条件

元素操作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 点击
agent-browser click @e2
agent-browser click "#submit-btn"
agent-browser dblclick ".item"

# 输入
agent-browser fill @e3 "hello@example.com"   # 清空后填入
agent-browser type @e3 "append text"          # 直接追加输入
agent-browser press Enter                     # 按键
agent-browser press "Control+a"               # 组合键
agent-browser keyboard type "raw text"        # 真实键盘事件

# 其他
agent-browser hover @e4
agent-browser check "#agree"
agent-browser select "#country" "China"
agent-browser drag ".src" ".dst"
agent-browser upload "#file" ./report.pdf

获取信息

1
2
3
4
5
6
7
8
agent-browser get text @e1          # 文本内容
agent-browser get html "#main"      # innerHTML
agent-browser get value "#input"    # 表单值
agent-browser get attr @e1 href     # 属性值
agent-browser get title             # 页面标题
agent-browser get url               # 当前 URL
agent-browser get count ".item"     # 元素数量
agent-browser get box @e1           # 边界框 {x,y,width,height}

状态检查

1
2
3
agent-browser is visible @e1        # → true/false
agent-browser is enabled "#btn"
agent-browser is checked "#checkbox"

语义化查找(Semantic Locators)

比 CSS selector 更语义化,适合不稳定的 DOM 结构:

1
2
3
4
5
6
7
agent-browser find role button click --name "Submit"
agent-browser find text "Sign In" click
agent-browser find label "Email" fill "test@test.com"
agent-browser find placeholder "Search..." fill "agent-browser"
agent-browser find testid "login-btn" click
agent-browser find first ".card" click
agent-browser find nth 2 "tr" text      # 第 2 个 tr 的文本

Snapshot:AI 工作流的核心

Snapshot 输出的是无障碍树(Accessibility Tree),而非 HTML,大幅减少 token 消耗:

1
2
3
4
5
6
agent-browser snapshot            # 完整树
agent-browser snapshot -i         # 仅可交互元素(按钮/输入/链接)
agent-browser snapshot -i -c      # 紧凑模式,去掉空结构节点
agent-browser snapshot -d 3       # 最多 3 层深度
agent-browser snapshot -s "#main" # 只看 #main 区域
agent-browser snapshot -i -C      # 包含自定义可点击元素(div onclick 等)

推荐的 AI Agent 工作流:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# Step 1: 导航
agent-browser open https://app.example.com/login

# Step 2: 等待加载完成
agent-browser wait --load networkidle

# Step 3: 获取 JSON 格式 Snapshot,喂给 LLM
agent-browser snapshot -i --json

# LLM 分析 snapshot,确定 ref → 执行操作
agent-browser fill @e3 "admin@example.com"
agent-browser fill @e4 "password123"
agent-browser click @e5

# Step 4: 页面变化后重新 snapshot
agent-browser wait --url "**/dashboard"
agent-browser snapshot -i --json

--json 输出结构:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "success": true,
  "data": {
    "snapshot": "- textbox \"Email\" [ref=e3]\n- textbox \"Password\" [ref=e4]\n...",
    "refs": {
      "e3": { "role": "textbox", "name": "Email" },
      "e4": { "role": "textbox", "name": "Password" }
    }
  }
}

截图与 PDF

1
2
3
4
5
6
7
8
# 截图
agent-browser screenshot                     # 视口截图,存临时目录
agent-browser screenshot page.png            # 指定路径
agent-browser screenshot --full page.png     # 全页截图
agent-browser screenshot --annotate          # 带编号标注(方便视觉模型)

# PDF
agent-browser pdf report.pdf

--annotate 截图会在每个交互元素上标注编号,非常适合视觉多模态模型:

1
2
3
agent-browser open https://example.com
agent-browser screenshot --annotate --full page_annotated.png
# 然后把图片传给 GPT-4o / Claude Vision

Session:多 Agent 并行

每个 session 有独立的浏览器实例、Cookie、存储和历史:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 两个 Agent 同时跑,互不干扰
agent-browser --session agent1 open site-a.com
agent-browser --session agent2 open site-b.com

agent-browser --session agent1 snapshot -i
agent-browser --session agent2 snapshot -i

# 查看所有活跃 session
agent-browser session list
# → default
# → agent1
# → agent2

# 环境变量方式
AGENT_BROWSER_SESSION=agent1 agent-browser click @e1

持久化 Profile:登录一次,永久复用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 第一次:登录并保存状态
agent-browser --profile ~/.profiles/myapp open https://myapp.com/login
agent-browser --profile ~/.profiles/myapp fill @e1 "user@example.com"
agent-browser --profile ~/.profiles/myapp fill @e2 "password"
agent-browser --profile ~/.profiles/myapp click @e3
agent-browser --profile ~/.profiles/myapp wait --url "**/dashboard"

# 以后直接用,Cookie/LocalStorage 都在
agent-browser --profile ~/.profiles/myapp open https://myapp.com/dashboard

# 配置文件方式,项目内新建 agent-browser.json
# { "profile": "./browser-data" }

Profile 存储:Cookie、LocalStorage、IndexedDB、Service Worker、Cache。


网络拦截与 Mock

非常适合测试场景,也可以用来阻断广告请求:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 拦截并中止请求(屏蔽广告)
agent-browser network route "**/*.doubleclick.net*" --abort

# Mock API 响应
agent-browser network route "https://api.example.com/user" \
  --body '{"id":1,"name":"Mock User","role":"admin"}'

# 查看当前请求日志
agent-browser network requests
agent-browser network requests --filter "/api/"

# 取消拦截
agent-browser network unroute

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# Cookie
agent-browser cookies                        # 查看所有
agent-browser cookies set token "abc123"     # 设置
agent-browser cookies clear                  # 清空

# localStorage
agent-browser storage local                  # 查看全部
agent-browser storage local "auth_token"     # 读取指定 key
agent-browser storage local set "theme" "dark"
agent-browser storage local clear

# sessionStorage 同理
agent-browser storage session set "cart" '{"items":[]}'

多标签页 & 弹窗处理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 标签页
agent-browser tab                  # 列出所有 tab
agent-browser tab new              # 新建空白 tab
agent-browser tab new https://example.com
agent-browser tab 2                # 切换到第 2 个 tab
agent-browser tab close            # 关闭当前 tab

# Frame(iframe)
agent-browser frame "#payment-iframe"  # 切入 iframe
agent-browser fill @e1 "4111111111111111"
agent-browser frame main               # 切回主 frame

# Dialog(alert/confirm/prompt)
agent-browser dialog accept
agent-browser dialog accept "My input text"
agent-browser dialog dismiss

调试工具

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 有头模式,看着浏览器操作(调试必备)
agent-browser open example.com --headed

# 高亮元素
agent-browser highlight "#submit"

# 录制 Playwright Trace(可用 trace viewer 回放)
agent-browser trace start ./trace.zip
agent-browser open example.com
agent-browser click @e1
agent-browser trace stop ./trace.zip
# npx playwright show-trace trace.zip

# 录制视频
agent-browser record start ./demo.webm https://example.com
agent-browser click @e1
agent-browser record stop

# 控制台日志 & 页面错误
agent-browser console
agent-browser errors

# 对比 Snapshot 差异
agent-browser diff snapshot   # 当前 vs 上次

# 执行任意 JS
agent-browser eval "document.title"
agent-browser eval "window.scrollTo(0, document.body.scrollHeight)"

CDP 模式:接管已有 Chrome

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 先启动 Chrome(带调试端口)
# macOS:
open -a "Google Chrome" --args --remote-debugging-port=9222

# 连接
agent-browser connect 9222
agent-browser snapshot -i

# 或者每次带 --cdp
agent-browser --cdp 9222 click @e1

# 自动发现(省去端口)
agent-browser --auto-connect snapshot

# 连接远程浏览器(Browserbase / 自建)
agent-browser --cdp "wss://remote.example.com/cdp?token=xxx" snapshot

设备模拟与浏览器设置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 模拟手机
agent-browser set device "iPhone 14"
agent-browser open https://example.com
agent-browser screenshot mobile.png

# 设置视口
agent-browser set viewport 1920 1080

# 地理位置
agent-browser set geo 22.3193 114.1694   # 香港

# 暗黑模式
agent-browser set media dark

# 断网测试
agent-browser set offline on
agent-browser open https://example.com
agent-browser screenshot offline.png
agent-browser set offline off

# 自定义 User-Agent
agent-browser --user-agent "MyBot/1.0" open https://example.com

iOS 模拟器:真实 Mobile Safari 测试

需要 macOS + Xcode + Appium

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 安装 Appium
npm install -g appium
appium driver install xcuitest

# 列出可用设备
agent-browser device list

# 在 iPhone 16 Pro 上跑 Safari
agent-browser -p ios --device "iPhone 16 Pro" open https://example.com
agent-browser -p ios snapshot -i
agent-browser -p ios tap @e1
agent-browser -p ios fill @e2 "search query"
agent-browser -p ios swipe up
agent-browser -p ios screenshot ios_test.png
agent-browser -p ios close

# 环境变量方式
export AGENT_BROWSER_PROVIDER=ios
export AGENT_BROWSER_IOS_DEVICE="iPhone 16 Pro"
agent-browser open https://example.com

云端浏览器集成

在 serverless 环境(CI/CD、Lambda、Vercel Function)里跑时,本地没有浏览器,用云端方案:

Browserbase

1
2
3
export BROWSERBASE_API_KEY="your-key"
export BROWSERBASE_PROJECT_ID="your-project"
agent-browser -p browserbase open https://example.com

Browser Use

1
2
export BROWSER_USE_API_KEY="your-key"
agent-browser -p browseruse open https://example.com

Kernel(支持 Stealth 模式 + 持久 Profile)

1
2
3
4
export KERNEL_API_KEY="your-key"
export KERNEL_STEALTH=true
export KERNEL_PROFILE_NAME="myapp-profile"
agent-browser -p kernel open https://example.com

Auth Vault:团队共享登录状态

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 保存认证 profile(会打开浏览器让你手动登录)
agent-browser auth save github --url https://github.com

# 也可以直接传账密(适合 CI)
agent-browser auth save myapp \
  --url https://app.example.com \
  --username admin@example.com \
  --password-stdin <<< "$APP_PASSWORD"

# 使用已保存的认证
agent-browser auth login github
agent-browser open https://github.com/settings/profile
agent-browser snapshot -i

# 管理
agent-browser auth list
agent-browser auth show github
agent-browser auth delete github

配置文件

项目根目录放 agent-browser.json,一次配置,全员复用:

1
2
3
4
5
6
7
{
  "headed": false,
  "proxy": "http://localhost:7890",
  "profile": "./browser-data",
  "session": "default",
  "ignoreHttpsErrors": true
}

优先级从低到高:~/.agent-browser/config.json./agent-browser.json → 环境变量 → CLI flags。


在 CI/CD 中使用

GitHub Actions

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
name: E2E Test

on: [push]

jobs:
  e2e:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Install agent-browser
        run: |
          npm install -g agent-browser
          agent-browser install --with-deps
      
      - name: Run tests
        run: |
          agent-browser open https://staging.example.com
          agent-browser wait --load networkidle
          agent-browser snapshot -i --json > snapshot.json
          agent-browser find role button click --name "Login"
          agent-browser fill @e1 "$TEST_USER" 
          agent-browser fill @e2 "$TEST_PASS"
          agent-browser click @e3
          agent-browser wait --url "**/dashboard"
          agent-browser screenshot dashboard.png
        env:
          TEST_USER: ${{ secrets.TEST_USER }}
          TEST_PASS: ${{ secrets.TEST_PASS }}
      
      - uses: actions/upload-artifact@v4
        with:
          name: screenshots
          path: "*.png"

Docker

1
2
3
4
5
6
7
8
9
FROM node:20-slim

RUN npm install -g agent-browser
RUN agent-browser install --with-deps

WORKDIR /app
COPY . .

CMD ["agent-browser", "open", "https://example.com"]

与 AI Agent 集成

最简方式:直接告诉 Agent

用 agent-browser 测试登录流程。先运行 agent-browser --help 看可用命令。

给 Claude Code / Cursor / Copilot 加技能

1
npx skills add vercel-labs/agent-browser

写入 CLAUDE.md / AGENTS.md

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
## Browser Automation

使用 `agent-browser` 进行 Web 自动化。

核心工作流:
1. `agent-browser open <url>` — 导航到页面
2. `agent-browser snapshot -i` — 获取交互元素 ref
3. `agent-browser click @e1` / `fill @e2 "text"` — 用 ref 交互
4. 页面变化后重新 snapshot
5. 使用 `--json` 获取结构化输出

调试:加 `--headed` 看可见浏览器窗口

Python 调用示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import subprocess
import json

def snapshot(session="default"):
    result = subprocess.run(
        ["agent-browser", "--session", session, "snapshot", "-i", "--json"],
        capture_output=True, text=True
    )
    return json.loads(result.stdout)

def click(ref, session="default"):
    subprocess.run(
        ["agent-browser", "--session", session, "click", f"@{ref}"],
        check=True
    )

# 使用
data = snapshot()
refs = data["data"]["refs"]
print(refs)  # {'e1': {'role': 'button', 'name': 'Login'}, ...}
click("e1")

Go 调用示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main

import (
    "encoding/json"
    "fmt"
    "os/exec"
)

func snapshot(session string) (map[string]any, error) {
    out, err := exec.Command(
        "agent-browser", "--session", session,
        "snapshot", "-i", "--json",
    ).Output()
    if err != nil {
        return nil, err
    }
    var result map[string]any
    return result, json.Unmarshal(out, &result)
}

func main() {
    exec.Command("agent-browser", "open", "https://example.com").Run()
    data, _ := snapshot("default")
    fmt.Println(data)
}

实战案例

案例 1:自动化登录并抓取数据

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash
set -e

# 登录
agent-browser open https://app.example.com/login
agent-browser wait --load networkidle
agent-browser find label "Email" fill "admin@example.com"
agent-browser find label "Password" fill "secret"
agent-browser find role button click --name "Sign In"
agent-browser wait --url "**/dashboard"

# 截图存档
agent-browser screenshot --full dashboard_$(date +%Y%m%d).png

# 抓取数据
agent-browser find role link click --name "Reports"
agent-browser wait --load networkidle
agent-browser get text "#report-summary" > report.txt

echo "Done: $(cat report.txt)"
agent-browser close

案例 2:Mock API 做前端测试

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 模拟后端返回 500 错误
agent-browser network route "https://api.example.com/data" \
  --body '{"error":"Internal Server Error","code":500}'

agent-browser open https://app.example.com
agent-browser wait --load networkidle
agent-browser screenshot error_state.png

# 模拟正常数据
agent-browser network unroute
agent-browser network route "https://api.example.com/data" \
  --body '{"items":[{"id":1,"name":"Test Item"}]}'

agent-browser reload
agent-browser screenshot normal_state.png

案例 3:对比两个页面的差异

1
2
3
agent-browser diff url \
  https://staging.example.com \
  https://production.example.com

案例 4:实时流式预览(pair browsing)

1
2
3
4
5
# 启动带 WebSocket 流的浏览器
AGENT_BROWSER_STREAM_PORT=9223 agent-browser open https://example.com

# 连接 ws://localhost:9223 就能实时看到浏览器画面
# 并可以注入鼠标/键盘事件,人机协作

常见问题

Q: 和 Playwright 直接用有什么区别?

Playwright 是 Node.js 库,适合代码级集成;agent-browser 是 CLI,适合 Shell 脚本、AI Agent 调用、快速原型。底层共享 Playwright,能力相同。

Q: 多个命令共享同一个浏览器吗?

是的。同一 session 下的命令都复用同一个 Daemon 进程,不会反复冷启动浏览器。

Q: 能用自己已有的 Chrome 吗?

可以。--cdp 9222 连接正在运行的 Chrome,或 --auto-connect 自动发现。

Q: 支持 Firefox / WebKit 吗?

通过 Daemon 支持,CLI 层目前主要是 Chromium,但 Playwright 底层具备多引擎能力。

Q: 生产环境如何部署?

推荐使用 Browserbase / Browser Use / Kernel 等云端浏览器方案,避免在 serverless 环境安装 Chromium。


总结

场景推荐用法
AI Agent 自动化snapshot -i --json + @ref 操作
E2E 测试find role/label 语义定位 + --json 断言
调试排查--headed + trace start/stop
CI/CD 无头跑install --with-deps + 云端浏览器 provider
多账号并行--session 隔离
登录态复用--profile 持久化
接管现有 Chrome--cdp / --auto-connect
iOS 真实 Safari-p ios + Appium

agent-browser 把浏览器操作降维成了 Unix 命令,正好卡在"CLI 够用"和"需要 AI 理解"的交叉点。对于 DevOps / 后端工程师来说,这才是最舒适的姿势。


项目地址:github.com/vercel-labs/agent-browser 官网文档:agent-browser.dev