一个 Chrome 扩展和 CLI,让你的 Agent 控制你的真实浏览器 —— 登录状态、扩展、Cookie 都已就绪。无需启动无头实例,不会被反爬虫检测,不占用额外内存。在 GitHub 上 Star。
其他浏览器 MCP 启动一个全新的 Chrome —— 没有登录状态、没有扩展、立即被反爬虫检测、双倍内存占用。RunBrowser 连接到你正在运行的浏览器。一个 Chrome 扩展,完整的 CDP 访问,你已经登录的所有网站。
快速开始
三步即可让你的 Agent 开始浏览。
- 安装 CLI:
npm i -g @jiweiyuan/runbrowser
-
在 Chrome 中加载扩展:打开
chrome://extensions/,启用开发者模式,点击加载已解压的扩展程序,选择packages/extension/dist文件夹 -
在标签页上点击扩展图标 —— 它会变成绿色。开始使用:
runbrowser navigate https://example.com runbrowser snapshot runbrowser click @e5
无需手动管理会话 —— 首次执行命令时自动创建会话。扩展将你的浏览器连接到 localhost:19988 上的本地 WebSocket 中继服务器。CLI 通过中继发送 CDP 命令。没有远程服务器、没有账户,一切都在你的机器上。
然后安装 skill —— 它会教你的 Agent 如何使用 RunBrowser:
npx -y skills add runbrowser/runbrowser
扩展图标绿色 = 已连接。灰色 = 未连接到此标签页。
工作原理
在标签页上点击扩展图标 —— 它通过 chrome.debugger 连接并打开一个 WebSocket 到本地中继。你的 Agent(CLI 或 MCP)连接到同一个中继。CDP 命令直接流过扩展到 Chrome —— 没有 Playwright,没有中间层。
┌─────────────────────┐ ┌──────────────────────┐ ┌─────────────────┐ │ BROWSER │ │ LOCALHOST │ │ CLIENT │ │ │ │ │ │ │ │ ┌───────────────┐ │ │ WebSocket Server │ │ ┌───────────┐ │ │ │ Extension │<───────┬───> :19988 │ │ │ CLI / MCP │ │ │ └───────┬───────┘ │ WS │ │ │ └───────────┘ │ │ │ │ │ /extension │ │ │ │ │ chrome.debugger │ │ │ │ │ v │ │ v │ │ v │ │ ┌────────────┐ │ │ ┌───────────────┐ │ │ CDPExecutor │ │ │ HTTP API │ │ │ │ Tab 1 (green) │ │ │ (direct CDP) │ │ │ /api/* │ │ │ │ Tab 2 (green) │ │ └──────────────────────┘ │ └────────────┘ │ │ │ Tab 3 (gray) │ │ │ │ └─────────────────────┘ Tab 3 not controlled └─────────────────┘
中继多路复用会话,因此多个 Agent 或 CLI 实例可以同时操作同一个浏览器。所有浏览器命令通过 CDP 直接执行 —— 无 Playwright 依赖。
人机协作
因为 Agent 在你的浏览器中工作,所以你可以协作。你能实时看到它做的一切 —— 每次点击都会在目标元素上显示绿色高亮,每个命令都会闪烁一个微妙的边框光晕。当它遇到验证码时,你来解决。当出现 Cookie 同意弹窗时,你点击通过。当 Agent 卡住时,你在该标签页上禁用扩展,手动修复问题,重新启用扩展,Agent 就能从中断处继续。
你不是在看远程屏幕或事后查看日志。你在共享浏览器 —— Agent 做重复性工作,你在需要人工干预时介入。
无障碍快照
你的 Agent 在操作之前需要看到页面。无障碍快照以文本形式返回每个可交互元素,并附带 @ref 标签。5–20KB 而非 100KB+ 的截图 —— 更便宜、更快,Agent 无需视觉能力即可解析。
runbrowser snapshot # 输出: # - banner: # - link "Home" @e1 # - navigation: # - link "Docs" @e2 # - link "Blog" @e3 # - main: # - heading "Welcome" @e4 # - button "Get started" @e5
每行末尾的 @ref 可以直接传给命令。将快照作为读取页面的主要方式。只在需要空间布局信息时才使用截图。
# 使用快照中的 ref 进行交互 runbrowser click @e5 runbrowser fill @e3 "搜索关键词" runbrowser get text @e4 # 仅过滤可交互元素 runbrowser snapshot -i # 限定到 CSS 选择器范围 runbrowser snapshot -S "main"
CLI 命令
RunBrowser 提供 50+ 命令,按类别组织。每个命令都支持 --json 输出和自动会话创建。
# 导航 runbrowser navigate https://example.com runbrowser back runbrowser forward runbrowser reload runbrowser close # 关闭会话 # 观察 runbrowser snapshot # 带 @refs 的无障碍树 runbrowser snapshot -i # 仅可交互元素 runbrowser screenshot shot.png # 保存截图 runbrowser get url # 当前 URL runbrowser get title # 页面标题 runbrowser get text @e5 # 元素文本内容 runbrowser get html @e5 # 元素 HTML runbrowser get attr @e5 --attr-name href # 属性值 runbrowser is visible @e5 # 检查元素状态 # 交互 runbrowser click @e5 # 点击元素 runbrowser dblclick @e5 # 双击 runbrowser fill @e3 "hello world" # 清空并填充输入框 runbrowser type "搜索关键词" # 在当前焦点处输入 runbrowser press Enter # 按键 runbrowser select @e5 "option-value" # 选择下拉选项 runbrowser check @e5 # 勾选复选框 runbrowser scroll down # 滚动方向 runbrowser hover @e5 # 悬停元素 runbrowser upload @e5 ./file.png # 上传文件 runbrowser drag @e1 @e2 # 拖拽 runbrowser viewport 1280 720 # 设置视口大小 # 等待条件 runbrowser wait @e5 # 等待元素可见 runbrowser wait 2000 # 等待毫秒 runbrowser wait --text "Welcome" # 等待文本出现 runbrowser wait --url "**/dashboard" # 等待 URL 模式 # 语义定位器 runbrowser find role button click --name "Submit" runbrowser find text "登录" click runbrowser find label "邮箱" fill "user@example.com" # 标签页和框架管理 runbrowser tab list # 列出所有标签页 runbrowser tab new https://example.com # 打开新标签页 runbrowser tab 2 # 切换到标签页索引 runbrowser frame "iframe#embed" # 切换到 iframe runbrowser frame main # 返回主框架 # 执行 runbrowser eval 'document.title' # 在浏览器中执行 JS runbrowser cdp Page.captureScreenshot '{}' # 原始 CDP 命令
热路径使用扁平命令。管理功能使用子分组。eval 用于其他一切。
站点命令
将任何网站变成一个 CLI 命令。站点命令是 TypeScript 插件,将导航、抓取和数据提取封装成可复用的命令。无需让 Agent 逐步导航、快照、解析 —— 运行一个命令,直接获得结构化 JSON。
# 获取 GitHub 热门仓库的结构化数据 runbrowser github trending --limit 5 # RANK NAME STARS LANGUAGE # --- ---- ----- -------- # 1 denoland/deno 5.2k Rust # 2 tauri-apps/tauri 3.8k Rust # 3 nickel-org/nickel 2.1k Rust # Agent 友好的 JSON 输出 runbrowser github trending --limit 3 --json
将 .ts 文件放入 ~/.runbrowser/commands/ 即可编写自定义命令。完整 TypeScript,完整 IDE 支持,无需 YAML 封装。
// ~/.runbrowser/commands/github/trending.ts export const description = 'GitHub trending repositories' export const columns = ['rank', 'name', 'stars', 'language'] export const args = { limit: { type: 'number', default: 20, description: 'Number of items' }, language: { type: 'string', description: 'Filter by language' }, } export async function run(ctx, args) { await ctx.navigate('https://github.com/trending') const data = await ctx.evaluate(` [...document.querySelectorAll('article.Box-row')].map(el => ({ name: el.querySelector('h2 a')?.textContent?.trim(), stars: el.querySelector('.octicon-star')?.parentElement?.textContent?.trim(), language: el.querySelector('[itemprop="programmingLanguage"]')?.textContent?.trim(), })) `) return data.slice(0, args.limit).map((item, i) => ({ rank: i + 1, ...item })) }
命令由中继服务器通过 jiti 加载 —— CLI 只是一个 HTTP 客户端。输出支持 --json、--csv、表格、markdown 和 YAML 格式。
TypeScript 插件。结构化数据。一个命令替代 导航 → 快照 → 解析。
命令扩展
从 runbrowser/commands 仓库安装社区维护的命令。无需克隆、无需构建 —— 安装即用。
# 列出可用的命令扩展 runbrowser commands list # Available command extensions: # # reddit # youtube # x ✓ installed # hackernews # producthunt # 安装一个扩展 runbrowser commands install reddit # ✓ Installed reddit/ # → ~/.runbrowser/commands/reddit/hot.ts # → ~/.runbrowser/commands/reddit/search.ts # 立即使用 runbrowser reddit hot --limit 5 runbrowser reddit search "浏览器自动化" # 卸载 runbrowser commands uninstall reddit # ✓ Uninstalled reddit/
社区命令以 TypeScript 文件的形式下载到 ~/.runbrowser/commands/<site>/。它们与自定义站点命令格式相同 —— 你可以查看、修改或 fork 它们。
工作原理: CLI 从 runbrowser/commands GitHub 仓库获取 .ts 文件并保存到本地。中继服务器在运行时通过 jiti 加载它们 —— 无需编译。每个扩展是一个包含一个或多个命令文件的目录。
贡献你自己的命令: 在 runbrowser/commands 仓库中创建一个目录,放入你的 .ts 文件并提交 PR。你的命令将通过 runbrowser commands install 对所有人可用。
一致的子命令模式。社区维护。与自定义命令相同的 TypeScript 格式。
会话
会话自动创建 —— 直接运行命令即可。对于高级用途,可以显式管理会话。
runbrowser session new # 创建会话,输出 id runbrowser session list # 显示会话和状态键 runbrowser session delete 1 # 删除会话
同时运行多个 Agent 而互不干扰。每个会话是一个隔离的沙箱,拥有自己的状态。浏览器标签页是共享的,但会话状态不是。
# 显式指定会话 runbrowser navigate https://a.com -s 1 runbrowser navigate https://b.com -s 2 # 或设置默认会话 export RUNBROWSER_SESSION=1 runbrowser snapshot # 使用会话 1
屏幕录制
让 Agent 录制它正在做的事情为 MP4 视频。录制使用 chrome.tabCapture 并在扩展上下文中运行,因此它在页面导航时不会中断。
# 开始录制 runbrowser record start -o recording.mp4 # 导航、交互 —— 录制跨页面持续 runbrowser navigate https://example.com runbrowser click @e5 # 停止并保存 runbrowser record stop # Recording saved: recording.mp4 # duration: 12.3s, size: 2.45 MB
对于自动录制(无需点击扩展图标),使用特殊标志重启 Chrome:
runbrowser config set profile "Profile 11" open -a "Google Chrome" --args --auto-accept-this-tab-capture --profile-directory="Profile 11"
原生标签页捕获。跨导航持久化。自动转码为 H.264 MP4。
MCP 集成
RunBrowser 使用双工具 MCP 模型 —— skill 和 run。没有工具膨胀,没有 schema 臃肿。
{ "mcpServers": { "runbrowser": { "command": "npx", "args": ["-y", "@jiweiyuan/runbrowser-mcp@latest"] } } }
Agent 调用 skill 学习可用命令,然后用 run 执行:
skill() → 返回完整 CLI 文档 + 站点命令
run({ command: "navigate https://example.com" })
run({ command: "snapshot" })
run({ command: "click @e1" })
run({ command: "eval document.title" })
run({ command: "github trending --limit 5" })
run 工具使用与 CLI 相同的语法。Agent 不需要学习单独的 API。
┌──────────────────────────────────────────────────────────────────────┐ │ MCP 客户端 │ │ (Claude, Cursor, Windsurf...) │ └──────────────┬──────────────────────────────┬────────────────────────┘ │ │ skill() run(command) │ │ v v ┌──────────────────────────────────────────────────────────────────────┐ │ RunBrowser MCP 服务器 │ │ │ │ ┌─────────────────┐ ┌──────────────────────────┐ │ │ │ skill 工具 │ │ run 工具 │ │ │ │ │ │ │ │ │ │ 返回 CLI │ │ 解析命令字符串 │ │ │ │ 文档 + 站点 │ │ 转发到中继服务器 │ │ │ │ 命令列表 │ │ 返回结果 │ │ │ └─────────────────┘ └────────────┬─────────────┘ │ │ │ │ └─────────────────────────────────────────────────┼───────────────────┘ │ HTTP / WS │ v ┌─────────────────────────┐ │ 中继服务器 :19988 │ │ CDPExecutor │ └────────────┬────────────┘ │ chrome.debugger │ v ┌─────────────────────────┐ │ 你的 Chrome 浏览器 │ └─────────────────────────┘
对比
为什么选择 RunBrowser 而不是其他方案。
| Playwright MCP | RunBrowser | |
|---|---|---|
| 浏览器 | 启动新 Chrome | 使用你的 Chrome |
| 扩展 | 无 | 你现有的扩展 |
| 登录状态 | 全新 | 已登录 |
| 反爬虫检测 | 总是被检测 | 可以绕过 |
| 协作 | 独立窗口 | 与用户共享浏览器 |
| BrowserUse | RunBrowser | |
|---|---|---|
| 语言 | Python | TypeScript / Node.js |
| 浏览器 | 启动新 Chrome(Playwright) | 使用你的 Chrome |
| 方式 | AI Agent 框架(LLM 自主决策) | CLI + MCP 工具(Agent 发送命令) |
| 登录状态 | 全新 | 已登录 |
| CLI | 无 | 有 —— 50+ 命令 |
| Agent Browser | RunBrowser | |
|---|---|---|
| 浏览器 | 启动无头 Chromium | 你正在运行的 Chrome |
| 命令数 | ~90(臃肿) | ~50(精简) |
| 命令扩展 | 无 | 有 —— 安装社区命令 |
| CLI | Rust CLI → Node 守护进程 | Node CLI → 中继(更简单) |
| 反爬虫检测 | 总是被检测 | 可以绕过 |
| 真实标签页 | 否 | 是 |
远程访问
在远程机器上控制 Chrome —— 无头 Mac mini、云 VM、开发容器。启动中继服务器并配置公开绑定和令牌。
# 在宿主机上 —— 启动中继服务器 runbrowser serve --host 0.0.0.0 --token <secret> # 从任何地方 —— 设置环境变量正常使用 export RUNBROWSER_HOST=192.168.1.10 export RUNBROWSER_TOKEN=<secret> runbrowser navigate https://example.com
也适用于开发容器和 Docker —— 使用 RUNBROWSER_HOST=host.docker.internal。MCP 同样适用 —— 在 MCP 客户端环境配置中设置 RUNBROWSER_HOST 和 RUNBROWSER_TOKEN。
安全性
一切都运行在你的机器上。中继绑定到 localhost:19988,只接受来自扩展的连接。没有远程服务器、没有账户、没有遥测。
- 仅限本地 —— WebSocket 服务器绑定到 localhost。没有任何数据离开你的机器。
- 来源验证 —— 只接受 RunBrowser 扩展的来源。浏览器无法伪造 Origin 头,因此恶意网站无法连接。
- 显式授权 —— 只有你点击了扩展图标的标签页才会被控制。没有后台访问。
- 可见的自动化 —— Chrome 在被控制的标签页上显示自动化横幅。每个 Agent 操作都有视觉反馈(绿色高亮)。