camofox-browser:基于 Firefox 内核的 AI 代理网页浏览项目

Stealth headless browser for AI agents — bypass Cloudflare, bot detection, and anti-scraping. Drop-in Puppeteer/Playwright replacement.

分支22Tags44
文件最后提交记录最后更新时间
1 个月前
3 个月前
5 个月前
4 个月前
20 天前
19 天前
20 天前
1 个月前
20 天前
3 个月前
3 个月前
4 个月前
1 个月前
6 个月前
22 天前
20 天前
6 个月前
1 个月前
20 天前
3 个月前
6 个月前
20 天前
4 个月前
4 个月前
4 个月前
4 个月前
19 天前
19 天前
19 天前
19 天前
1 个月前
1 个月前
4 个月前
1 个月前
6 个月前
20 天前
4 个月前
4 个月前
camofox-browser

camofox-browser

为 AI 代理打造的反检测浏览器服务,由 Camoufox 驱动

License: MIT GitHub stars npm version GitHub last commit

站在 Camoufox 这位巨人的肩膀上——这是一款在 C++ 层面实现指纹伪装能力的 Firefox 分支。


Jo

jo 个人 AI 代理 的开发团队打造——jo 一半运行在你的 Mac 上,一半运行在专属于你的云端机器上,完全无需维护。支持 macOS、Telegram、WhatsApp 和电子邮件。 免费试用测试版 ->


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 以及大多数机器人检测系统
  • 元素引用 — 稳定的 e1e2e3 标识符,确保可靠的交互操作
  • 高 Token 效率 — 无障碍快照比原始 HTML 小约 90%
  • 随处可运行 — 浏览器懒启动 + 空闲自动关闭,空闲时内存占用约 40MB。专为与你的其他服务共享同一台机器而设计——树莓派、5 美元 VPS、共享基础设施均可。
  • 会话隔离 — 每个用户独立存储 Cookie 和数据
  • Cookie 导入 — 注入 Netscape 格式的 Cookie 文件,实现已认证状态的浏览
  • 文件上传 — 从配置的上传目录附加文件,无需原生操作系统对话框
  • 代理 + GeoIP — 通过住宅代理路由流量,自动匹配区域设置和时区
  • 结构化日志 — 带请求 ID 的 JSON 日志行,便于生产环境可观测性
  • YouTube 字幕提取 — 通过 yt-dlp 从任意 YouTube 视频提取字幕,无需 API 密钥
  • 搜索宏@google_search@youtube_search@amazon_search@reddit_subreddit 以及另外 10 余种
  • 快照截图 — 在无障碍快照旁附带 base64 PNG 截图
  • 大页面处理 — 自动截断快照,支持基于偏移量的分页
  • 下载捕获 — 捕获浏览器下载内容并可通过 API 获取(可选内联 base64)
  • DOM 图片提取 — 列出 <img> 的 src/alt 属性,可选返回内联 data URL
  • 随处部署 — Docker、Fly.io、Railway
  • VNC 交互式登录 — 通过 noVNC 可视化登录网站,导出存储状态供智能体复用
  • OpenAPI 文档 — 自动生成的规范文件位于 /openapi.json,交互式文档位于 /docs
  • 结构化提取POST /tabs/:tabId/extract 接口,配合 JSON Schema 通过 x-ref 将属性映射到快照引用
  • 会话追踪 — 按会话选择性地捕获 Playwright 追踪(截图 + DOM 快照 + 网络),并提供 API 端点来列出、获取和删除追踪压缩包
  • 遥测 — 通过 GitHub Issues 自动上报匿名化的崩溃/挂起遥测数据。用于识别导致故障的网站和常见故障模式。私有域名经 HMAC 哈希处理,路径/参数被剥离,令牌/IP 被脱敏。可通过 CAMOFOX_CRASH_REPORT_ENABLED=false 关闭。

可选依赖

依赖项 用途 安装方式
yt-dlp YouTube 字幕提取(快速通道) pip install yt-dlpbrew 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。所有选项请参阅环境变量

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

外部 Camoufox 可执行文件:npm install 之前以及启动服务器时,设置 CAMOUFOX_EXECUTABLE=/path/to/camoufox-bin,以跳过捆绑下载并启动该可执行文件。兼容别名包括 CAMOUFOX_EXECUTABLE_PATHCAMOFOX_EXECUTABLE_PATH。这对于 NixOS 路径(如 /nix/store/.../camoufox-bin)非常有用;该可执行文件必须来自包含 properties.jsonversion.jsonfontconfig/ 的 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-scriptsCAMOUFOX_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

在 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 后端的 Docker Desktop for Windows。

换行符: 本项目包含一个 .gitattributes 文件,强制对所有 .sh 文件使用 Unix(LF)换行符。如果你已经克隆了仓库,并且在 docker build 过程中遇到 sh: not foundset: Illegal option - 错误,请运行:

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

此命令会将 shell 脚本转换为 LF 换行符。得益于 .gitattributes,后续克隆将自动处理此问题。

警告:请勿直接运行 docker build Dockerfile 使用绑定挂载(bind mounts)从 dist/ 目录加载预下载的二进制文件。请始终使用 make up(或先执行 make fetch 再执行 make build)——该流程会先下载二进制文件。

Fly.io

对于 Fly.io 或其他远程 CI 环境,你需要一个在构建阶段下载二进制文件(而非使用绑定挂载)的 Dockerfile。

Railway

已包含一个 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 导入 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 机密中设置 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. 让您的智能体导入这些 Cookie:

从 linkedin.txt 导入我的 LinkedIn Cookie

智能体会调用 camofox_import_cookies -> 读取文件 -> 使用 Bearer 令牌向服务器发送 POST 请求 -> Cookie 被注入浏览器会话。随后对 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}'

trace(跟踪记录)在会话关闭时写入。请关闭会话以刷新数据,然后依次执行列出、获取和查看操作:

# 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

为什么用追踪记录(traces)而不是视频: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

对于 Fly.io:

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

对于 Railway:

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 会自动将 localetimezonegeolocation 设置为与代理出口 IP 相匹配
  • 浏览器指纹(语言、时区、坐标)与代理位置保持一致
  • 未配置代理时,默认使用 en-USAmerica/Los_Angeles 以及旧金山坐标

遥测

浏览器自动化会以难以预测的方式失败——Cloudflare 质询、网站改版导致选择器失效、重定向循环、对话框风暴、渲染进程崩溃。失败范围广泛,失败模式多种多样。没有遥测,唯一的信号就是“它没跑通”。

遥测为我们提供结构化数据,告诉我们哪些网站失败如何失败以及失败频率,这样我们就能优先修复那些真正影响用户的模式。当出现以下情况时,遥测会自动提交 GitHub Issue:

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

每条报告都包含失败类型、堆栈跟踪、标签页健康计数器(HTTP 状态码直方图、控制台错误、请求失败、重定向深度)以及目标 URL——全部经过匿名化处理。

工作原理

遥测数据发送至位于 https://camofox-telemetry.askjo.workers.dev 的轻量级 Cloudflare Worker 端点。该端点将 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 评论,而不会创建新 issue。

# 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 App -- Settings -> Developer settings -> GitHub Apps -> New

    • 权限设置:Repository -> Issues -> Read & Write
    • 取消勾选 Webhook -> Active(无需启用)
    • 点击 Generate a key -- 下载 .pem 文件
    • 将应用安装到目标仓库(Install App -> 选择仓库)
    • 记下您的 App ID(应用 General 页面上的数字)和 Installation ID(安装后从 URL 中获取:github.com/settings/installations/{id}
  2. 部署端点 -- 克隆此仓库并部署 worker:

    cd workers/crash-reporter
    # 编辑 wrangler.toml:将 account_id 设置为您的 Cloudflare 账户 ID
    npx wrangler deploy
    

    该 worker 是一个零 npm 依赖的单一 TypeScript 文件,也可在 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
    # 密钥必须为 PKCS#8 DER base64 格式(非原始 PEM)
    openssl pkcs8 -topk8 -inform PEM -outform DER -nocrypt -in your-app.pem | \
      base64 | tr -d '\n' | npx wrangler secret put GH_PRIVATE_KEY
    # 在您的仓库中创建 issue
    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"}'

API

标签页生命周期

方法 端点 描述
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(返回内联 data URL)、maxBytes=Nlimit=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 停止浏览器引擎

会话

方法 端点 描述
POST /sessions/:userId/cookies 向用户会话添加 Cookie(Playwright Cookie 对象)
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
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 会话无活动超时时间 1800000(30分钟)
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_PROVIDER 会话格式的提供商名称(例如 decodo decodo
PROXY_HOST 代理主机名或 IP(简单模式) -
PROXY_PORT 代理端口(简单模式) -
PROXY_USERNAME 代理认证用户名 -
PROXY_PASSWORD 代理认证密码 -
PROXY_BACKCONNECT_HOST 回连网关主机名 -
PROXY_BACKCONNECT_PORT 回连网关端口 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 访问密码(生产环境推荐设置) -
NOVNC_PORT noVNC 网页界面端口 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_KEYCAMOFOX_ACCESS_KEY)提供,或者是 Cloudflare Worker 环境机密(遥测端点的 GitHub App 密钥)。

Cookie 导入端点(POST /sessions/:userId/cookies)由 CAMOFOX_API_KEY 保护。如果未设置此环境变量,服务器将以 HTTP 403 拒绝所有 Cookie 导入请求。Cookie 文件从沙箱目录(~/.camofox/cookies/)读取,并带有路径遍历防护——尝试逃逸该目录的行为将被阻止。每个请求最多 500 个 Cookie,文件大小限制为 5MB。

访问控制

CAMOFOX_ACCESS_KEY 为所有路由(/health 除外)提供全局 Bearer 令牌认证。设置后,每个请求必须包含 Authorization: Bearer <key>。建议任何超出 localhost 的部署都启用此功能。

二进制下载

Camoufox 浏览器引擎(约 300MB)在 npm install 时由 camoufox-js 下载,该 npm 包由 Camoufox 项目 维护。下载源为官方 GitHub Releases,完整性验证由 camoufox-js 处理。无自定义下载 URL、无短链接、无原始 IP 地址。

遥测

匿名的崩溃/挂起遥测数据会发送至一个 Cloudflare Worker 端点。该端点的源代码位于本仓库中,可供审计。验证方式:对端点发起 GET /source 请求,将返回部署时的提交哈希和 sha256 值,方便你与仓库进行比对。报告器(lib/reporter.js L28-290)采用了极为谨慎的匿名化处理:私有域名经过 HMAC 哈希(不可逆),路径会被剥离,令牌/IP/邮箱信息均被脱敏。页面内容、Cookie 或用户数据绝不会被发送。可通过设置 CAMOFOX_CRASH_REPORT_ENABLED=false 来禁用,或通过 CAMOFOX_CRASH_REPORT_URL 指定你自己的端点。

会话持久化

持久化插件会将 Cookie 和 localStorage 保存至 ~/.camofox/profiles/<hashed-userId>/ 目录,从而确保已认证的会话在浏览器重启后依然有效。用户 ID 经过哈希处理后用作目录名称。如需禁用,可在 camofox.config.json 中将 persistence 从插件数组中移除。

网络访问

出站连接包括:(1)代理所导航的 URL(核心功能),(2)遥测端点(匿名数据,可选择退出)。入站连接:REST API 监听于 9377 端口,默认绑定所有网络接口,或可通过 CAMOFOX_BIND_HOST 指定绑定地址,并可选地通过 CAMOFOX_ACCESS_KEY 进行访问保护。

子进程使用

可能会启动两个子进程:(1)Camoufox 浏览器引擎(核心功能,lib/launcher.js),(2)用于 YouTube 转录文本提取的 yt-dlp(可选功能,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 均与我们无关。

许可证

MIT

项目介绍

AI 智能体专用无头浏览器自动化服务器,可访问通常被屏蔽的网站【此简介由AI生成】

定制我的领域
2810.39 K1.05 K访问 GitHub