内容
# 无头浏览器使用
[English](https://github.com/flyingsquirrel0419/headless-use/blob/main/README.md) | [한국어](https://github.com/flyingsquirrel0419/headless-use/blob/main/README.ko.md) | [日本語](https://github.com/flyingsquirrel0419/headless-use/blob/main/README.ja.md) | [中文](https://github.com/flyingsquirrel0419/headless-use/blob/main/README.zh.md)
<p align="center">
<img src="https://raw.githubusercontent.com/flyingsquirrel0419/headless-use/main/docs/assets/demo.gif" alt="headless-use demo" width="720">
</p>
> 适用于网页开发代理的计算机使用工具,构建用于无头 Linux 和 CI。
`headless-use` 是一个轻量级浏览器运行时,允许 AI 编程代理**看到、使用和调试**他们构建的 Web 应用程序。它通过 Chrome DevTools 协议(CDP)驱动 Chrome,提供**实际输入事件** - 而不是 JavaScript `element.click()` - 并为代理提供基于截图的“计算机使用”和页面元素的标记轻量语义引用(`@g1:e1`、`@g1:e2`,...;`@eN` 作为简写)。
它是一个单独的 Rust 二进制文件,没有 Node.js 运行时,设计用于在无 GUI 的服务器、Docker 和 CI 上运行,无需 Xvfb。
---
## 为什么
浏览器自动化工具是为**测试脚本**构建的。代理需要**实时交互**:他们观察页面,决定下一步行动,并验证结果。标准工具以选择器为中心,仅限于 DOM,并让代理在每个步骤重新截图。`headless-use` 以代理为中心:
| 通用浏览器自动化 | headless-use |
| ------------------------------------- | ----------------------------------------- |
| 编写测试代码 | 实时代理操作 |
| CSS 选择器 | 坐标**和**语义引用 |
| 仅限 DOM | 截图 + DOM + 控制台 + 网络 |
| Node.js 依赖常见 | 单个 Rust 二进制文件 |
| 关注本地桌面 | 无头 Linux、Docker、CI 第一 |
## 30 秒快速入门
```bash
# 构建(单个二进制文件,无运行时依赖)
cargo build --release
# 诊断您的环境
./target/release/headless-use doctor
```
`serve` 启动一个长期会话,通过 stdin/stdout 进行换行分隔的 JSON-RPC 通信(stdout 仅携带**协议响应**;日志和横幅发送到 stderr)。将请求管道传输到一个进程 - 每个 `serve` 都拥有自己的浏览器:
```bash
# 打开页面,观察交互元素,单击引用,键入。
printf '%s\n' \
'{"id":1,"method":"browser.open","params":{"url":"http://localhost:3000"},"jsonrpc":"2.0"}' \
'{"id":2,"method":"observe","params":{},"jsonrpc":"2.0"}' \
'{"id":3,"method":"click","params":{"ref":"@g1:e1"},"jsonrpc":"2.0"}' \
'{"id":4,"method":"type","params":{"text":"user@example.com"},"jsonrpc":"2.0"}' \
'{"id":5,"method":"browser.close","params":{},"jsonrpc":"2.0"}' \
| ./target/release/headless-use serve --no-sandbox
```
`observe` 返回页面元数据以及交互元素,每个元素都有一个生成绑定引用(`ref`),`click`、`hover` 和 `screenshot` 接受该引用:
```json
{
"id": 2,
"result": {
"schemaVersion": 1,
"page": { "url": "http://localhost:3000/", "title": "로그인", "viewport": { "width": 1280, "height": 720 } },
"elements": [
{ "ref": "@g1:e1", "ref_id": 1, "role": "textbox", "name": "이메일" },
{ "ref": "@g1:e2", "ref_id": 2, "role": "textbox", "name": "비밀번호" },
{ "ref": "@g1:e3", "ref_id": 3, "role": "button", "name": "로그인" }
],
"generation": 1
},
"jsonrpc": "2.0",
"schemaVersion": 1
}
```
(元素携带更多字段 - 边界框、`visible`、`enabled`、`checked`、`value`、`selectorHint` - 为简洁起见在此修剪。裸 `@eN` 形式被接受为简写,但只有完整的 `@g<gen>:eN` 形式才能检测导航后的过时引用。)
有两个成本是可选的,以保持默认路径的轻量:
- `observe` 启用 `"listeners": true` 还会通过 CDP 检测编程附加的单击监听器(每个候选元素最多两个额外的 CDP往返)。
- `click` 启用 `"effects": true` 会在 300 毫秒内采样单击后效果(`dom_mutations`、`network_requests`、`navigated`、`focus_changed`);如果不启用,则 `effects` 为 `null`,仅运行廉价的预单击命中测试。
## 一次性模式
```bash
# 打开 URL 并保存截图,然后退出。
./target/release/headless-use run --url https://example.com --screenshot out.png
```
## 安装
### 已发布的软件包
```bash
# 通过 npm 在 Linux x86_64 上安装二进制文件(主机上需要 Chrome/Chromium)
npm install --global headless-use
# 从 crates.io 构建并安装(主机上需要 Chrome/Chromium)
cargo install headless-use --locked
# 包含 Chromium 的容器
docker pull ghcr.io/flyingsquirrel0419/headless-use:1.0.0
# 镜像:docker pull flyingsquirrel0419/headless-use:1.0.0
```
预构建的存档和 SHA-256 校验和附在 [GitHub Releases](https://github.com/flyingsquirrel0419/headless-use/releases) 上。GitHub 还为每个发布标签提供完整的源代码 zip 和 tar.gz 存档。目前仅支持 Linux x86_64 的预构建 v1 软件包。
### 从检查点
```bash
cargo install --path .
# 需要 PATH 上的 Chrome/Chromium,或设置 HEADLESS_USE_BROWSER_PATH。
```
### 浏览器发现
`headless-use` 按以下顺序查找浏览器:
1. `HEADLESS_USE_BROWSER_PATH` 环境变量
2. `chrome-headless-shell`、`chromium-headless-shell`、`chromium`、`chromium-browser`、`google-chrome`、`google-chrome-stable` 在 `PATH` 上
使用 `--stealth` 时,顺序会颠倒:无头 shell 最后被尝试,因为它们缺少浏览器 API,而 bot 检查读取的内容(参见 [隐身模式](#隐身模式))。
显式覆盖:
```bash
headless-use launch --browser-path /opt/chrome-headless-shell
```
### Docker
```bash
docker pull ghcr.io/flyingsquirrel0419/headless-use:1.0.0
# 镜像包含 Chromium 并以非 root 用户身份运行,工作目录为 /home/hu。挂载一个可写的目录用于输出(先创建 mkdir -p output):
docker run --rm --network host --shm-size=1g \
--security-opt seccomp=unconfined \
-v "$PWD/output:/home/hu/output" \
ghcr.io/flyingsquirrel0419/headless-use:1.0.0 \
run --url http://127.0.0.1:3000 --screenshot output/page.png --no-sandbox
```
> **沙盒注意:** Chromium 拒绝在没有 `--no-sandbox` 的情况下以 root 身份运行;当进程以 root 身份运行时(常见于 CI 容器),`headless-use` 会自动应用它。发布的 Dockerfile 以非 root 用户身份运行,默认的 Docker seccomp 配置文件仍可能与 Chromium 的沙盒冲突 - 因此上面的 `--security-opt seccomp=unconfined` 加上 `--no-sandbox`。对于受信任的生产使用,建议保持沙盒开启并调整 seccomp。参见 [SECURITY.md](https://github.com/flyingsquirrel0419/headless-use/blob/main/SECURITY.md)。
## 稳定性:v1 保证的内容
**核心浏览器控制 API 自 v1.0.0 起稳定**,并遵循 semver:
- CLI 子命令 `serve`、`run`、`mcp`、`launch`、`doctor`、`install-browser`
- JSON-RPC 方法 `browser.open`/`page.goto`、`observe`、`click`、`hover`、`mouse.*`、`scroll`、`type`、`insert-text`、`key.*`、`wait`、`screenshot`、`console`、`network`、`evaluate`、`url`、`title`、`browser.close`
- 相应的 MCP `browser_*` 工具
- 错误模型(代码是稳定字符串)和响应信封(`jsonrpc`、`schemaVersion` - 结果形状仅增加字段)
**实验性** - 今天已可用,但形状和默认值可能会在小版本中更改,并且不涵盖 v1 稳定性保证:
- **实时查看器** (`view`、`--viewer-*` 标志、MJPEG 流)
- **跟踪 + 重放** (`trace.start`/`trace.stop`/`replay`、`actions.jsonl`、`report.html`)
- **隐身模式** (`--stealth`) - 指纹抑制本质上是一场军备竞赛
- **Dewiggle** (`dewiggle`、`dewiggle` 方法/工具)
## 支持的功能
- **真实输入**:`Input.dispatchMouseEvent`、`dispatchKeyEvent`、`insertText`
- **鼠标**:移动、单击(左/右/中/后/前)、双击/三击、按下/释放、悬停、滚轮滚动、拖动(插值)、拖动路径
- **键盘**:按下/释放/按下、和弦(`Control+Shift+P`)、键入、插入文本(CJK/emoji 安全)、按住、重复
- **观察**:基于 DOM 的交互元素提取、语义 `@g<gen>:eN` 引用(生成绑定以检测过时)、边界框、过时引用检测任意导航;按需监听器扫描(`"listeners": true`)提升具有编程附加单击处理程序的元素并标记 `opaqueInteractive` 表面
- **单击报告**:每个单击返回预单击命中测试;按需(`"effects": true`)单击后效果采样检测无效单击
- **诊断**:控制台 + 未捕获错误、网络(CDP `Network.*` 事件 - 不是 JS monkey-patching)带有秘密掩蔽、等待稳定(基于活动时间戳,捕获子轮询请求)
- **截图**:视口、全页、元素区域(`--element @g1:e3`)
- **Dewiggle** *(实验性)*:使用 **仅像素** 反转动画文本验证码中的每个字形垂直摆动 - 无答案数组,无 DOM 文本/属性。捕获 N 个帧,每个柱子对齐到其中性基线,并平均成锐化图像以及可选的每个字形裁剪。`headless-use dewiggle --url ... --out out.png --chars 6`
- **隐身** *(实验性)*:`--stealth` 保持 `--headless=new` 但停止它宣布自己 - 参见 [隐身模式](#隐身模式)
- **会话**:长期 `serve`(JSON-RPC stdio)、一次性 `run`
- **跟踪 + 重放** *(实验性)*:`actions.jsonl`、`report.html`(自包含、嵌入截图)、强制秘密在编写器边界处涂红,以及 `replay` 以重执行记录的跟踪
- **MCP 服务器**:符合规范的 `initialize`/`tools/list`/`tools/call` via stdio
## MCP 服务器
`headless-use mcp` 在 stdio 上运行符合规范的 MCP 服务器(协议版本 `2024-11-05`):
```bash
headless-use mcp --no-sandbox
```
服务器宣传 19 个 `browser_*` 工具,带有类型化的 `inputSchema`。截图结果作为 MCP 图像块返回;其他一切都返回紧凑的 JSON 文本块。错误返回 `isError: true` 并附有恢复提示。
### Claude Desktop / Cursor 配置
将以下内容添加到您的 MCP 客户端配置中:
```json
{
"mcpServers": {
"headless-use": {
"command": "/usr/local/bin/headless-use",
"args": ["mcp", "--no-sandbox"]
}
}
}
```
### 协议流程
```
client → initialize {protocolVersion, capabilities}
server ← {protocolVersion, capabilities, serverInfo}
client → notifications/initialized
client → tools/list
server ← {tools: [...19 browser_* tools...]}
client → tools/call {name: "browser_observe", arguments: {}}
server ← {content: [{type:"text", text:"{...elements...}"}], isError: false}
```
## CLI 参考
```
headless-use
├── launch 启动浏览器并保持运行
├── serve 启动长期 JSON-RPC 会话 via stdio
├── run 运行一次性操作并退出
├── dewiggle (实验性) 捕获动画文本区域并反转每个字形摆动(仅像素)
├── view (实验性) 提供实时查看器 + JSON-RPC 会话(参见下文)
├── replay (实验性) 从运行目录重执行记录的跟踪
├── doctor 诊断环境
├── install-browser 打印浏览器安装指南
└── mcp 启动 stdio 上的 MCP 服务器
```
```bash
# 反转动画文本验证码中的摆动,保存 6 个字形裁剪。
headless-use dewiggle --url https://example.com/captcha --out out.png --chars 6 --frames 12
```
### 隐身模式(实验性)
站点在 bot 检查(Cloudflare Turnstile 等)后面提供一个挑战,无头 Chrome 接受挑战,而有头 Chrome 直接通过。 `--stealth` 弥补了差距而不支付真正的显示器 - 它适用于 `launch`、`serve`、`run`、`view` 和 `mcp`:
```bash
headless-use run --url https://example.com/protected --screenshot out.png --stealth
headless-use serve --stealth --no-sandbox
```
它更改的内容,按相关顺序:
| 层 | 移除信号 |
| --- | --- |
| 启动标志 | `navigator.webdriver`(via `--disable-blink-features=AutomationControlled`)、UA 字符串中的 `HeadlessChrome/…` |
| `Emulation.setUserAgentOverride` | `Sec-CH-UA: "HeadlessChrome"` 客户端提示头和 `navigator.userAgentData` - 标志本身不修复这些 |
| 预加载脚本 | SwiftShader WebGL 驱动程序字符串、空 `navigator.plugins`、缺少 `window.chrome`、`outerHeight == innerHeight`、屏幕大小为窗口大小、 `notifications: denied` |
| 自动附加 | 相同的处理跨源 iframe,这是挑战小部件运行的位置 |
用户代理源自浏览器自己的版本,因此 UA、客户端提示品牌列表和引擎都同意。每个替换函数都报告原生源(`function … () { [native code] }`),包括此工具自己的控制台/网络收集器 - 包装的 `fetch` 本身就是一个信号。
注意:
- 隐身模式更喜欢 **完整** 的 Chrome/Chromium 而不是 `chrome-headless-shell`。shell 没有 `window.chrome`、没有 PDF 插件条目和专有编解码器;这些不能令人信服地伪造。如果仅有 shell 可用,则会发出警告。
- `--stealth` 更改两个默认值:滚动条不再隐藏(零宽度滚动条是文档化的检查)和 GPU 进程保持活动,以便 WebGL 存在(没有 WebGL 就像软件渲染器一样响亮);
- 两个默认值在 `--stealth` 下会发生变化:滚动条不会被隐藏(文档化的检查),GPU 进程保持活动,以便 WebGL 存在(没有 WebGL 就像没有软件渲染器一样)。如果仍然受到挑战, `--compat xvfb` 运行一个真正的无头浏览器在 Xvfb 下,大约需要双倍的内存。
### 实时查看器(实验性)
```bash
headless-use view --no-sandbox # 打印 http://127.0.0.1:7780/?token=…
```
`view` 表现与 `serve` 完全相同(stdio 上的 JSON-RPC),并额外提供带有代理光标叠加的页面 MJPEG 流。
**访问令牌。** 每次运行都会生成一个令牌,作为 stderr 中的 URL 的一部分打印出来(stdout 是 JSON-RPC 通道)- 以打印的 URL 开启。将其固定在 `--viewer-token <TOKEN>` 处,当 URL 必须保持稳定时。是否强制执行取决于绑定地址:
| `--viewer-host` | 请求中没有有效的 `?token=` |
| --- | --- |
| 环回(`127.0.0.1`,默认) | 提供 - 接受令牌但可选 |
| 其他任何地方(`0.0.0.0`,LAN 地址) | `401 Unauthorized` |
```bash
headless-use view --viewer-host 0.0.0.0 --viewer-token "$(openssl rand -hex 16)"
```
**光标运动。** `view` 默认 `--cursor-motion smooth`:光标移动到单击/悬停目标,发出真正的中间 `mouseMoved` 事件。这是使流可读的原因,也驱动了需要实际运动的悬停菜单。它的成本是每个单击的旅行时间(~220ms),因此 `serve`/`run`/`mcp` 默认使用 `instant`。在任一方向覆盖:
```bash
headless-use view --cursor-motion instant # 最快,光标传送
headless-use serve --cursor-motion smooth # 较慢,悬停菜单友好
```
> **暴露注意:** 查看器默认绑定到 `127.0.0.1`。 `--viewer-host 0.0.0.0` 将其公开给网络,在那里令牌是 URL 中的一个凭证,因此它会出现在 shell 和浏览器历史记录中,以及 `Referer` 头中,而流本身是纯 HTTP 的 - 任何获得该 URL 的人,或可以监视流量的人,都会看到页面显示的内容,包括登录内容。隧道或在不受信任的网络上前面加 TLS。参见 [SECURITY.md](https://github.com/flyingsquirrel0419/headless-use/blob/main/SECURITY.md)。
`serve` 接受 JSON-RPC 方法,包括:`browser.open`(别名 `page.goto`)、`observe`、`screenshot`、`click`、`hover`、`mouse.move`、`mouse.down`、`mouse.up`、`scroll`、`mouse.drag`、`mouse.drag_path`、`type`、`insert-text`、`key.press`、`key.down`、`key.up`、`wait`、`console`、`network`、`evaluate`、`url`、`title`、`browser.close`,以及实验性的 `dewiggle`、`trace.start`、`trace.stop` 和 `replay`。添加 `--json` 以启动/运行以获取机器输出(在 `view` 上,`--json` 查看器横幅打印到 stderr - stdout 保持协议专用)。
## 限制
- 跨源 iframe 交互受到限制;会返回已记录的错误。
- 操作系统级别的 IME 编组未完全模拟;CJK/表情符号使用 `Input.insertText`。
- Firefox/WebKit 超出初始范围(仅限 Chromium)。
- 自动浏览器下载(`install-browser`)打印指导信息而不是获取。
- 触摸输入(`touch tap`,`touch swipe`)在结构上得到支持,但不在 MVP CLI 中。
## 它与 Playwright/Puppeteer 的区别
`headless-use` **不** 包装 Playwright。它直接通过 WebSocket 与 CDP 通信,
拥有进程生命周期(临时配置文件清理、防止僵尸进程、信号处理),
并公开基于代理的 API(引用 + 观察 + 结构化错误)。它可以
与 Playwright 一起用于兼容性检查,但不是 Playwright 包装器。
## 路线图
- `report.html` 交互式时间线
- HTML5 文件拖放与 MIME 处理
- `install-browser` 校验和验证
## 安全
参阅 [SECURITY.md](https://github.com/flyingsquirrel0419/headless-use/blob/main/SECURITY.md)。要点:CDP 仅绑定到 `127.0.0.1`,
跟踪中会屏蔽密钥(包括自动检测密码字段),
代理提供的 file 路径(`trace.start`,`replay`)仅限于工作目录,
Chrome 站点隔离保持开启,并且在导航时强制执行主机允许/拒绝策略(`--allow-host`/`--deny-host`)—
这也限制导航到 `http`/`https`,因此 `file:`/`data:`/`javascript:` URL 不能绕过主机规则。实时查看器仅限环回,
除非您使用 `--viewer-host` 放宽限制,并且非环回绑定需要 `?token=` 访问令牌(`--viewer-token`);
在环回时,令牌被接受但不被要求。
## 社区
- [贡献](https://github.com/flyingsquirrel0419/headless-use/blob/main/CONTRIBUTING.md) — 开发设置、代码标准、PR 流程
- [发布指南](https://github.com/flyingsquirrel0419/headless-use/blob/main/docs/releasing.md) — 发布、Actions Secrets、源代码
- [行为准则](https://github.com/flyingsquirrel0419/headless-use/blob/main/CODE_OF_CONDUCT.md) — 社区标准
- [安全策略](https://github.com/flyingsquirrel0419/headless-use/blob/main/SECURITY.md) — 漏洞报告
- [变更日志](https://github.com/flyingsquirrel0419/headless-use/blob/main/CHANGELOG.md) — 发布历史
- [讨论](https://github.com/flyingsquirrel0419/headless-use/discussions) — 问题和想法
## 许可证
根据 Apache License, Version 2.0 授权。参阅 [LICENSE](https://github.com/flyingsquirrel0419/headless-use/blob/main/LICENSE)。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器