Agent智能体 活跃维护

camofox-browser

jo-inc/camofox-browser

用于 AI 代理的隐身无头浏览器——绕过 Cloudflare、机器人检测和防抓取。即插即用的 Puppeteer/Playwright 替代品。

12009
Stars 标星
1213
Forks 分支
26
Watchers 关注
98
Open Issues
JavaScript
主要语言
MIT
开源协议
15.9 MB
仓库大小
4 天前
最后推送
一键安装扩展 / 插件指令
dsh plugin --profile web add github:jo-inc/camofox-browser
git clone https://github.com/jo-inc/camofox-browser.git
git clone git@github.com:jo-inc/camofox-browser.git
README.md master

英文原文正文为项目原始 README(英文),本站后续会翻译为中文,当前仅剔除图片与无关章节并统一排版。

camofox-浏览器

由Camoufox驱动的AI代理防检测浏览器服务器

站在强大的Camoufox肩膀上——这是一个在C级别实现指纹伪装的Firefox分支。


由jo,一款个人AI助手背后的团队打造,该助手一半运行在你的Mac上,一半运行在专属于你的云端机器上——无需任何维护。在macOS、Telegram、WhatsApp和电子邮件上可用。免费试用测试版 ->

Pradeep Elankumaran (@pradeep24) — Jo的联合创始人兼技术首席执行官。



git clone https://github.com/jo-inc/camofox-browser && cd camofox-browser
npm install && npm start
# -> http://localhost:9377

为什么

AI 代理需要浏览真实的网页。Playwright 会被封锁。无头 Chrome 会被指纹识别。隐身插件本身会成为指纹。

Camoufox 在 C 实现层面 修补 Firefox——navigator.hardwareConcurrency、WebGL 渲染器、AudioContext、屏幕几何、WebRTC——在 JavaScript 看到之前全部伪装。没有 shim,没有包装器,没有痕迹。

这个项目将该引擎封装在为代理构建的 REST API 中:使用可访问性快照代替臃肿的 HTML,点击用稳定的元素引用,以及用于常用网站的搜索宏。

功能

  • C 反检测 - 绕过 Google、Cloudflare 和大多数机器人检测
  • 元素引用 - 稳定的 e1、e2、e3 标识符,用于可靠交互
  • 节省 Token - 可访问性快照比原始 HTML 小约 90%
  • 适用于任何环境 - 延迟浏览器启动,空闲关闭,使内存空闲时保持约 40MB。设计用于与栈中其他服务共享同一台机器——Raspberry Pi、5 美元 VPS、共享基础设施。
  • 会话隔离 - 每个用户独立的 Cookie/存储
  • Cookie 导入 - 注入 Netscape 格式的 Cookie 文件,实现已认证的浏览
  • 文件上传 - 从配置的上传目录附加文件,无需本地操作系统对话框
  • 代理与 GeoIP - 通过住宅代理路由流量,自动设置区域/时区
  • 结构化日志 - JSON 日志行,带请求 ID,用于生产环境可观测性
  • YouTube 字幕 - 通过 yt-dlp 提取任何 YouTube 视频的字幕,无需 API key
  • 搜索宏 - @google_search、@youtube_search、@amazon_search、@reddit_subreddit 等 10 个以上
  • 快照截图 - 在可访问性快照旁包含 base64 PNG 截图
  • 大页面处理 - 自动快照截断并基于偏移量分页
  • 下载捕获 - 捕获浏览器下载并通过 API 获取(可选内联 base64)
  • DOM 图像提取 - 列出 <img> 的 src/alt,并可选择返回内联数据 URL
  • 随处部署 - Docker, Fly.io, Railway
  • VNC 交互登录 - 通过 noVNC 可视化登录网站,导出存储状态供代理重用
  • OpenAPI 文档 - 在 /openapi.json 上自动生成规格说明,在 /docs 查看交互式文档
  • 结构化提取 - 使用 JSON Schema 的 POST /tabs/:tabId/extract 将属性映射到通过 x-ref 的快照引用
  • 会话跟踪 - 每个会话可选择启用 Playwright 跟踪捕获(截图、DOM 快照、网络),提供 API 端点列出、获取和删除跟踪压缩包
  • 遥测 - 通过 GitHub Issues 自动收集匿名崩溃/挂起遥测。可识别哪些网站导致失败及常见失败模式。私有域名经过 HMAC 哈希处理,路径/参数删除,令牌/IP 模糊化。可通过 CAMOFOX_CRASH_REPORT_ENABLED=false 选择退出。

可选依赖

依赖 目的 安装
yt-dlp YouTube 文本提取(快速路径) pip install yt-dlp 或 brew install yt-dlp

Docker 镜像包含 yt-dlp。对于本地开发,请为 /youtube/transcript 端点安装它。没有它,该端点将回退到较慢的基于浏览器的方法。

快速开始

OpenClaw 插件

openclaw plugins install @askjo/camofox-browser

工具: camofox_create_tab | camofox_snapshot | camofox_click | camofox_type | camofox_navigate | camofox_scroll | camofox_screenshot | camofox_close_tab | camofox_list_tabs | camofox_import_cookies

独立使用

从 npm 运行:

npx @askjo/camofox-browser

或者来自来源:

git clone https://github.com/jo-inc/camofox-browser
cd camofox-browser
npm install
npm start  # downloads Camoufox on first run (~300MB)

默认端口是 9377。有关所有选项,请参阅环境变量。

注意: 安装后脚本会在获取 Camoufox 二进制文件之前为自身取消设置 PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD。如果没有这个覆盖,导出的 PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1(在 Playwright 配置为使用系统 Chrome 时很常见)会默默跳过二进制文件下载,并在运行时导致服务器崩溃。

外部 Camoufox 可执行文件: 在运行 npm install 之前以及启动服务器时设置 CAMOUFOX_EXECUTABLE=/path/to/camoufox-bin,以跳过内置下载并启动该可执行文件。兼容别名为 CAMOUFOX_EXECUTABLE_PATH 和 CAMOFOX_EXECUTABLE_PATH。这对于 NixOS 路径(例如 /nix/store/.../camoufox-bin)非常有用;该可执行文件必须来自包含 properties.json、version.json 和 fontconfig/ 的 Camoufox 包。

隔离环境或自定义二进制管理: 当你已有 Camoufox 包时,优先使用 CAMOUFOX_EXECUTABLE。否则,通过 npm install --ignore-scripts 禁用自动获取(对每个依赖项跳过生命周期脚本——最粗暴的方法),或者更精细地使用 npm install --omit=optional,然后手动执行 npx camoufox-js fetch 来从你的镜像获取。请注意,PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm install 现在不再跳过 Camoufox 下载(postinstall 会在本地清理环境);对此请使用 --ignore-scripts 或 CAMOUFOX_EXECUTABLE。

Docker

包含的 Makefile 会自动检测你的 CPU 架构,并在 Docker 构建之外预下载 Camoufox 和 yt-dlp 二进制文件,因此重建速度很快(约 30 秒 vs 约 3 分钟)。

# Build and start (auto-detects arch: aarch64 on M1/M2, x86_64 on Intel)
make up

# Stop and remove the container
make down

# Force a clean rebuild (e.g. after upgrading VERSION/RELEASE)
make reset

# Just download binaries (without building)
make fetch

# Override arch or version explicitly
make up ARCH=x86_64
make up VERSION=135.0.1 RELEASE=beta.24

窗口

在 Windows 上,make 不可用。请改用随附的 build.ps1 PowerShell 脚本:

# Build and start
.\build.ps1 up

# Stop and remove the container
.\build.ps1 down

# Build image only
.\build.ps1 build

# Force a clean rebuild
.\build.ps1 reset

# Download binaries only (without building)
.\build.ps1 fetch

# Override architecture
.\build.ps1 up -Arch x86_64
.\build.ps1 up -Arch aarch64

注意: 建议使用 PowerShell 7 (pwsh),但 powershell.exe(Windows PowerShell 5.1)也可以。该脚本需要安装带有 WSL2 后端的 Windows 版 Docker Desktop。

行结束符: 该项目包含一个 .gitattributes 文件,用于强制 .sh 文件使用 Unix (LF) 行结束符。如果你已经克隆了仓库,并在 docker build 期间遇到 sh: not found 或 set: Illegal option - 错误,请运行:

Get-ChildItem -Recurse *.sh | ForEach-Object { (Get-Content $_) -join "`n" + "`n" | Set-Content $_ -NoNewline }

这会将 shell 脚本转换为 LF 行结尾。未来的克隆将自动处理此问题,感谢 .gitattributes。

警告:不要直接运行 docker build。 该 Dockerfile 使用绑定挂载从 dist/ 拉取预下载的二进制文件。请始终使用 make up(或先 make fetch 然后 make build)——它会先下载二进制文件。

Fly.io

对于 Fly.io 或其他远程 CI,你需要一个在构建时下载二进制文件而不是使用绑定挂载的 Dockerfile。

铁路

包含了一个 railway.toml。它使用 Dockerfile.ci(在构建时下载二进制文件)并自动将 Railway 的 PORT 环境变量映射到 CAMOFOX_PORT。

# Install Railway CLI, then:
railway link
railway up

通过 Railway 仪表板或 CLI 设置秘密:

railway variables set CAMOFOX_API_KEY="your-generated-key"

使用

Cookie 导入

将浏览器中的 Cookie 导入 Camoufox,以跳过例如 LinkedIn、Amazon 等网站的互动登录。

设置

1. 生成一个密钥:

# macOS / Linux
openssl rand -hex 32

2. 在启动 OpenClaw 之前设置环境变量:

export CAMOFOX_API_KEY="your-generated-key"
openclaw start

相同的密钥同时被插件(用于验证请求)和服务器(用于验证请求)使用。两者都运行在相同的环境中——只需设置一次。

为什么使用环境变量? 密钥是机密信息。openclaw.json 中的插件配置以明文存储,因此秘密信息不应该放在那里。在你的 shell 配置文件、systemd 单元、Docker 环境变量或 Fly.io secrets 中设置 CAMOFOX_API_KEY。

默认情况下禁用 cookie 导入。 如果未设置 CAMOFOX_API_KEY,服务器会以 403 拒绝所有 cookie 请求。

3. 从浏览器导出 cookie:

安装一个可以导出 Netscape 格式 cookie 文件的浏览器扩展(例如 Chrome/Firefox 的“cookies.txt”)。导出你希望进行身份验证的网站的 cookie。

4. 放置 cookie 文件:

mkdir -p ~/.camofox/cookies
cp ~/Downloads/linkedin_cookies.txt ~/.camofox/cookies/linkedin.txt

默认目录是 ~/.camofox/cookies/。可以通过 CAMOFOX_COOKIES_DIR 覆盖。

5. 让你的代理导入它们:

从 linkedin.txt 导入我的 LinkedIn cookies

代理调用 camofox_import_cookies -> 读取文件 -> 使用 Bearer 令牌 POST 到服务器 -> cookies 被注入到浏览器会话中。随后对 linkedin.com 的 camofox_create_tab 调用将是已认证的。

它的工作原理

~/.camofox/cookies/linkedin.txt          (Netscape format, on disk)
        |
        v
camofox_import_cookies tool              (parses file, filters by domain)
        |
        v  POST /sessions/:userId/cookies
        |  Authorization: Bearer <CAMOFOX_API_KEY>
        |  Body: { cookies: [Playwright cookie objects] }
        v
camofox server                           (validates, sanitizes, injects)
        |
        v  context.addCookies(...)
        |
Camoufox browser session                 (authenticated browsing)
  • cookiesPath 是相对于 cookies 目录解析的——阻止了该目录之外的路径遍历
  • 每个请求最多 500 个 cookie,文件大小限制为 5MB
  • Cookie 对象会清理为 Playwright 字段的允许列表

会话持久化

默认情况下,camofox 会将每个用户的 cookies 和 localStorage 持久化到 ~/.camofox/profiles/。会话在浏览器重启后依然有效——只需登录一次(通过 cookies 或 VNC),随后会话会自动恢复已认证状态。

~/.camofox/
|-- cookies/          # Bootstrap cookie files (Netscape format)
\-- profiles/         # Persisted session state (auto-managed)
    \-- <hashed-userId>/
        \-- storage_state.json

通过 CAMOFOX_PROFILE_DIR 覆盖目录,或在持久化插件配置中设置 "profileDir"。要禁用持久化,请在 camofox.config.json 中设置 "persistence": { "enabled": false }。

默认情况下,存储状态只包含 cookies 和 localStorage。要同时持久化 IndexedDB,请在持久化插件配置中设置 "indexedDB": true。这将捕获所有可序列化的 IndexedDB 记录——不仅仅是身份验证数据——并可能使快照显著增大,检查点速度变慢。

会话追踪

捕获会话中每个操作的 Playwright 追踪:页面截图、DOM 快照、网络请求和控制台输出。输出为单个 .zip 文件,可在 Playwright 内置的 Trace Viewer 中打开。

在打开第一个标签页时,通过传递 trace: true 选择每个会话:

curl -X POST http://localhost:9377/tabs \
  -H 'Content-Type: application/json' \
  -d '{"userId":"agent1","sessionKey":"task1","url":"https://example.com","trace":true}'

跟踪在会话关闭时写入。关闭会话以刷新它,然后列出、获取并查看:

# Close the session to flush the trace
curl -X DELETE http://localhost:9377/sessions/agent1

# List trace files
curl http://localhost:9377/sessions/agent1/traces
# {"traces":[{"filename":"trace-2026-04-18T04-05-00-...zip","sizeBytes":42810,"createdAt":...}]}

# Download (Content-Type: application/zip)
curl http://localhost:9377/sessions/agent1/traces/trace-2026-04-18T04-05-00-abc.zip > session.zip

# View it in Playwright's Trace Viewer
npx playwright show-trace session.zip

# Delete
curl -X DELETE http://localhost:9377/sessions/agent1/traces/trace-2026-04-18T04-05-00-abc.zip

为什么使用追踪而不是视频:Camoufox 基于 Firefox,而 Playwright 的 recordVideo 仅支持 Chromium。追踪可以在 Firefox 上工作,并且提供比视频更多的信息(网络、DOM、控制台、截图)。

追踪无法在现有会话中切换。如果需要更改标志,先执行 DELETE /sessions/:userId。

存储默认在 ~/.camofox/traces/<hashed-userId>/,服务器启动时会清理:

  • CAMOFOX_TRACES_DIR - 基目录(默认:~/.camofox/traces)
  • CAMOFOX_TRACES_MAX_BYTES - 每个追踪的最大大小,如果超出将在下次启动时删除(默认:50MB)
  • CAMOFOX_TRACES_TTL_HOURS - 超过此时间的追踪将在下次启动时删除(默认:24 小时)

独立服务器使用

curl -X POST http://localhost:9377/sessions/agent1/cookies \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer YOUR_CAMOFOX_API_KEY' \
  -d '{"cookies":[{"name":"foo","value":"bar","domain":"example.com","path":"/","expires":-1,"httpOnly":false,"secure":false}]}'

Docker / Fly.io / Railway

docker run -p 9377:9377 \
  -e CAMOFOX_API_KEY="your-generated-key" \
  -v ~/.camofox/cookies:/home/node/.camofox/cookies:ro \
  camofox-browser

Applicable to Fly.io:

fly secrets set CAMOFOX_API_KEY="your-generated-key"

铁路专用:

railway variables set CAMOFOX_API_KEY="your-generated-key"

代理 GeoIP

通过代理路由所有浏览器流量,并通过Camoufox内置的GeoIP根据代理的IP地址自动获取区域、时区和地理位置。

简单代理(单一端点):

export PROXY_HOST=166.88.179.132
export PROXY_PORT=46040
export PROXY_USERNAME=myuser
export PROXY_PASSWORD=mypass
npm start

反向连接代理(旋转粘性会话):

对于像 Decodo、Bright Data 或 Oxylabs 这样提供基于会话的粘性 IP 的单一网关端点的提供商:

export PROXY_STRATEGY=backconnect
export PROXY_BACKCONNECT_HOST=gate.provider.com
export PROXY_BACKCONNECT_PORT=7000
export PROXY_USERNAME=myuser
export PROXY_PASSWORD=mypass
npm start

每个浏览器上下文都会获得一个唯一的粘性会话,因此不同的用户会得到不同的 IP 地址。会话在代理错误或 Google 阻止时会自动轮换。

或者在 Docker 中:

docker run -p 9377:9377 \
  -e PROXY_HOST=166.88.179.132 \
  -e PROXY_PORT=46040 \
  -e PROXY_USERNAME=myuser \
  -e PROXY_PASSWORD=mypass \
  camofox-browser

当配置了代理时:

  • 所有流量都通过代理路由
  • Camoufox 的 GeoIP 会自动设置 locale、timezone 和 geolocation 以匹配代理的出口 IP
  • 浏览器指纹(语言、时区、坐标)与代理位置一致

没有代理时,Camofox 不会声明地理位置,也不会从主机 IP 推断地理位置。要使用固定的直接会话身份,请同时设置 CAMOFOX_LOCALE 和 CAMOFOX_TIMEZONE;否则 Camoufox 会保留其自身的默认身份。

遥测

浏览器自动化可能会以难以预测的方式失败——Cloudflare 挑战、网站重新设计导致选择器失效、重定向循环、对话框风暴、渲染器崩溃。影响范围广,失败模式多样。没有遥测的情况下,唯一的信号是“它没有工作”。

遥测为我们提供有关 哪些网站失败、如何失败 以及 发生频率 的结构化数据,以便我们优先修复真正影响用户的模式。当出现以下情况时,它会自动创建 GitHub Issues:

  • 未捕获的异常 导致进程崩溃
  • 事件循环停滞 超过 5 秒(看门狗检测)
  • 挫败模式 —— 同一标签页连续 3 次失败(超时、上下文失效、导航中止)

每份报告包括失败类型、堆栈跟踪、标签页健康计数器(HTTP 状态直方图、控制台错误、请求失败、重定向深度)以及目标 URL——所有信息均已匿名化。

工作原理

遥测数据发送到轻量级的 Cloudflare Worker 端点 https://camofox-telemetry.askjo.workers.dev。该端点将 GitHub App 凭证作为环境密钥存储——本软件包中不包含任何密钥。

lib/reporter.js (client, no secrets)
    |  anonymize -> POST https://camofox-telemetry.askjo.workers.dev/report
    v
Cloudflare Worker (holds GitHub App key)
    |  validate -> rate-limit -> dedup -> create GitHub Issue
    v
GitHub Issue created

终端源码位于该仓库的 workers/crash-reporter/index.ts。

验证

你不必信任我们 —— 验证实时端点正在运行的内容:

# 1. Ask the endpoint what code it's running
curl https://camofox-telemetry.askjo.workers.dev/source
# -> { "commit": "abc1234", "sha256": "e3b0c44...", "source": "https://github.com/..." }

# 2. Compare the sha256 against the source in this repo
sha256sum workers/crash-reporter/index.ts

# 3. Check the commit matches what CI deployed
#    https://github.com/jo-inc/camofox-browser/actions/workflows/telemetry-deploy.yml
git log --oneline workers/crash-reporter/index.ts | head -1

如果哈希不匹配,则端点运行的代码与仓库中的不同。部署工作流程 (.github/workflows/telemetry-deploy.yml) 会在部署时注入提交和源哈希 —— 每次部署都可以在 GitHub Actions 中审计。

或者完全跳过验证:CAMOFOX_CRASH_REPORT_ENABLED=false 禁用所有遥测,或者使用 CAMOFOX_CRASH_REPORT_URL 指向 您自己的端点。

隐私

所有报告的数据在离开进程之前都会经过严格匿名化 (lib/reporter.js L28-290):

  • URL —— 知名公共域名(Google、Amazon、Reddit、Cloudflare 等)会如实显示,以便我们识别哪些网站会导致问题。私有/未知域名会被替换为稳定的 HMAC 哈希(site-a1b2c3d4) —— 不同报告中使用相同哈希以便关联,但不能反向还原为原始域名。路径段会变为 */*/*(仅保留深度)。查询参数会变为 ?[3](仅保留数量)。绝不包含密钥、值或路径内容。
  • 文件路径 -> 只保留文件名 (<path>/server.js)
  • 令牌、密钥、API 密钥 -> <token>
  • IP、邮件、环境变量 -> 已编辑
  • Docker/Fly 机器 ID -> <id>
  • 标签健康 —— 纯计数器(崩溃次数、错误次数、状态码直方图)。不包含页面内容、不包含 URL、不包含用户数据。

重复问题通过堆栈签名检测,并获得一个 +1 注释,而不是新问题。

# Disable telemetry
export CAMOFOX_CRASH_REPORT_ENABLED=false

# Point to your own endpoint (see below)
export CAMOFOX_CRASH_REPORT_URL=https://your-endpoint.example.com/report

# Adjust rate limit (default: 10 per hour)
export CAMOFOX_CRASH_REPORT_RATE_LIMIT=5

自托管遥测端点

在您自己的 GitHub 仓库中归档遥测报告,而不是 jo-inc/camofox-browser:

  1. 创建一个 GitHub 应用 -- 设置 -> 开发者设置 -> GitHub 应用 -> 新建

    • 权限:仓库 -> 问题 -> 读与写
    • 取消勾选 Webhook -> 激活(不需要)
    • 点击 生成密钥 -- 下载 .pem 文件
    • 在目标仓库中安装应用(安装应用 -> 选择仓库)
    • 记下您的 应用 ID(应用通用页面上的数字)和 安装 ID(安装后 URL 中的 github.com/settings/installations/{id})
  2. 部署端点 -- 克隆此仓库并部署 worker:

    cd workers/crash-reporter
    # Edit wrangler.toml: set account_id to your Cloudflare account ID
    npx wrangler deploy

    该 worker 是一个单独的 TypeScript 文件,没有任何 npm 依赖。它也可以在 Deno、Bun 或任何支持 Web Crypto API 的运行时环境中运行。

  3. 设置 worker 密钥:

    cd workers/crash-reporter
    echo "YOUR_APP_ID" | npx wrangler secret put GH_APP_ID
    echo "YOUR_INSTALL_ID" | npx wrangler secret put GH_INSTALL_ID
    # Key must be PKCS#8 DER base64 (not raw PEM)
    openssl pkcs8 -topk8 -inform PEM -outform DER -nocrypt -in your-app.pem | \
     base64 | tr -d '\n' | npx wrangler secret put GH_PRIVATE_KEY
    # File issues in your repo
    echo "your-org/your-repo" | npx wrangler secret put GH_REPO
  4. 将 camofox-browser 指向您的端点:

    export CAMOFOX_CRASH_REPORT_URL=https://your-worker.your-subdomain.workers.dev/report
  5. 验证:

    curl https://your-worker.your-subdomain.workers.dev/health
    # -> {"status":"ok"}

结构化日志

所有日志输出都是 JSON(每行一个对象),以便日志聚合器轻松解析:

{"ts":"2026-02-11T23:45:01.234Z","level":"info","msg":"req","reqId":"a1b2c3d4","method":"POST","path":"/tabs","userId":"agent1"}
{"ts":"2026-02-11T23:45:01.567Z","level":"info","msg":"res","reqId":"a1b2c3d4","status":200,"ms":333}

健康检查请求(/health)被排除在请求日志之外,以减少噪音。

基础浏览

# Create a tab
curl -X POST http://localhost:9377/tabs \
  -H 'Content-Type: application/json' \
  -d '{"userId": "agent1", "sessionKey": "task1", "url": "https://example.com"}'

# Get accessibility snapshot with element refs
curl "http://localhost:9377/tabs/TAB_ID/snapshot?userId=agent1"
# -> { "snapshot": "[button e1] Submit  [link e2] Learn more", ... }

# Click by ref
curl -X POST http://localhost:9377/tabs/TAB_ID/click \
  -H 'Content-Type: application/json' \
  -d '{"userId": "agent1", "ref": "e1"}'

# Type into an element
curl -X POST http://localhost:9377/tabs/TAB_ID/type \
  -H 'Content-Type: application/json' \
  -d '{"userId": "agent1", "ref": "e2", "text": "hello", "pressEnter": true}'

# Navigate with a search macro
curl -X POST http://localhost:9377/tabs/TAB_ID/navigate \
  -H 'Content-Type: application/json' \
  -d '{"userId": "agent1", "macro": "@google_search", "query": "best coffee beans"}'

应用程序接口

标签生命周期

方法 端点 描述
POST /tabs 创建带有初始 URL 的标签页
GET /tabs?userId=X 列出打开的标签页
GET /tabs/:id/stats 标签页统计(工具调用,访问的 URL)
DELETE /tabs/:id 关闭标签页
DELETE /tabs/group/:groupId 关闭组内的所有标签页
DELETE /sessions/:userId 关闭用户的所有标签页

页面交互

方法 端点 描述
GET /tabs/:id/snapshot 带有元素引用的无障碍快照。查询参数:includeScreenshot=true(添加 base64 PNG),offset=N(分页大量快照)
POST /tabs/:id/click 通过引用或 CSS 选择器点击元素
POST /tabs/:id/type 在元素中输入文本
POST /tabs/:id/press 按下键盘键
POST /tabs/:id/scroll 滚动页面(向上/向下/向左/向右)
POST /tabs/:id/navigate 导航到 URL 或搜索宏
POST /tabs/:id/wait 等待选择器或超时
GET /tabs/:id/links 提取页面上的所有链接
GET /tabs/:id/images 列出 <img> 元素。查询参数:includeData=true(返回内联数据 URL),maxBytes=N,limit=N
GET /tabs/:id/downloads 列出捕获的下载。查询参数:includeData=true(base64 文件数据),consume=true(读取后清除),maxBytes=N
GET /tabs/:id/screenshot 截图
POST /tabs/:id/back 后退
POST /tabs/:id/forward 前进
POST /tabs/:id/refresh 刷新页面

YouTube 字幕

方法 端点 描述
POST /youtube/transcript 从 YouTube 视频中提取字幕
curl -X POST http://localhost:9377/youtube/transcript \
  -H 'Content-Type: application/json' \
  -d '{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "languages": ["en"]}'
# -> { "status": "ok", "transcript": "[00:18] [music] We're no strangers to love [music]\n...", "video_title": "...", "total_words": 548 }

在可用时使用 yt-dlp(快速,无需浏览器)。如果未安装 yt-dlp,则回退到基于浏览器的拦截方法——由于 YouTube 广告前置,这种方法更慢且不太可靠。

服务器

方法 端点 描述
GET /health 健康检查
POST /start 启动浏览器引擎
POST /stop 停止浏览器引擎

会话

方法 端点 描述
GET /tabs/:tabId/downloads 列出已捕获的浏览器下载和保存的当前资源 PDF
POST /tabs/:tabId/fetch-current-resource 使用浏览器会话认证将当前内联 PDF 保存为下载工件
GET /sessions/:userId/storage_state 导出已持久化的浏览器存储(VNC 插件)
DELETE /sessions/:userId/storage_state 重置实时会话并删除其持久化的浏览器存储(持久化插件)

搜索宏

@google_search | @youtube_search | @amazon_search | @reddit_search | @reddit_subreddit | @wikipedia_search | @twitter_search | @yelp_search | @spotify_search | @netflix_search | @linkedin_search | @instagram_search | @tiktok_search | @twitch_search

Reddit 宏直接返回 JSON(无需解析 HTML):

  • @reddit_search - 搜索整个 Reddit,返回包含 25 条结果的 JSON
  • @reddit_subreddit - 浏览一个子版块(例如,查询 "programming" -> /r/programming.json)

浏览器配置

浏览器行为可以在 camofox.config.json 中进行调整:

{
  "newPageTimeoutMs": 10000
}

newPageTimeoutMs 控制标签创建等待 Firefox 创建页面的时间。如果上下文没有响应,Camofox 仅替换该用户的上下文并重试一次。默认值为 10 秒。

环境变量

变量 描述 默认
CAMOFOX_PORT 服务器端口 9377
PORT 服务器端口(回退,用于像 Fly.io、Railway 这样的平台) 9377
CAMOFOX_BIND_HOST 可选的服务器绑定主机。设置为 127.0.0.1 以仅回环访问,或设置为 0.0.0.0 以在所有接口上启用 IPv4。当未设置时,Node 使用其默认的所有接口绑定。 -
CAMOFOX_API_KEY 启用 Cookie 导入端点(如果未设置则禁用) -
CAMOFOX_ADMIN_KEY 需要用于 POST /stop -
CAMOFOX_ACCESS_KEY 如果设置,所有路由(除了 /health、cookie 导入和 /stop)都需要 Authorization: Bearer <key>。允许您安全地在回环之外公开服务器。 -
CAMOFOX_EVALUATE_MAX_BODY_SIZE POST /tabs/:tabId/evaluate 的最大 JSON 请求体大小;其他 JSON 路由仍限制为 100kb。 1mb
CAMOFOX_LOCALE 明确配置的直接会话身份的本地化语言。必须与 CAMOFOX_TIMEZONE 一起设置。 -
CAMOFOX_TIMEZONE 明确配置的直接会话身份的 IANA 时区。必须与 CAMOFOX_LOCALE 一起设置。 -
CAMOUFOX_EXECUTABLE 使用的外部 Camoufox 可执行文件,代替下载/启动捆绑缓存。必须指向包含同级资源的 Camoufox 包。 -
CAMOUFOX_EXECUTABLE_PATH CAMOUFOX_EXECUTABLE 的兼容别名 -
CAMOFOX_EXECUTABLE_PATH CAMOUFOX_EXECUTABLE 的兼容别名 -
CAMOFOX_DISABLE_DEFAULT_ADDONS 设置为 1/true 跳过下载和启动默认的 uBlock Origin (UBO) 插件。在 addons.mozilla.org 下载不可靠或不需要的部署中很有用(否则下载失败会留下损坏的插件缓存,阻止启动)。 0
CAMOFOX_COOKIES_DIR cookie 文件目录 ~/.camofox/cookies
CAMOFOX_UPLOADS_DIR 允许 POST /tabs/:tabId/upload 文件附件的目录。目录之外的路径,包括符号链接逃逸,将被拒绝。 ~/.camofox/uploads
CAMOFOX_PROFILE_DIR 持久化会话配置文件目录 ~/.camofox/profiles
CAMOFOX_TRACES_DIR 会话跟踪压缩文件目录 ~/.camofox/traces
CAMOFOX_TRACES_MAX_BYTES 每个跟踪的最大大小,超过将在下次启动时被删除 52428800 (50MB)
CAMOFOX_TRACES_TTL_HOURS 启动时清理早于此时间的跟踪 24
MAX_SESSIONS 最大并发浏览器会话数 50
MAX_TABS_PER_SESSION 每个会话的最大标签页数 10
SESSION_TIMEOUT_MS 会话无活动超时(0 = 永不) 600000 (10分钟)
BROWSER_IDLE_TIMEOUT_MS 空闲时关闭浏览器(0 = 永不) 300000 (5分钟)
CAMOFOX_INTERACTIVE 交互式浏览器模式:desktop 打开本地真实 Camoufox 窗口;off 保持正常无头行为 off
HANDLER_TIMEOUT_MS 任何处理程序的最大时间 30000 (30秒)
MAX_CONCURRENT_PER_USER 每个用户的并发请求上限 3
MAX_OLD_SPACE_SIZE Node.js V8 堆内存限制 (MB) 128
PROXY_STRATEGY 代理模式:backconnect(轮换粘性会话)或空白(单一端点) -
PROXY_PROTOCOL 代理协议:http、https、socks4 或 socks5 http
PROXY_PROVIDER 会话格式提供商名称(例如 decodo) decodo
PROXY_HOST 代理主机名或 IP(简单模式) -
PROXY_PORT 代理端口(简单模式) -
PROXY_USERNAME 代理认证用户名 -
PROXY_PASSWORD 代理认证密码 -
PROXY_BACKCONNECT_HOST Backconnect 网关主机名 -
PROXY_BACKCONNECT_PORT Backconnect 网关端口 7000
PROXY_COUNTRY 代理地理定位的目标国家 -
PROXY_STATE 代理地理定位的目标州/地区 -
TAB_INACTIVITY_MS 关闭闲置时间超过此值的标签页 300000 (5分钟)
CAMOFOX_CRASH_REPORT_ENABLED 启用匿名崩溃/挂起遥测(设为 false 以禁用) true
CAMOFOX_CRASH_REPORT_URL 遥测端点(自托管端点) https://camofox-telemetry.askjo.workers.dev/report
CAMOFOX_CRASH_REPORT_REPO 遥测问题的 GitHub 仓库 jo-inc/camofox-browser
CAMOFOX_CRASH_REPORT_RATE_LIMIT 每小时最大遥测报告数 10
ENABLE_VNC 启用 VNC 插件以获取交互式浏览器访问 (1) -
VNC_PASSWORD VNC 访问密码(建议在生产环境中使用) -
VNC_BIND noVNC 监听地址;设置为 0.0.0.0 可通过公开的容器端口访问 noVNC 127.0.0.1
VNC_RFB_BIND 原生 VNC 监听地址;非回环地址需要 VNC_PASSWORD,并且不会随 VNC_BIND 变化 127.0.0.1
NOVNC_PORT noVNC Web 界面端口 6080

交互式桌面浏览器

Camofox 默认是无头的。在有本地图形桌面的机器上,可选择显示 Camoufox 窗口:

CAMOFOX_INTERACTIVE=desktop npm start

或者在 camofox.config.json 中设置相同的偏好并重启服务器:

{
  "interactive": { "mode": "desktop" }
}

环境变量会覆盖文件设置。设置 CAMOFOX_INTERACTIVE=off 可恢复正常的无头行为。此模式适用于使用同一台机器的人;它不会暴露远程浏览器控制服务。

架构

Browser Instance (Camoufox)
\-- User Session (BrowserContext) - isolated cookies/storage
    |-- Tab Group (sessionKey: "conv1")
    |   |-- Tab (google.com)
    |   \-- Tab (github.com)
    \-- Tab Group (sessionKey: "conv2")
        \-- Tab (amazon.com)

会话在30分钟不活跃后自动失效。浏览器本身在无活跃会话时5分钟关闭,并在下一个请求时重新启动。

当会话的标签限制达到时,最旧/最少使用的标签页会自动回收,而不是返回错误——这样长期运行的代理会话就不会遇到死胡同。

安全模型

本节记录了 Camofox-browser 为用户和自动安全审查者所面临的安全边界。

代码隔离

所有 process.env 的读取都集中在 lib/config.js 中。所有 child_process 的使用都在 lib/launcher.js(服务器子进程)和 plugins/youtube/youtube.js(yt-dlp)中。主 server.js 有路由处理程序,但没有任何 process.env 的读取,也没有任何 child_process 的导入。没有单个文件同时包含环境/凭据访问和网络发送。

没有嵌入的秘密

此软件包中不包含任何凭证、私钥、API 令牌或签名密钥。所有秘密信息均在运行时通过环境变量提供(CAMOFOX_API_KEY、CAMOFOX_ACCESS_KEY),或者作为 Cloudflare Worker 环境秘密提供(遥测端点 GitHub 应用密钥)。

Cookie导入默认是禁用的

Cookie 导入端点(POST /sessions/:userId/cookies)需要 CAMOFOX_API_KEY 才能访问。如果未设置该环境变量,服务器会以 HTTP 403 拒绝所有 cookie 导入请求。Cookie 文件从一个受限目录(~/.camofox/cookies/)中读取,该目录具有路径遍历保护——尝试逃出目录的操作会被阻止。每次请求最多允许 500 个 cookie,文件大小限制为 5MB。

访问控制

CAMOFOX_ACCESS_KEY 为所有路由(除了 /health)提供全局承载令牌认证。设置后,每个请求都必须包含 Authorization: Bearer <key>。建议在任何超出本地主机的部署中使用。

二进制下载

Camoufox 浏览器引擎(约 300MB)在运行 npm install 时由 camoufox-js 下载,该 npm 包由 Camoufox 项目 维护。它从 官方 GitHub 发布 下载,完整性验证由 camoufox-js 处理。没有自定义下载 URL,没有 URL 缩短器,没有直接 IP 地址。

遥测

匿名崩溃/卡顿遥测数据会发送到 Cloudflare Worker 端点。端点源码位于 此仓库 并且可审计。验证方法:在端点执行 GET /source 会返回已部署的提交哈希和 sha256,你可以与仓库进行比对。报告器 (lib/reporter.js L28-290) 采用严格匿名化:私有域名会进行 HMAC 哈希(不可逆),路径会被移除,令牌/IP/邮箱会被遮蔽。不会发送任何页面内容、Cookie 或用户数据。可通过 CAMOFOX_CRASH_REPORT_ENABLED=false 禁用,或通过 CAMOFOX_CRASH_REPORT_URL 指向你自己的端点。

会话持久性

持久化插件将 cookies 和 localStorage 保存到 ~/.camofox/profiles/<hashed-userId>/,以便经过认证的会话在浏览器重启后仍然有效。UserId 会被哈希用于目录名称。可以通过在 camofox.config.json 中从插件数组中移除 persistence 来禁用。

网络访问

外部连接包括: (1) 代理访问的 URL(核心功能),(2) 遥测端点(匿名,可选择退出)。内部连接:REST API 监听 9377 端口,默认绑定到所有接口,或在配置 CAMOFOX_BIND_HOST 时绑定到指定接口,可选地使用 CAMOFOX_ACCESS_KEY 保护。

子进程使用

可能会启动两个子进程: (1) Camoufox 浏览器引擎(核心功能,lib/launcher.js),(2) yt-dlp 用于 YouTube 字幕提取(可选,plugins/youtube/youtube.js)。两者都在独立文件中隔离,独立于路由处理器。

测试

npm test              # all tests
npm run test:e2e      # e2e tests only
npm run test:live     # live site tests (Google, macros)
npm run test:debug    # with server output

npm

npm install @askjo/camofox-browser

致谢

加密货币诈骗警告

现在,一些可疑的人正在用名为“Camofox”的加密代币做可疑的事情,因为这个项目开始受到关注。Camofox 不是加密项目,也永远不会成为加密项目。任何使用 Camofox 名称的代币、硬币或 NFT 都与我们无关。

许可证

麻省理工学院

本站来源与版权声明
  • 本文标题:camofox-browser - 用于 AI 代理的隐身无头浏览器——绕过 Cloud
  • 本文链接:https://www.cn121.com/agent/jo-inc-camofox-browser.html
  • 原项目:jo-inc/camofox-browser 版权归原作者 jo-inc 及贡献者所有
  • 收录信息:本站于 2026-10-28 收录本项目,本页所列协议与仓库指标均为收录当时的状态;该日期之后原项目的版本更新与协议变更,本页不作同步。
  • 开源协议:收录时本项目采用 MIT(查看 LICENSE 原文),本站转载其原始文档(未改动文字,仅剔除图片与无关章节);使用、修改、分发请以该仓库 LICENSE 原文为准。
  • 站点出处:本文首发于 OneTwoOne,收录自 GitHub 开源项目 jo-inc/camofox-browser。
  • 内容说明:本页正文为原项目 README 原文(英文),本站后续会翻译为中文(当前尚未译出),仅剔除了图片与赞助等无关章节、并把相对链接改为绝对地址;页首简介为机器翻译自仓库描述。
  • 引用声明:商业转载、第三方聚合或 AI 检索训练引用时,请务必保留以上来源出处、本文永久链接,以及原项目的版权声明与许可信息。
  • 下架通道:若原项目此后变更或收紧了许可协议、或作者/权利人认为本站的收录方式(译文、排版适配、简介翻译等)超出其授权范围,请通过 xyd3302001@163.com 发送下架通知,并附上项目地址与本页链接。本站核实后将第一时间删除本页内容,或改为不复制原文的目录性收录;署名更正等其他要求可一并提出。