四大AI浏览器工具横评:谁才是真正的浏览器王者?
一、四个狠角色登场
想让AI帮你操作浏览器?你算是问对人了!我找到了四个”传说中”最强的浏览器自动化工具:
|
|
|
|
|
|---|---|---|---|
| Playwright |
|
|
|
| Agent-browser |
|
|
|
| Chrome-devtools-mcp |
|
|
|
| Browser-use |
|
|
|
这四个货性格各异,有的爱秀肌肉(显示UI),有的爱搞神秘(隐藏窗口),有的还偷偷”复制”你的用户数据…
二、第一个问题:默认显示UI吗?
这可是面子问题!有的工具一上来就给你看窗口,有的藏着掖着。
2.1 验证结果一览
|
|
|
|
|
|---|---|---|---|
| Playwright |
|
|
headless: false |
| Agent-browser |
|
|
--headed |
| Chrome-devtools-mcp |
|
|
|
| Browser-use |
|
|
|
Chrome-devtools-mcp 简直是异类——别人都藏着掖着,它倒好,直接把窗口糊你脸上。
2.2 代码实锤
Playwright(闷骚型):
// 默认隐藏const browser = await chromium.launch();// 想要显示?加参数const browser = await chromium.launch({ headless: false });
Agent-browser(低调型):
agent-browser open https://example.com # 隐藏agent-browser open https://example.com --headed # 显示
Chrome-devtools-mcp(社牛型):
# chrome_management.py:175# 默认就是显示!就是玩~await start_chrome(headless=False)
Browser-use(看心情型):
# 源码 profile.py:1194-1196if self.headless is None: self.headless = not has_screen_available # 有屏幕就显示
三、第二个问题:Cookie能复用吗?
这才是真爱问题!谁也不想每次都重新登录对吧?
3.1 理论分析:默认都是”临时工”
|
|
|
|
|
|---|---|---|---|
| Playwright |
|
|
launchPersistentContext(userDataDir)
|
| Agent-browser |
|
|
--profile
|
| Chrome-devtools-mcp |
|
|
|
| Browser-use |
|
|
|
Browser-use 简直是”表面一套背后一套”——你给了它用户目录,它转头复制一份到临时目录,还笑嘻嘻告诉你”我用完了”。
3.2 源码实锤:Browser-use 的骚操作
# profile.py:803-823 源码def _copy_to_temp_if_user_data_dir(self) -> Self: """Copy profile to temp directory if user_data_dir is not None.""" if self.user_data_dir is not None: temp_dir = tempfile.mkdtemp(prefix='browser-use-user-data-dir-') path_original_user_data = Path(self.user_data_dir) # ... 复制所有文件到临时目录 ... self.user_data_dir = temp_dir # 你的Cookie被复制走了!
3.3 正确的复用姿势
Playwright(推荐):
const browser = await chromium.launchPersistentContext( 'C:/Users/xxx/AppData/Local/Google/Chrome/User Data/Default', { headless: false });
Agent-browser:
# 先关闭daemonagent-browser close# 再用profile启动agent-browser open https://example.com --profile "用户目录"
Chrome-devtools-mcp:
# 先手动打开Chrome并开启调试chrome --remote-debugging-port=9222 --user-data-dir="你的Chrome目录"# 然后让MCP连接上去(自动检测已运行的Chrome)await start_chrome() # 连接已运行的Chrome
3.4 各平台Chrome数据目录
|
|
|
|---|---|
| Windows | C:\Users\<用户名>\AppData\Local\Google\Chrome\User Data\Default |
| macOS | ~/Library/Application Support/Google/Chrome/Default |
| Linux | ~/.config/google-chrome/Default |
四、内功对比:谁的技术栈更扎实?
4.1 架构一览
|
|
|
|
|
|---|---|---|---|
| Playwright |
|
|
|
| Agent-browser |
|
|
|
| Chrome-devtools-mcp |
|
|
|
| Browser-use |
|
|
|
4.2 调用流程对比
Browser-use(智能助手型):
用户(task) → Agent.run() → LLM.chat() → Tools.execute() → CDP → Chrome │ │ │ │ │ │ │ └─ CDP命令: DOM, Input, Runtime... │ │ └─ LLM API: OpenAI/Anthropic │ └─ 任务循环控制 └─ 纯Python调用
Chrome-devtools-mcp(MCP工具型):
用户(在Claude中说话) │ ▼MCP Server (@mcp.tool) → ChromeDevToolsClient → WebSocket → Chrome │ ├─ get_network_requests() ├─ get_console_logs() └─ execute_javascript()
Agent-browser(CLI极客型):
CLI命令 (agent-browser open xxx) │ ▼main.rs → commands.rs → actions.rs → CDP Client (Rust) → WebSocket → Chrome │ │ │ │ │ └─ click, type, scroll... │ └─ 命令路由 └─ 程序入口
Playwright(企业标准型):
用户代码 (page.click()) │ ▼Page API → ChannelOwner.invoke() → WebSocket → Server → CDP/BiDi → Chrome │ │ │ └─ JSON-RPC └─ TypeScript API
五、技术方案深度分析:像 Spring Boot 一样理解它
作为 Java/前端工程师,我们可以把浏览器自动化工具想象成一个前后端分离的系统:
┌─────────────────────────────────────────────────────────────────────┐│ 用户层 ││ (你说一句话 or 写一段代码) │└─────────────────────────────┬───────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────────┐│ 业务逻辑层 (类似 Controller/Service) │└─────────────────────────────┬───────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────────┐│ 协议层 (类似 HTTP Client / WebSocket) │└─────────────────────────────┬───────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────────┐│ 浏览器层 (类似 Database) │└─────────────────────────────────────────────────────────────────────┘
5.1 Browser-use:像 Spring Boot 一样的 AI Agent
像写 Spring Boot Controller 一样:
# 就像你写一个 Spring Boot Controllerfrom browser_use import Agent, BrowserSession, BrowserProfile# 1. 创建 Agent(像 @Autowired 一个 Service)agent = Agent( task="帮我搜索今天的科技新闻", # 任务指令 llm=AnthropicLLM() # 注入 LLM 客户端)# 2. 执行任务(像调用 service.run())result = await agent.run()
内部流程:像 Spring MVC 的请求处理
用户说 "帮我订机票" │ ▼┌─────────────────────────────────────────────────────────────────────┐│ Agent.run() ← 类似 Spring 的 @RequestMapping 方法 ││ │ ││ ├── 1. 获取页面状态 → BrowserSession.get_state() ││ │ │ ││ │ └── 类似: request.getParameter() ││ │ ││ ├── 2. 调用 LLM 思考 → llm.chat("任务是什么?该怎么做?") ││ │ │ ││ │ └── 类似: restTemplate.postForEntity("api/llm", ...) ││ │ ││ ├── 3. LLM 返回动作 → "点击搜索框,输入..." ││ │ │ ││ │ └── 类似: 返回 JSON 响应 ││ │ ││ └── 4. 执行动作 → Tools.execute(click, type...) ││ │ ││ └── 类似: service.doAction() │└─────────────────────────────┬───────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────────┐│ CDP 协议 ← 类似 JDBC / HttpClient ││ │ ││ ├── cdp_client.send(DOM.getDocument()) # 获取页面 ││ ├── cdp_client.send(Input.dispatchMouseEvent()) # 点击 ││ └── cdp_client.send(Runtime.evaluate()) # 执行JS ││ ││ 通信方式: WebSocket (类似 Socket.IO) │└─────────────────────────────┬───────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────────┐│ Chrome 浏览器 ← 类似 MySQL/Redis ││ │ ││ ├── 执行渲染 ││ ├── 执行 JavaScript ││ └── 返回结果 │└─────────────────────────────────────────────────────────────────────┘
核心概念对照
|
|
|
|
|---|---|---|
Agent |
@Service
|
|
BrowserSession |
Connection
|
|
LLM |
RestTemplate
|
fetch() |
cdp-use |
JDBC
|
|
Tools |
@Component
|
|
bubus (事件总线) |
ApplicationEvent |
|
5.2 Chrome-devtools-mcp:像 Spring MVC + WebSocket
架构图:像 Spring MVC + WebSocket
用户通过 Claude 对话 │ ▼┌─────────────────────────────────────────────────────────────────────┐│ MCP Server ← 类似 @RestController ││ │ ││ ├── @mcp.tool() ← 类似 @GetMapping/@PostMapping ││ ├── start_chrome() ← 启动 Chrome ││ ├── get_network_requests() ← 获取网络请求 ││ ├── get_console_logs() ← 获取 Console ││ └── execute_javascript() ← 执行 JS │└─────────────────────────────┬───────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────────┐│ ChromeDevToolsClient ← 类似 WebSocketClient (Socket.IO) ││ │ ││ ├── connect() → WebSocket 连接 ││ ├── send_command() → 发送 CDP 命令 ││ └── on_event() → 监听事件 │└─────────────────────────────┬───────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────────┐│ CDP 协议 ← 类似 WebSocket 消息 │└─────────────────────────────┬───────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────────┐│ Chrome 浏览器 │└─────────────────────────────────────────────────────────────────────┘
MCP 工具定义:像 Controller 方法
# 就像 Spring 的 Controllerfrom mcp.server.fastmcp import FastMCPmcp = FastMCP("Chrome DevTools MCP")# 类似 @GetMapping("/network")@mcp.tool()async def get_network_requests(filter_domain: str = None): """获取网络请求列表""" # 类似 service 方法 cdp_client = get_cdp_client() requests = cdp_client.send("Network.getRequests") return {"requests": requests}
5.3 Agent-browser:像命令行工具的架构
CLI命令 (agent-browser open xxx) │ ▼┌─────────────────────────────────────────────────────────────────────┐│ main.rs ← 程序入口 (类似 main 方法) ││ │ ││ └── parse_command() ← 解析命令 (类似 argparse) │└─────────────────────────────┬───────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────────┐│ commands.rs ← 命令处理 (像 Spring Controller) ││ │ ││ ├── open ← 子命令 ││ ├── click ← 子命令 ││ └── screenshot ← 子命令 │└─────────────────────────────┬───────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────────┐│ actions.rs ← 动作执行 (像 Service) ││ │ ││ ├── click_element() ││ ├── type_text() ││ └── navigate() │└─────────────────────────────┬───────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────────┐│ CDP Client (Rust) ← 类似 Rust 的 reqwest / tokio-tungstenite ││ │ ││ ├── WebSocket 连接 ││ └── 发送 CDP 命令 │└─────────────────────────────┬───────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────────┐│ Chrome 浏览器 │└─────────────────────────────────────────────────────────────────────┘
5.4 Playwright:像前后端分离的架构
用户代码 │ ▼┌─────────────────────────────────────────────────────────────────────┐│ Client (playwright-core) ← 类似前端 SDK ││ │ ││ ├── page.click() ← API (类似 axios.get()) ││ ├── page.fill() ← API ││ └── locator ← 类似 DOM 查询 │└─────────────────────────────┬───────────────────────────────────────┘ WebSocket / Pipe │ ▼┌─────────────────────────────────────────────────────────────────────┐│ Server/Driver (playwright-server) ← 类似后端服务 ││ │ ││ ├── 启动浏览器 ││ ├── 管理 BrowserContext ││ └── 协议转换 (CDP ↔ BiDi) │└─────────────────────────────┬───────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────────┐│ 浏览器 (Chromium/Firefox/WebKit) │└─────────────────────────────────────────────────────────────────────┘
TypeScript 代码示例:像前端调用 API
// 类似前端调用 APIimport { chromium } from 'playwright';// 1. 启动浏览器 (类似创建 HTTP Client)const browser = await chromium.launch();// 2. 创建页面 (类似打开新标签页)const page = await browser.newPage();// 3. 导航 (类似 fetch)await page.goto('https://example.com');// 4. 操作 (类似 DOM 操作)await page.click('button.submit');// 内部流程:// page.click() → ChannelOwner.invoke('click') → WebSocket → Server → CDP → Chrome
六、四兄弟性格分析
6.1 Playwright – 成熟稳重大哥
-
• 优点:文档齐全、生态丰富、跨语言跨平台(Chromium/Firefox/WebKit) -
• 缺点:默认隐藏窗口,得手动设置 -
• 适合:企业级项目、需要多浏览器兼容、自动化测试
6.2 Agent-browser – 速度担当
-
• 优点:Rust编写、启动飞快、CLI操作简洁 -
• 缺点: --headed参数有时不太听话,Cookie复用需要先关daemon -
• 适合:喜欢命令行的性能党、CI/CD集成
6.3 Chrome-devtools-mcp – 官富二代
-
• 优点:Claude Desktop 官方集成,调试超方便,默认显示UI -
• 缺点:没有 userDataDir 参数,只能连接已运行的Chrome -
• 适合:已经在用 Claude Code 的开发者、网页调试
6.4 Browser-use – 躺平族
-
• 优点:Python生态好、LLM集成丝滑、能自主决策多步骤任务 -
• 缺点:会”偷”用户目录(复制走),不能真正复用Cookie -
• 适合:不需要复用Cookie的LLM自动化场景、AI助手
七、实战代码:谁能帮你干活?
7.1 打开百度搜个东西
Browser-use(最智能):
from browser_use import Agent, ChatBrowserUsellm = ChatBrowserUse(model='bu-2-0')agent = Agent(task="打开百度搜索Python教程", llm=llm)await agent.run()
Playwright(最标准):
const browser = await chromium.launch();const page = await browser.newPage();await page.goto('https://www.baidu.com');await page.fill('#kw', 'Python 教程');await page.click('#su');
Agent-browser(最快):
agent-browser open "https://www.baidu.com/s?wd=Python"
Chrome-devtools-mcp(最简单):
# 告诉Claude:请打开百度
7.2 登录GitHub
Playwright:
const page = await browser.newPage();await page.goto('https://github.com/login');await page.fill('#login_field', '用户名');await page.fill('#password', '密码');await page.click('input[type="submit"]');
Agent-browser:
# 脚本方式agent-browser open "https://github.com/login"agent-browser fill "#login_field" "用户名"agent-browser fill "#password" "密码"agent-browser click "input[type=submit]"
八、使用方式:怎么调用它们?
8.1 browser-use:Python API
# 安装pip install browser-use# 环境配置export BROWSER_USE_API_KEY="your-api-key"
# 使用云端LLMfrom browser_use import Agent, ChatBrowserUsellm = ChatBrowserUse(model='bu-2-0')agent = Agent(task="打开百度搜索天气", llm=llm)await agent.run()# 或使用底层APIfrom browser_use import BrowserSessionsession = BrowserSession()await session.goto("https://www.baidu.com")
8.2 chrome-devtools-mcp:MCP + Claude
# 安装pip install chrome-devtools-mcp
配置 Claude Desktop:
{ "mcpServers": { "chrome-devtools": { "command": "python", "args": ["-m", "chrome_devtools_mcp"] } }}
然后直接告诉Claude:
"请帮我打开百度,搜索Python教程"
8.3 agent-browser:Rust CLI
# 安装npm install -g agent-browseragent-browser install# 核心命令agent-browser open <url> # 打开网页agent-browser click <sel> # 点击agent-browser fill <sel> <text> # 填写agent-browser screenshot <path> # 截图agent-browser get title # 获取标题
8.4 playwright:TypeScript/Python
# 安装npm install playwrightnpx playwright install chromium
import { chromium } from 'playwright';const browser = await chromium.launch();const page = await browser.newPage();await page.goto('https://www.baidu.com');await page.fill('#kw', 'Python');await page.click('#su');
九、执行用例:真刀真枪测试
测试时间:2026-03-28,测试环境:Windows 11,Chrome 120+
9.1 用例1:打开百度搜索
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9.2 用例2:打开天气网站
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9.3 用例3:表单填写
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9.4 用例4:截图保存
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9.5 用例5:获取页面标题
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Browser-use 因需要API key未能完成测试
十、使用场景:该选谁?
|
|
|
|
|
|---|---|---|---|
| AI自动化多步骤任务 |
|
|
|
| 网页调试/问题排查 |
|
|
|
| 自动化测试 |
|
|
|
| 数据采集/爬虫 |
|
|
|
| CLI脚本/快速验证 |
|
|
|
| 跨浏览器测试 |
|
|
|
| CI/CD集成 |
|
|
|
| Claude Code集成 |
|
|
|
十一、选型决策树
├── 任务需要AI自主决策?│ ├─ 是 → browser-use(内置LLM大脑)│ └─ 否│ ││ ├── 需要自动化测试?│ │ ├─ 是 → playwright(生态最全)│ │ └─ 否│ │ ││ │ ├── 需要调试网页?│ │ │ ├─ 是 → chrome-devtools-mcp(官方集成)│ │ │ └─ 否│ │ │ ││ │ │ └── 追求性能?│ │ │ ├─ 是 → agent-browser(Rust极速)│ │ │ └─ 否 → 根据语言偏好选择│ │ ││ │ └── 需要显示UI?│ │ ├─ 是 → chrome-devtools-mcp(默认显示)│ │ └─ 否│ ││ └── 需要Cookie复用?│ ├─ 是 → playwright(launchPersistentContext)│ └─ 否 → 随便选
十二、血泪教训
-
1. Chrome进程记得关:测试时残留进程会让你怀疑人生(累计关了50+个) -
2. 临时目录是默认:四个工具默认都用临时目录,不会复用你的登录状态 -
3. Browser-use 的套路:它真的会复制用户目录,用之前请三思 -
4. Agent-browser 要先关daemon:否则 --profile参数会被忽略
十三、实测速度对比
|
|
|
|
|
|---|---|---|---|
|
|
|
|
~0.8秒
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Agent-browser 打开百度仅需0.8秒,是真的快!
测试环境:Windows 11,Chrome 120+,Node.js 24,Python 3.13
夜雨聆风