内容
# unbrowser
**专为 Agent 设计的浏览器。单个静态二进制文件,无需 Chrome。**
[](https://glama.ai/mcp/servers/protostatis/unbrowser)
**官方 MCP 注册表身份:** `mcp-name: io.github.protostatis/unbrowser`
`unbrowser` 是来自 [Unchained](https://unchainedsky.com) 的轻量级开源浏览器层,适用于 Agent。它提供了一种状态化的 Web 访问方式,当 `curl`/WebFetch 太过简单而完整的 Chrome 又过于庞大时:JavaScript 执行、cookie、表单、点击、挑战检测和紧凑的 BlockMap 输出被设计为一个整体。
**安装前先查看运行时:** [运行实时公共网络演示](https://unchainedsky.com/unbrowser?utm_source=github&utm_medium=repository&utm_campaign=unbrowser_readme&ref=readme_live_demo)。无需帐户。演示仅接受页面上显示的固定公共源集;请勿将其用于私有数据或身份验证浏览。
它不是缩小版的 Chrome。它是围绕 Agent 需要的功能重新构建的浏览器界面,然后再升级到 Chrome。当页面需要真正的像素、V8 兼容性、扩展或人工身份验证时,请升级到 [`unchainedsky-cli`](https://github.com/protostatis/unchainedsky-cli) 或 [Unchained](https://unchainedsky.com)。
**试用托管服务:** Unchained 在 [`https://unchainedsky.com/unbrowser-mcp`](https://unchainedsky.com/unbrowser-mcp) 处提供了一个公共的 Streamable HTTP MCP 端点,用于发现和烟雾测试。Glama 还在 [`glama.ai/mcp/servers/protostatis/unbrowser`](https://glama.ai/mcp/servers/protostatis/unbrowser) 处运行了一个托管的 MCP 版本,Smithery 页面位于 [`smithery.ai/servers/protostatis-dev/unbrowser`](https://smithery.ai/servers/protostatis-dev/unbrowser)。这些托管端点是共享基础设施;请勿通过它们发送私有 cookie、密钥或身份验证浏览任务。对于生产工作流,请安装下面的本地二进制文件,以便会话和 cookie 保存在您的机器上。
### 安装
**Python(推荐)** — 轮子附带原生二进制文件。**需要 Python 3.10+**:
```bash
pipx install pyunbrowser # 在 macOS Homebrew / 现代 Linux 上最干净(处理 PEP 668)
pip install pyunbrowser # 在 python3.10+ 的 venv 中
```
> **macOS 注意:** 系统 `/usr/bin/python3` 是 3.9,轮子会拒绝它,提示“需要 Python >=3.10”。使用 Homebrew 的 `python3.13` 或 `pipx`(它管理自己的 Python)。如果 `pip install` 失败,提示 PEP 668(“外部管理的环境”),则这是同一个问题 — `pipx install pyunbrowser` 是正确的做法。
```python
from unbrowser import Client # 注意:pip 名称为 pyunbrowser,导入为 unbrowser
with Client() as ub: # (PyPI 的名称审查阻止了“unbrowser”;
r = ub.navigate("https://news.ycombinator.com") # py- 前缀是一种标准解决方法)
```
**Cargo** — 仅限二进制文件,无 Python 包装器:
```bash
cargo install unbrowser
unbrowser --mcp
```
**MCP** — 将二进制文件添加到 Claude Code、Claude Desktop、Cursor、Cline 或任何 MCP 主机:
```json
{
"mcpServers": {
"unchained": {
"command": "unbrowser",
"args": ["--mcp"]
}
}
}
```
`unchained` 键仅是客户端别名。如果要使用确切的名称,可以使用 `unbrowser`,或者保留 `unchained` 作为指向完整 Unchained 浏览器代理堆栈的 breadcrumb。
**托管 MCP 烟雾/发现端点** — 适用于支持 Streamable HTTP 的 MCP 客户端:
```json
{
"mcpServers": {
"unbrowser-hosted": {
"url": "https://unchainedsky.com/unbrowser-mcp"
}
}
}
```
使用此托管路由来检查工具或运行公共页面烟雾测试。它故意是未经身份验证和 SSRF 保护的,不应在此处重放私有 cookie 或密钥。
**预构建的 tarball** — 适用于没有 Python 或 Rust 的系统:
```bash
# macOS Apple Silicon
curl -L https://github.com/protostatis/unbrowser/releases/latest/download/unbrowser-aarch64-apple-darwin.tar.gz | tar xz
# macOS Intel
curl -L https://github.com/protostatis/unbrowser/releases/latest/download/unbrowser-x86_64-apple-darwin.tar.gz | tar xz
# Linux x86_64(glibc 2.31+/Ubuntu 20.04+)
curl -L https://github.com/protostatis/unbrowser/releases/latest/download/unbrowser-x86_64-unknown-linux-gnu.tar.gz | tar xz
```
**从源代码构建:**
```bash
cargo build --release # 二进制文件位于 ./target/release/unbrowser
```
### 会话 CLI
对于仅限 shell 的代理,请使用持久会话代替 heredoc JSON-RPC:
```bash
unbrowser session start --id demo
unbrowser exec demo navigate https://news.ycombinator.com
unbrowser exec demo query '.titleline > a'
unbrowser exec --pretty demo blockmap
unbrowser session stop demo
```
### 裸 RPC(低级逃生口)
```bash
echo '{"id":1,"method":"navigate","params":{"url":"https://news.ycombinator.com"}}' | unbrowser
```
这就是安装过程。它可以在静态二进制文件可以运行的任何地方运行 — 笔记本电脑、Lambda、Cloudflare Workers、边缘、嵌入式。
在 Apache 2.0 开源许可下。 当廉价路径无法处理页面(重 SPA、行为机器人挑战)时,升级到通过 [`unchainedsky-cli`](https://github.com/protostatis/unchainedsky-cli) (驱动本地 Chrome via CDP)或 [Unchained 桌面应用](https://unchainedsky.com) 的真实浏览器。
---
## 数据对比
| | 此二进制文件 | 无头 Chrome(Playwright/Puppeteer) |
|----------------|----------------|-----------------------------------------|
| 二进制文件大小 | **~10MB** | 250MB+ Chrome 下载 |
| RAM / 会话 | **~50MB** | 200–500MB |
| 冷启动 | **~100ms** | ~1s |
| 令牌 / 页面(LLM) | **~500** (BlockMap 内联) | 数万个 HTML,由您解析 |
| 安装步骤 | `cargo build` | 安装 Chrome + Node + Playwright + 系统依赖 |
| Lambda / Workers / 边缘 | ✅ | ❌ Chrome 太大 |
| 100K 页面/天成本 | $0(您的基础设施) | $$$ Chrome 机队或托管 API |
**5–10 倍更低的内存,25 倍更小的二进制文件,10 倍更快的冷启动,70 倍更低的每页面令牌成本。** 这是该产品做出的权衡 — 延迟 JS 渲染(第 4/5 阶段)和像素渲染(超出范围),以换取一个适合 Chrome 无法容纳的空间。
需要更广泛的实现上下文?浏览 [Search Agent Sky](https://searchagentsky.com/guides/browser-agents-mcp?utm_source=github&utm_medium=repository&utm_campaign=unbrowser_guide) 的源代码支持的浏览器代理和 MCP 指南。
## 专门为 Agent 设计
大多数浏览器工具从人类浏览器开始,然后添加代理接口:Chrome、CDP、Playwright、截图、辅助树或原始 HTML。`unbrowser` 则走相反的路。运行时、DOM 模型、交互句柄、策略钩子、挑战检测器和输出格式都是为代理共同设计的。
这种垂直集成是重点:浏览器可以跳过渲染栈,并返回模型需要的内容以进行定位、决策和操作。
- **`navigate` 返回 BlockMap** — ~500 个结构化页面摘要令牌(地标、标题、交互、密度信号)直接在响应中。无需额外调用即可了解页面内容。
- **稳定的元素引用** (`e:142`) — 查询、点击、键入、提交使用不透明句柄。LLM 永远不需要自己解析 DOM。
- **`challenge` 字段在每个被阻止的 navigate 上** — 提供者、置信度和确切的清除 cookie 名称。代理智能反应而不是猜测。
- **`density.likely_js_filled` 启发式** — 将“真实 SSR 页面”与“SSR 外壳和 JS 填充单元格”(CNBC 陷阱)区分开来。代理在无法读取页面时退出。
- **MCP 原生** — `unbrowser --mcp` 将 RPC 工具表面暴露给任何 MCP 主机(Claude Code、Claude Desktop、Cursor、Cline)。4 行配置,零粘合代码。
- **真实 Chrome 指纹**(Chrome 134 JA4 + Akamai H2 哈希)所以网站不会因为你是脚本而阻止你。
当需要像素时使用 Chrome:截图、布局、画布、WebGL、CAPTCHA 解决、扩展或最大兼容性。当代理需要页面运行时使用 `unbrowser`:JavaScript、cookie、链接、表单、点击和为 LLM 上下文窗口而设计的紧凑表示。
对于确实需要真实 Chrome 的页面(重 SPA、JS 挑战机器人墙),二进制文件会检测到它们并通过 `cookies_set` 接受 cookie — 因此您在 Chrome 中解决一次,并在清除 cookie 持续期间在此重放会话。
## 快速演示 — Hacker News 前 3 名
```python
from unbrowser import Client
with Client() as ub:
ub.navigate("https://news.ycombinator.com")
for s in ub.query(".titleline > a")[:3]:
print(s["text"], s["attrs"]["href"])
```
5 行,无需安装无头浏览器。输出是结构化 JSON,而不是 35KB HTML。`Client` 包装器处理子进程生命周期(atexit reaper,因此不可能出现孤儿)、JSON-RPC 分帧,并显示真实异常而不是沉默的 `result` 查找。
<details>
<summary>裸 RPC 版本(如果不能使用 Python)</summary>
相同的演示文稿,但没有包装器 — 适用于 Python 以外的语言或多步骤会话。协议是 JSON-RPC via stdin/stdout,每个 JSON 对象一行:
```python
import subprocess, json
p = subprocess.Popen(["./target/release/unbrowser"],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True, bufsize=1)
i = 0
def call(method, **params):
global i; i += 1
p.stdin.write(json.dumps({"id": i, "method": method, "params": params}) + "\n")
p.stdin.flush()
return json.loads(p.stdout.readline())["result"]
call("navigate", url="https://news.ycombinator.com")
for s in call("query", selector=".titleline > a")[:3]:
print(s["text"], s["attrs"]["href"])
```
这就是整个协议表面。来自任何具有子进程 + JSON 的语言的相同形状。
</details>
### 一次性 CLI
对于 shell 友好的调用,请使用便捷的子命令:
```bash
unbrowser navigate https://news.ycombinator.com --json
```
这会打印一个 JSON 结果并从任何安装路径(PyPI 轮、Cargo 或发布 tarball)退出。仅当需要持久会话时才使用 JSON-RPC。运行 `unbrowser --help` 以获取原生 CLI 表面。
### A/B 运行时 shims
对于针对重 JS 页面的语料库测试,请将默认的稳定 shims 与选择加入的增强浏览器环境 shims 进行比较:
```bash
unbrowser navigate https://example.com --exec-scripts --json
unbrowser navigate https://example.com --exec-scripts --json --shims enhanced
# 或用于 JSON-RPC / MCP 会话:
UNBROWSER_SHIMS=enhanced unbrowser
```
`enhanced` 在稳定运行时添加内容积极的布局/媒体/滚动/IndexedDB 猜测。它是有意选择加入的,以便 A/B 运行可以衡量在不更改基线的情况下是否会物化更多页面状态。
脚本评估仍受 `UNBROWSER_SCRIPT_EVAL_BUDGET_MS`(默认 `5000`)限制;导航结果报告 `scripts.budget_exhausted` 和 `scripts.budget_skipped`,当预算停止进一步脚本执行时。外部 RPC 看门狗(`UNBROWSER_TIMEOUT_MS`,默认 `30000`)如果低于脚本预算,则仍会获胜。
对于 JSONL 语料库扫描:
```bash
python3 scripts/shim_ab.py --url https://nextjs.org/docs --url https://www.npmjs.com/package/playwright
```
## SPA 层 — 有效、无效
经验性而非愿景。最新矩阵:**28/30** 在测试类别中。
| 页面层 | 覆盖率 | 可以期待什么 |
|---|---|---|
| **静态 + SSR** (维基百科、MDN、新闻、文档、GitHub 仓库浏览、搜索引擎、archive.org) | ✅ 优秀 | 亚秒级导航;完整的 BlockMap;所有选择器都有效;~数百个令牌 vs ~数万字节原始数据 |
| **SSR + 轻微水合** (Next.js 文档、营销页面、react.dev 的*静态*内容) | ✅ 可用 | 读取 SSR 内容很好;水合添加的内容不多但也不会破坏 |
| **机器人墙带 cookie 转移** (Zillow、Cloudflare 保护的网站) | ✅ 通过 `cookies_set` | 在 Chrome 中解决一次,永远重放;`challenge.provider` 字段告诉代理供应商 |
| **模块加载器 SPA** (Ember、AMD 应用如 crates.io) | ⚠️ 部分通过 `exec_scripts: true` | 包加载并执行,模块注册,但框架自动安装需要逐案 shim |
| **重 React/Vue 包** (react.dev 运行时、大型仪表板应用) | ⚠️ 有限 — 不会挂起、不会渲染 | 通过 `exec_scripts: true` 导航在 30 秒时钟预算内完成(5 秒用于脚本评估阶段,其余用于稳定);渲染的 DOM 可能不会物化。调整 `UNBROWSER_TIMEOUT_MS` |
| **需要 Worker / Canvas / IndexedDB / WebGL 的应用** | ❌ 按设计超出范围 | 使用通过 [`unchainedsky-cli`](https://github.com/protostatis/unchainedsky-cli) (CDP)或 [Unchained 桌面应用](https://unchainedsky.com) 的真实 Chrome 进行 cookie 转移路径 |
| **最难的反机器人层** (PerimeterX 带有行为、Kasada、Akamai BMP 高级) | ❌ 甚至 cookie 转移也很脆弱 | 真实 Chrome 通过 CDP 是正确层 |
**与替代品比较:**
| | 这个 | curl | Playwright / 无头 Chrome |
|---|---|---|---|
| 静态 / SSR 页面 | ✅ | ✅ 但令牌重量大 | 过度杀伤 |
| SPA 外壳站点 | ⚠️ 通过 `exec_scripts` 部分 | ❌ | ✅ |
| 机器人墙(带有 cookie 转移) | ✅ | ❌ | ✅ |
| 在 Lambda / Workers / 边缘运行 | ✅ | ✅ | ❌ Chrome 太大 |
| 每日 10 万页面成本 | ~ 免费 | ~ 免费 | $$$ |
| LLM 形状输出 | ✅ BlockMap 内联 | DIY 解析 | DIY 解析 |
## 验证通过(工作)
测试的具体网站及测量时间。从冷启动到提取结果。
| 类别 | 网站 | 时间 |
|---|---|---|
| 参考/文档 | 维基百科、MDN、docs.rs、PyPI、react.dev(SSR 部分) | 0.9 – 5.8 秒 |
| 新闻 | Hacker News、BBC、TechCrunch、ArXiv 列表 | 1 – 1.6 秒 |
| 搜索 | Google `/search`、Bing、Brave、DuckDuckGo(html) | 0.2 – 1.8 秒 |
| 开发 | GitHub 仓库页面、npm、StackOverflow、HuggingFace 模型卡 | 0.7 – 2.4 秒 |
| 加密/金融 | CoinGecko、Yahoo Finance(修复后重定向) | 3.5 – 6.9 秒 |
| 社交 | Lobsters、old.reddit.com | 0.9 – 1.4 秒 |
| 政府/机构 | arXiv、archive.org、gov.uk | 0.6 – 1.0 秒 |
| 交互原语 | type、click + auto-follow、cookies_set/get/replay、eval、query_text | 0.3 – 1.3 秒 |
**惊喜:** 所有四家主要搜索引擎都能正常工作。CoinGecko 的重仪表板 SSR 足以使引用生效。HuggingFace 模型卡在 `<h1>` 中暴露模型名称。
## 机器人检测诊断
每个被阻止的导航都返回一个 `challenge` 字段,指定供应商(`perimeterx_block`、`cloudflare_turnstile`、`aws_waf`、`datadome`、`akamai_bmp`、`imperva`、`arkose_labs`、`recaptcha`、`press_hold`、`yahoo_sad_panda`、`interstitial`、`generic_human_verification`、`unknown_block`)以及预期的清除 cookie 名称。代理通过 `cookies_set` 做出智能反应,而不是猜测。
### 本地 cookie 求解服务
对于完全透明的 cookie 转移,请使用由 `unchained-cli` 支持的本地求解服务:
```bash
pip install 'pyunbrowser[solver]' # 或:pip install unchainedsky-cli
python scripts/cookie_service.py --headless --profile unbrowser-cookie-service
export UNBROWSER_COOKIE_SERVICE_URL=http://127.0.0.1:8765
```
然后使用 `scripts/router.py`(或 `RouterConfig(cookie_service_url=...)`)作为面向代理的入口点。当被阻止的 navigate 时,路由器将:
```text
检测挑战 -> 调用本地服务 -> Chrome 获取 cookie -> cookies_set -> 重试一次
```
该服务公开 `GET /.well-known/unbrowser-cookie-solver` 和 `POST /solve`,支持与 `navigate.challenge` 相同的挑战提供者,并仅返回来自用户本地 Chrome/unchained 会话的 cookie。它不会伪造挑战令牌。保持它绑定到 `127.0.0.1`;除非传递 `--allow-remote-bind`,否则非环回绑定被拒绝,因为 `/solve` 是无身份验证的,可以返回浏览器 cookie。使用 `--allow-host` 进行域允许列表(如果需要),并使用 `--no-headless --stealth` 适用于拒绝无头 Chrome 的网站。Chrome 默认情况下会持续运行以解决这个问题;传递 `--no-keep-chrome` 以一次性使用。解决方案会因服务进程而序列化,因为一个服务实例拥有一个 CDP 端口/配置文件对。由于安装的 Python 包,相同的部分在控制台包装器后面捆绑在一起:
```bash
unbrowser cookie-service --headless --profile unbrowser-cookie-service
unbrowser router https://example.com/protected
```
`unbrowser router` 还会在第一次挑战时自动启动本地 cookie 服务,当存在 `unchained` 且未设置 `UNBROWSER_COOKIE_SERVICE_URL` 时。 `--allow-host example.com` 仅允许 `example.com` 及其子域名。广泛的单标签后缀如 `com` 被拒绝。 如果没有允许列表,服务会默认拒绝私有/保留 IP、localhost 和内部单标签主机;使用 `--allow-host` 选择加入特定的内部主机进行本地测试。 路由器默认拒绝非环回的 `UNBROWSER_COOKIE_SERVICE_URL` 值,因为它会发布目标 URL 和挑战元数据到该服务;仅当信任远程求解器时,传递 `--allow-remote-cookie-service`。
## SPA-detection diagnostics
每次导航的 `blockmap.density` 字段都会发出 SPA 信号,因此代理在浪费往返之前就会退出:
- `thin_shell: true` — 页面正文文本小于 4KB,没有标题或交互元素(典型的 React/Ember 根目录)。对于 HTTP 错误(`status >= 400`),shell 信号会被抑制,并附加 `http_error_status`,以便 404 不会被误认为是 SPA。
- `likely_js_filled: true` — 表格/列表/单元格 shell 为空,或者页面有很多脚本,但可视化 UI 很小(CNBC / YouTube 类陷阱)
- `json_scripts: N` — `<script type="application/json">` 的计数(通常包含 JS 将渲染的数据 — 在升级之前尝试 `eval()`)
- `script_heavy_shell: true` — 许多脚本,很少文本,少量链接;通常是浏览器渲染的 UI,而不是有用的 SSR
## 代理与之交互的三种方式
### Session CLI(持久 shell 工作流)
当代理只能 shell 输出但需要增量状态时,启动一个本地守护进程支持的会话。Cookie、DOM、JS 全局变量和元素引用在 `stop` 之前持续存在:
```bash
unbrowser session start --id golf
unbrowser exec golf navigate https://news.ycombinator.com
unbrowser exec golf query '.titleline > a'
unbrowser exec --pretty golf blockmap
unbrowser exec golf eval 'document.title'
unbrowser session stop golf
```
`session exec` 和更短的 `exec` 别名接受常见方法的简写参数或原始 JSON 参数对象:
```bash
unbrowser exec golf navigate https://example.com --exec-scripts
unbrowser exec golf query_debug '.product-card' --limit 5
unbrowser exec golf extract_cards '{"kind":"product","limit":20}'
unbrowser session prune # remove dead sockets
```
### MCP(无胶)
```json
{
"mcpServers": {
"unchained": {
"command": "unbrowser",
"args": ["--mcp"]
}
}
}
```
工具由 Claude Code、Claude Desktop、Cursor、Cline 自动发现。
### 子进程(自定义运行时)
13 行 Python 代码(以上)。或任何具有子进程 + JSON 的语言。
### 自动升级路由器 (`scripts/router.py`)
```python
from scripts.router import Router, RouterConfig, cached_cookies_solver
with Router(RouterConfig(
binary="./target/release/unbrowser",
chrome_solver=cached_cookies_solver("cookies.json"),
)) as r:
r.navigate("https://www.zillow.com/homes/for_rent/") # auto-handles 403 + cookie replay
```
### Live event watcher (`scripts/watch.py`)
二进制文件在 stderr 上发出 NDJSON 事件(`ready`, `navigate`, `challenge`)。通过 `watch.py` 以彩色代码的一行代码管道传输:
```bash
unbrowser 2> >(python3 scripts/watch.py)
```
## RPC 方法
| | |
|---|---|
| `navigate {url}` | 获取 + 解析 + 返回 `{status, url, bytes, headers, blockmap, challenge, tool_confidence, tool_margin, tool_likelihoods, tool_recommendations}` |
| `query {selector}` | CSS 查询 → `[{ref, tag, attrs, text, text_chars, text_truncated}]` |
| `query_debug {selector, limit?}` | 解释选择器缺失:匹配计数、样本匹配、DOM 摘要、顶部标签/类/数据属性/ id 和 `selector_miss`、`thin_shell`、`embedded_json` 等提示 |
| `text {selector?}` | 第一个匹配项(默认为 `body`)的 textContent。在 Wikipedia/MDN/news 网站上,第一个 `<p>` 通常是帽子注释 — 优先使用 `text_main` 获取文章正文。 |
| `text_main` | `<main>` / `[role=main]` / 单个 `<article>` / 最长的非 Chrome 子树的 textContent。用于阅读文章/文档/博客内容。 |
| `discover {url?, goal?, exec_scripts?, same_origin?, include_network?, limit?, debug?}` | 廉价信息发现。首先合并 DOM 路由、推断的表单/查询 URL 和网络 JSON 路由到一个有出处和升级提示的排名图。默认为静态发现;设置 `exec_scripts: true` 以获取当静态 HTML 不足以获取可见路由时。 |
| `extract_cards {selector?, limit?, kind?}` | 自动检测重复的产品/列表/文章卡片,并返回包括 `title`、`price`、`condition`、`url`、`availability`、`snippet`、`meta`、`image_alt`、`score` 在内的规范化字段 |
| `extract_table {selector}` / `table_to_json {selector?}` | 将 HTML 表格规范化为头部、行和行计数。`table_to_json` 默认为第一个 `table`。 |
| `click {ref}` | 分派点击;自动跟随 `<a href>`(返回 `{status, url, bytes, headers, blockmap, challenge}` — 与 `navigate` 相同) |
| `type {ref, text}` | 设置值 + 分派输入/更改事件 |
| `submit {ref}` | 收集表单字段并导航。支持 GET 和 `application/x-www-form-urlencoded` POST;不支持多部分。 |
| `eval {code}` | 在嵌入的 QuickJS 中运行 JS。原始 JSON-RPC 还接受 `script` 或 `expression` 别名,现在如果没有类似代码的参数,则会报错而不是静默返回 `null`。 |
| `cookies_set / cookies_get / cookies_clear` | 会话 jar |
| `blockmap` | 重新计算页面摘要 |
| `body` | 最后一次导航的原始 HTML |
`blockmap.selectors` 为当前页面提供具体的选择器提示(`data-testid`、`aria-label`、`role`),以便代理在不猜测的情况下偏向于 `query` 或 `query_text`。
`discover` 是在提取之前使用的路由查找层,当您需要了解信息存储位置时。默认情况下,它返回紧凑的 `navigate_summary`、`route_discover_summary` 和 `network_extract_summary` 字段,以及合并的 `routes`、`forms`、`api_endpoints`、`network_sources` 和 `escalations`。仅当您需要完整的嵌套 `navigate`、`route_discover` 和 `network_extract` 有效载荷进行诊断时,请传递 `debug: true`。`limit` 必须在 1 和 200 之间;无效的 `url` / `limit` 输入将在 RPC 边界处失败。
```json
{"jsonrpc":"2.0","id":1,"method":"discover","params":{"url":"https://example.com","goal":"find pricing docs api status","same_origin":true,"limit":25}}
```
使用 `exec_scripts: true` 作为一个选择性第二步,适用于静态 HTML 未公开足够路由的页面。在此模式下,已经在脚本之前存在的路由标记为 `static_dom`;仅在 JavaScript/定时器/获取之后出现的路由标记为 `js_dom`。
CSS 选择器引擎:标签、id、类、`[attr=val]` (也是 `^=`、`$=`、`*=`、`~=`),所有四个组合符(` `、`>`、`+`、`~`)、`:first/last/nth-child/of-type` 包括 An+B 公式、`:only-child/of-type`、`:not()` 和 `:has()`。
## 何时升级到真正的 Chrome
此二进制文件是一条廉价路径。对于它无法处理的案例(重框架水化、行为机器人挑战、Worker/Canvas/IndexedDB),下一层是使用 CDP 驱动的真正 Chrome 实例。有两种方法可以实现:
| | 本二进制文件 | [`unchainedsky-cli`](https://github.com/protostatis/unchainedsky-cli) | [Unchained 桌面应用程序](https://unchainedsky.com) |
|---|---|---|---|
| 运行 JS | QuickJS(无 V8 JIT) | 通过 CDP 的真实 Chrome | 真实 Chrome(用户的登录) |
| SPA 水化 | 部分 | ✅ | ✅ |
| 机器人挑战 | 仅 cookie 传递 | 通过真实浏览器主动解决 | 手动/交互 |
| 设置 | `pip install pyunbrowser` | `pip install unchainedsky-cli` | 桌面安装 |
| 受众 | 代理/管道 | 代理/管道 | 终端用户 |
| 每页占用 | ~50MB | 完整 Chrome | 完整 Chrome |
升级路径是有意选择,而不是自动回退 — 您将 `pyunbrowser` 用于 80% 的有效页面,然后将 20% 的页面路由到 `unchainedsky-cli`(或通过桌面应用程序路由到人类)。词汇(`navigate`、`query`、`click`、`cookies_set`、`BlockMap`)是共享的,因此代码可以干净地传输。
## 诚实的限制
- **脚本执行通过 `exec_scripts: true` 选择加入。** 默认导航跳过它(SSR/静态路径是大多数代理想要的)。启用后,内联 + 外部 `<script>` 标签在 QuickJS 中运行 — 适用于许多 SPA,但重框架启动(Ember,大型 React)通常不会自动安装,因为 shim 无法伪造每个浏览器特定的信号。`density.likely_js_filled` 标志在一个调用中告诉代理何时升级而不是烧往返。
- **所有 eval 都是限时时钟绑定的。** 30 秒的看门狗(可通过 `UNBROWSER_TIMEOUT_MS` 配置,限制在 1 秒至 10 分钟之间)涵盖了脚本执行和每个后续 settle/microtask/timer 回调,因此恶意站点永远无法阻塞二进制文件或阻塞 CPU 的孤儿进程。
- **表单提交故意狭窄。** 支持 GET 和 `application/x-www-form-urlencoded` POST,包括选中复选框/单选按钮值。不支持 multipart 上传表单 — 通过 `eval` 或升级手动构造请求。
- **最难的机器人检测**(带有行为遥测的 PerimeterX,Avanced Akamai BMP,Kasada)需要 cookie 传递路径。二进制文件检测并为您标记挑战,但解决它需要真正的 Chrome(或令牌供应商)。
- **无截图。** 按设计超出范围。
## 构建
Rust 1.95+ via [rustup](https://rustup.rs)。在 macOS 上,还需要 `brew install cmake ninja`(BoringSSL 依赖)。
```bash
cargo build --release
```
~2 分钟首次构建(BoringSSL 编译),之后立即完成。
## 架构图
```
JSON-RPC stdin ─┐ ┌─ stdout
▼ ▲
┌────────────────────┐
│ 请求 (Chrome │ ┌──────────┐ ┌──────────────────┐
│ TLS+H2 指纹)├──▶ html5ever ├───▶ rquickjs + │
│ │ │ 解析器 │ │ dom.js + │
│ cookie_store │ └──────────┘ │ blockmap.js + │
│ (jar) │ │ interact.js │
└────────────────────┘ └──────────────────┘
```
## 许可证
Apache 2.0 — 请参阅 [LICENSE](./LICENSE)。
---
对于此二进制文件无法处理的案例(重框架水化、行为机器人挑战、需要真实 Chrome 的任何情况),下一层是 [`unchainedsky-cli`](https://github.com/protostatis/unchainedsky-cli) — 通过 CDP 驱动真实 Chrome,使用相同的词汇。想要点按代理的终端用户可以直接跳过 CLI,使用 [Unchained 桌面应用程序](https://unchainedsky.com)。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器