关于 Stealthy Auto Browse
Stealthy Auto Browse 是基于 Docker 中 Camoufox 的可自托管浏览器自动化服务,使用操作系统级输入并提供 HTTP API。它面向需要远程控制浏览器、执行脚本或通过 noVNC 查看过程的 Agent 与自动化工作流。
主要功能
- 01Docker 中运行 Camoufox 浏览器
- 02操作系统级鼠标和键盘输入
- 03JSON HTTP API 与 YAML 脚本
- 04通过 noVNC 实时查看浏览器
- 05请求排队与集群模式
适用场景
- 01在 CI 或定时作业中运行浏览器自动化
- 02远程执行多步骤浏览器工作流
- 03通过 noVNC 查看自动化会话
- 04测试请求摄像头或麦克风访问的页面
MCP 相关
MCP 服务通过端口 8080 的 `/mcp` 提供 Streamable HTTP 接口。它将导航、截图、点击、输入、JavaScript 求值和 Cookie 管理等浏览器操作作为工具开放。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
docker-stealthy-auto-browse
真正好用的隐蔽式浏览器自动化。通过 Docker 运行 Camoufox(定制版 Firefox),完全不暴露 Chrome DevTools Protocol,借助 PyAutoGUI 实现真正的操作系统级鼠标和键盘输入,并提供 JSON HTTP API 和 MCP 服务,供远程控制。可通过 noVNC 实时观看。既可以运行单个实例,也可以在 HAProxy 后启动集群,并通过 Redis 同步 Cookie、排队请求和启用粘性会话。可使用 curl 驱动、通过 stdin 传入 YAML 脚本、通过 API 发送多步脚本、使用页面加载器自动处理弹窗和付费墙,或通过 MCP 直接连接 AI Agent。还可通过 AUTH_TOKEN 启用可选的 Bearer 令牌身份验证。
此镜像可避免 Chromium CDP 信号,并确保生成的 Linux 字体和 WebGL 指纹在内部保持一致。检测结果仍取决于网站、网络出口、时区、浏览器版本和测试日期。
目录
包含内容
| 组件 | 功能 |
|---|---|
| Camoufox | 定制版 Firefox,完全不暴露 Chrome DevTools Protocol。机器人检测器会查找 CDP 信号,而这款浏览器没有任何此类信号。自动化脚本在页面无法访问的 JavaScript 环境中运行。 |
| Xvfb | 虚拟帧缓冲器,让浏览器可以在容器内以完整图形显示模式运行,无需实体显示器。这一点很重要,因为无头模式也是一种检测信号。 |
| PyAutoGUI | 生成真实的操作系统级鼠标移动和按键操作。页面会将其视为可信的用户输入,操作时序也如同真人。请参阅 两种输入模式。 |
| noVNC | 基于 Web 的 VNC 客户端,让你可以在自己的浏览器中实时观看浏览器。默认情况下,查看器会在自动化指针的实际位置显示该指针。设置 VNC_SHOW_CURSOR=false 可将其隐藏。 |
| Openbox | 轻量级窗口管理器。它会为弹出窗口(OAuth 对话框等)添加标题栏和缩放控点,否则这些窗口可能太小而无法操作。主窗口的尺寸经过调整,可适配标题栏。对隐身效果没有任何影响。 |
| HTTP API | 运行在端口 8080 上的 JSON API,可让你控制所有功能:浏览页面、点击元素、输入文本、截图、管理标签页、处理 Cookie 等。 |
| MCP 服务 | 在同一端口的 /mcp 上运行的模型上下文协议服务。AI Agent(Claude 等)可以通过 Streamable HTTP 直接使用 MCP 驱动浏览器。 |
| ffmpeg | 使用 x11grab 从 Xvfb 录制屏幕。捕获实际渲染的像素,包括操作系统级鼠标光标。请参阅屏幕录制。 |
预装扩展:uBlock Origin(广告/跟踪器)、LocalCDN(防止 CDN 跟踪)、ClearURLs(剥离跟踪参数)、Consent-O-Matic(自动处理 Cookie 弹窗)。
快速开始
docker run -d --name browser \
-p 8080:8080 \
-p 5900:5900 \
psyb0t/stealthy-auto-browse
端口 8080 是 HTTP API,端口 5900 是 VNC 查看器(http://localhost:5900/)。
# Navigate
curl -X POST http://localhost:8080 \
-H "Content-Type: application/json" \
-d '{"action": "goto", "url": "https://example.com"}'
# Get page text
curl -X POST http://localhost:8080 \
-H "Content-Type: application/json" \
-d '{"action": "get_text"}'
# Click by CSS selector (preferred: fast and reliable)
curl -X POST http://localhost:8080 \
-H "Content-Type: application/json" \
-d '{"action": "click", "selector": "button#submit"}'
# Screenshot (last resort; prefer get_text and always resize to save tokens)
curl "http://localhost:8080/screenshot/browser?whLargest=512" -o screenshot.png
在单个请求中运行多步骤脚本:
curl -X POST http://localhost:8080 \
-H "Content-Type: application/json" \
-d '{
"action": "run_script",
"steps": [
{"action": "goto", "url": "https://example.com", "wait_until": "domcontentloaded"},
{"action": "sleep", "duration": 2},
{"action": "get_text", "output_id": "text"},
{"action": "eval", "expression": "document.title", "output_id": "title"}
]
}'
也接受采用脚本模式相同 YAML 格式的 "yaml": "..."。在单实例模式下,服务会自动串行处理请求。并行发送多个脚本,它们会排队执行。
所有操作和完整 API 参考请参阅 docs/api.md。
导航使用由应用控制的控件,而非隐藏的浏览器库超时。每次尝试默认最多等待 30 秒,超时后重试一次,重试间隔为 1 秒。如果工作流需要不同的限制,可在 goto、refresh 或 new_tab 中传入 timeout、retry_count 和 retry_delay。retry_count: 0 会禁用重试。有关限制和重试行为,请参阅导航控制。
两种输入模式
与页面交互有两种方式。系统输入使用 PyAutoGUI 生成真实的操作系统级鼠标和键盘事件,因此页面会收到可信事件,不留注入痕迹,事件时序也像真人一样。Playwright 输入使用 CSS 选择器和 DOM 事件注入。它更简单,但理论上可被行为分析检测到。在任何启用了机器人防护的网站上,都应使用系统输入。
系统输入会像真人一样移动鼠标和输入文字。默认参数依据已发布的人类行为数据集进行拟合(鼠标轨迹使用 SapiMouse,点击使用 Balabit,输入使用 Aalto 按键研究):
- **鼠标:**采用曲线 sigma-lognormal 轨迹和符合菲茨定律的时序,移动初期达到速度峰值,约三分之一的移动会出现过冲和修正,并加入手部颤动;事件以 125 Hz 的鼠标速率发送。
- **点击:**按下前短暂停顿,按住按钮约 100 ms,落点随机分布在目标内,不会落在正中心。
- **输入:**根据按键组合调整节奏,每个按键都会按住一段时间;快速打字者的按键会重叠;输入大写字母前会先按下 Shift;还可选择加入始终会被更正的错字。
- **滚动:**每次发送一个刻度的滚轮手势,期间有阅读停顿、指针漂移,偶尔还会向上滚动。
每个容器的行为都像同一个人,每项时序都可按请求覆盖。模型和选项见拟人化输入。其针对行为检测器的评分见行为检测结果。
完整说明和使用指南:docs/stealth.md
剪贴板
set_clipboard 和 get_clipboard 使用真实的 X11 文本剪贴板,该剪贴板由 Camoufox 和 noVNC 共享。在浏览器中复制的文本可通过 API 读取,通过 API 设置的文本可使用 Ctrl+V 粘贴。值必须是有效的 UTF-8,且最多为 1 MiB。
curl -X POST http://localhost:8080 -H "Content-Type: application/json" \
-d '{"action":"set_clipboard","text":"paste me"}'
curl -X POST http://localhost:8080 -H "Content-Type: application/json" \
-d '{"action":"get_clipboard"}'
这两项操作各自都是专用的 MCP 工具。在集群模式下,请在同一次 run_script 调用中使用它们,以确保两项操作由同一个浏览器实例执行。请参阅 API 参考。
虚拟摄像头和麦克风
将测试媒体以只读方式挂载到 /media,并设置 VIRTUAL_CAMERA_FILE 和/或 VIRTUAL_MICROPHONE_FILE。调用 navigator.mediaDevices.getUserMedia() 的页面会收到从这些文件捕获的轨道,因此无需主机硬件即可运行摄像头和麦克风检查。
docker run -d -p 8080:8080 \
-v ./media:/media:ro \
-e VIRTUAL_CAMERA_FILE=camera.webm \
-e VIRTUAL_MICROPHONE_FILE=microphone.wav \
psyb0t/stealthy-auto-browse
源文件必须位于 /media 内;更改源文件后,请重启浏览器。对于未配置虚拟源的媒体类型,请求会失败并返回 NotFoundError,不会回退到硬件。虚拟轨道使用源文件的原生格式,因此页面不得要求不兼容的精确媒体约束。此功能仅虚拟化 getUserMedia(),不虚拟化 enumerateDevices()。
若要在经授权的测试期间切换源,同时不替换已获取的摄像头或麦克风轨道,请启用 VIRTUAL_MEDIA_DYNAMIC=true。动态模式默认关闭。使用 set_virtual_media_source 选择 VIRTUAL_MEDIA_DIR 下已有的相对文件名,或使用 upload_virtual_media 添加大小受限的 base64 内容,并可选择是否激活该文件。上传文件名仅需是安全且类型匹配的媒体名称;服务会生成不会冲突的存储文件名并将其返回,且绝不会覆盖已有的命名源。存储或激活前,服务会使用 ffprobe 检查解码后的上传内容,确认其中包含与所请求摄像头或麦克风类型匹配的流。上传需要媒体目录可写;VIRTUAL_MEDIA_UPLOAD_MAX_BYTES 默认值为 50 MiB。更改源时,现有页面流会保留其轨道标识。
动态模式仅接受配置媒体目录中的文件。不接受任意主机路径、远程 URL、WebSocket 流或其他实时输入。两项操作都使用常规 API 身份验证。设置 AUTH_TOKEN 后,请发送常规的 Authorization: Bearer <token> 标头。有关操作约定和可写卷设置,请参阅 docs/api.md#virtual-camera-and-microphone 和 docs/configuration.md。
MCP 服务
AI Agent 可通过同一 8080 端口上的 /mcp,经由 模型上下文协议 使用 Streamable HTTP 控制浏览器。该服务将所有浏览器操作作为 MCP 工具提供:导航、截图、点击、输入、JavaScript 求值、Cookie 等。
对于出现验证组件时需要人工审核的经授权测试流程,请使用 detect_challenge。此操作为只读。它会根据有限的供应商和位置证据,尽力报告 absent、present 或 unknown 状态,但绝不会点击、进入框架或解决验证挑战。传入 scroll_into_view: true,可将首个检测到的可见框架或组件滚动到视口内,以便交接给 VNC;但它仍不会点击或聚焦该组件。在集群模式下,请将其作为 run_script 步骤。请参阅 API 参考。
将任何兼容 MCP 的客户端(Claude Desktop、Claude Code、自定义 Agent)连接到 http://localhost:8080/mcp/,即可开始浏览。
独立模式和集群模式均可使用。
Agent 集成
技能适用于任何会读取 .agents/skills/ 的 Agent(例如 peen),并且可原生安装到下列客户端中。
Claude Code
claude plugin marketplace add psyb0t/agents
claude plugin install stealthy-auto-browse@psyb0t
Claude Code 会提示输入 stealthy-auto-browse URL,以及在启用身份验证时输入令牌,并将其存储在操作系统钥匙串中。
Codex
codex plugin marketplace add psyb0t/agents
codex plugin add stealthy-auto-browse@psyb0t
通过市场安装后,该技能会以 $stealthy-auto-browse:stealthy-auto-browse 的形式调用。Codex 还会自动识别任何包含 .agents/skills/ 的仓库中的该技能,无需安装;此时会以 $stealthy-auto-browse 的形式直接调用。
OpenClaw
每次发布时,都会将此技能发布到 ClawHub:
openclaw skills install @psyb0t/stealthy-auto-browse
对于使用本地 stdio 通信的 MCP 客户端,插件 @psyb0t/stealthy-auto-browse 可桥接到服务的 /mcp 端点:
openclaw plugins install clawhub:@psyb0t/stealthy-auto-browse
然后设置 STEALTHY_AUTO_BROWSE_URL(如果服务器需要身份验证,还需设置 AUTH_TOKEN)。
脚本模式
将 YAML 脚本通过管道传入容器,在 stdout 上获取 JSON 结果,然后容器退出。无需 HTTP 服务器。适用于 CI、cron 任务和一次性抓取。
cat my-script.yaml | docker run --rm -i \
-e TARGET_URL=https://example.com \
psyb0t/stealthy-auto-browse --script > results.json
完整文档:docs/script-mode.md
脚本模式还支持显式 if 分支,以及有界的 repeat 和 while 循环。条件可以检查元素、可见文本、URL、JavaScript 布尔值和之前的 output_id 值;请参阅控制流参考。
页面加载器
在 YAML 文件中定义 URL 模式和操作序列。将这些文件挂载到 /loaders。每当 goto 匹配某个模式时,加载器便会自动运行。它会移除弹窗、等待内容加载并清理页面。相当于 HTTP API 的 Greasemonkey。
完整文档:docs/page-loaders.md
屏幕录制
将浏览器录制为 MP4,并显示鼠标光标。ffmpeg 使用 x11grab 对 Xvfb 进行录制,并将文件写入挂载的 /recordings 卷。提供三种模式:window(完整的 Camoufox 窗口)、viewport(根据录制开始时测得的 mozInnerScreenX/Y 页面位置裁剪浏览器内容)、desktop(整个 Xvfb 屏幕)。停止录制时提供 slug,因此可以在运行完成后命名文件。可防止路径遍历、文件名冲突和崩溃导致的问题。
mkdir -p ./recordings
docker run -d -p 8080:8080 -v ./recordings:/recordings psyb0t/stealthy-auto-browse
curl -X POST http://localhost:8080 \
-H "Content-Type: application/json" \
-d '{"action": "start_recording", "mode": "viewport", "fps": 20}'
# … do stuff …
curl -X POST http://localhost:8080 \
-H "Content-Type: application/json" \
-d '{"action": "stop_recording", "slug": "my-flow"}'
# → ./recordings/my-flow.mp4
也可在 run_script 中使用(兼容集群模式:开始和停止操作必须位于同一个 run_script 中,确保二者命中同一实例)。完整操作表、脚本模式示例和说明见 docs/api.md#screen-recording。
集群模式
通过 HAProxy 运行多个浏览器实例,并配置请求队列、会话粘滞和 Redis Cookie 同步(默认 5 个,可通过 NUM_REPLICAS 配置)。下载 compose 文件和 HAProxy 配置,然后启动:
curl -LO https://raw.githubusercontent.com/psyb0t/docker-stealthy-auto-browse/main/docker-compose.cluster.yml
docker compose -f docker-compose.cluster.yml up -d
在任一实例上设置的 Cookie 都会通过 Redis PubSub 即时同步到其他实例。只需登录一次,整个集群便会完成身份验证。
每个浏览器默认内存限制为 5GB。如果集群或显示分辨率需要不同的内存预算,请设置 BROWSER_MEMORY_LIMIT 和 BROWSER_MEMORY_RESERVATION;请参阅集群模式。
仅限脚本的强制执行(v1.0.0+): 当 NUM_REPLICAS > 1 时,HTTP API 和 MCP 服务都仅允许使用 run_script(以及 ping 和 sleep)。它们会拒绝单独的操作,以防止跨实例路由导致内容过时的问题。所有操作仍可作为步骤在 run_script 中使用。
完整文档:docs/cluster-mode.md
身份验证
设置 AUTH_TOKEN,要求所有请求都携带 Bearer 令牌(/health 除外):
docker run -d -p 8080:8080 -e AUTH_TOKEN=your-token-here psyb0t/stealthy-auto-browse
在 Authorization 标头中传递令牌:
# Header
curl -H "Authorization: Bearer your-token-here" http://localhost:8080 ...
示例
请参阅 .agents/skills/stealthy-auto-browse/scripts/ 中可直接使用的脚本:
websearch.py:并行使用多个搜索引擎(Brave、Google、Bing)进行网页搜索,并提取结构化结果和 AI 概览。输出 JSON,其中每条结果都包含标题、URL 和摘要。
配置
完整的环境变量表、代理设置(包括可用的私有 pr0xteus HTTP 代理示例)、持久化配置文件、浏览器扩展和 VNC 访问说明见:docs/configuration.md
开发
Docker 是唯一的开发依赖项。Makefile 会构建本地浏览器基础镜像,然后在单独的一次性开发容器中运行 lint、测试和安全工具。只有完整测试目标会获得 Docker socket,因为它会启动自己的浏览器和测试夹具容器。
make build
make lint
make test
make test-real
make sec
make sec 会生成供 GitHub Security 使用的 sec.sarif。它会报告发现的问题,但不会阻止发布。使用 make help 查看完整命令列表。
make test-real 会针对公共网站运行可选的实时检查,因此需要出站网络访问,并且不会在确定性默认测试套件中运行。它会检查 liarjs.dev 上的指纹一致性,以及 deviceandbrowserinfo.com 登录测试和 FCaptcha 演示在复选框和隐形模式下的输入行为。每项行为检查都会在同一 IP 上,分别使用拟人化输入、Playwright DOM 输入和原始 PyAutoGUI 执行相同任务。拟人化运行必须通过,而两种机器人式运行必须失败或得分更低,这证明该服务确实会对行为进行评分。
机器人检测结果
以下为观测结果,并不保证每个服务的每个版本都会返回相同结果。 请使用你计划采用的确切镜像、代理、时区和目标流程进行测试。
| 服务 | 观测结果 | 检查内容 |
|---|---|---|
| CreepJS | 通过 | Canvas/WebGL 指纹一致性、欺骗检测、worker 比较 |
| liarjs.dev | 82/100,无严重问题 | 字体、Canvas、worker、GPU、网络和行为一致性 |
| BrowserScan | 通过 | WebDriver 标志、CDP 信号、navigator 属性 |
| Pixelscan | 通过 | 指纹一致性、时区/IP 匹配、WebRTC 泄漏 |
| Cloudflare | 通过 | 验证页面、Turnstile、机器人管理 |
| SannySoft | 通过 | Intoli + 指纹扫描器测试 |
| Incolumitas | 通过 | 现代检测技术 |
| Rebrowser | 通过 | CDP 泄漏检测、webdriver、视口分析 |
| BrowserLeaks WebRTC | 通过 | WebRTC IP 泄漏检测 |
| DeviceAndBrowserInfo | 通过 | 19 项检查,全部通过,“你是人类!” |
| IpHey | 通过 | “可信”评级 |
| Fingerprint.com | 通过 | 识别为普通 Firefox,没有机器人标志 |
为何有效:docs/stealth.md
行为检测结果
干净的指纹说明浏览器是什么。行为检测器关注它做了什么:指针如何移动,按键和按钮按下了多久,滚轮如何滚动。下面的每项检测都会在同一个容器、使用同一个 IP,以三种方式执行同一任务,因此指纹和网络完全相同,只有输入不同。
| 检测 | 模拟人类操作的系统输入 | Playwright DOM 输入 | 原始 PyAutoGUI |
|---|---|---|---|
| DeviceAndBrowserInfo 登录测试 | 人类 | 机器人 | 机器人 |
| FCaptcha 复选框 | 已验证 | 失败 | 失败 |
| FCaptcha 隐形风险评分(越低越好) | 0.06,允许 | 0.60,拦截 | 0.22,允许 |
| motion-attestation 和 Gaitcha:鼠标、打字、滚动 | 通过 | 未运行 | 检测到 |
原始 PyAutoGUI 发送相同的可信 OS 级事件,但移动路线笔直且瞬间完成,按下时长为零。三个托管检测中有两个会直接将其标记出来,另一个给出的风险评分几乎高出四倍。仅有可信事件还不够,模拟人类操作的时序才能通过检测。
托管检测结果通过 make test-real 观测,该命令每次运行都会验证这一模式:模拟人类操作的运行必须通过,两个机器人式运行都必须失败或得分明显更差。每次 make test 都会在本地探测页面上运行离线检测器,并且每项检测也会执行一个必须被检测出来的机器人式会话。和指纹检测结果一样,托管检测的评分取决于服务版本、网络出口和时区。
许可证
WTFPL(Do What The Fuck You Want To Public License)
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。