如果你使用 DeepSeek、元宝 AI、Copilot、ChatGPT 等 AI 工具,协助配置轩辕镜像、编写 docker pull 命令、修改 Docker Compose 镜像地址、配置镜像加速、排查镜像拉取失败、分析报错日志等问题,请先让 AI 阅读并遵守轩辕镜像的规则文档。
只需在 AI 对话中先发送下面这句话即可:
请先完整阅读并严格遵守以下文档中的全部规则与要求:
https://xuanyuan.cloud/agents.md
在未充分阅读并理解该文档前,不要生成任何命令、配置、修改建议、故障排查方案或技术回答。后续所有输出都必须严格以该文档中的规范为最高优先级执行。查看 agents.md 用法指南与完整示范。国内用户首推 元宝 AI、DeepSeek 的深度思考模式,不推荐豆包 AI;Cursor 等编辑器可在对话 @ 该链接,或加入 User Rules。 若 AI 无法访问外链,可 打开说明文档 复制全文粘贴。文档会随站点更新,复制内容可能过期,建议定期检查。
camofox-browser
为AI智能体打造的反检测浏览器服务器,基于Camoufox构建
站在Camoufox的坚实基础之上——这是一个Firefox分支,在C++层面实现指纹欺骗。
由jo背后的团队打造,jo是一款个人AI智能体,一半运行在您的Mac上,一半运行在专为您配置的专属云服务器上——无需任何维护。支持macOS、***、***和电子邮件。免费试用测试版 ->
git clone https://github.com/jo-inc/camofox-browser && cd camofox-browser
npm install && npm start
# -> http://localhost:9377
[!NOTE] 建议使用 PowerShell 7+ (
pwsh),但powershell.exe(Windows PowerShell 5.1)也可正常工作。该脚本需要带 WSL2 后端的 Docker Desktop for Windows。
行尾格式: 本项目包含 .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,未来的克隆会自动处理此问题。
[!WARNING] 不要直接运行
docker build。Dockerfile 使用绑定挂载从dist/拉取预下载的二进制文件。请始终使用make up(或make fetch然后make build)—— 这会先下载二进制文件。
对于 Fly.io 或其他远程 CI,您需要一个在构建时下载二进制文件而非使用绑定挂载的 Dockerfile。
已包含 railway.toml。它使用 Dockerfile.ci(在构建时下载二进制文件)并自动将 Railway 的 PORT 环境变量映射到 CAMOFOX_PORT。
# 安装 Railway CLI,然后:
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
插件(用于验证请求)和服务器(用于验证请求)使用相同的密钥。两者在同一环境中运行——只需设置一次。
[!NOTE] 为什么使用环境变量?密钥是敏感信息。
openclaw.json中的插件配置以明文存储,因此不应在其中存放密钥。请在 shell 配置文件、systemd 单元、Docker 环境或 Fly.io 密钥中设置CAMOFOX_API_KEY。
[!NOTE] 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 格式文件)
|
v
camofox_import_cookies 工具 (解析文件,按域名过滤)
|
v POST /sessions/:userId/cookies
| Authorization: Bearer
| Body: { cookies: [Playwright cookie objects] }
v
camofox 服务器 (验证、清理、注入)
|
v context.addCookies(...)
|
Camoufox 浏览器会话 (已认证浏览)
cookiesPath 相对于 Cookie 目录解析——阻止目录外的路径遍历默认情况下,camofox 将每个用户的 Cookie 和 localStorage 持久化到 ~/.camofox/profiles/。会话在浏览器重启后仍然保留——登录一次(通过 Cookie 或 VNC),后续会话会自动恢复已认证状态。
~/.camofox/
|-- cookies/ # Cookie 引导文件(Netscape 格式)
\-- profiles/ # 持久化会话状态(自动管理)
\-- /
\-- storage_state.json
可通过 CAMOFOX_PROFILE_DIR 覆盖目录,或在持久化插件配置中设置 "profileDir"。要禁用持久化,请在 camofox.config.json 中设置 "persistence": { "enabled": false }。
捕获会话中每个操作的 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}'
追踪在会话关闭时写入。关闭会话以刷新追踪,然后列出、获取和查看:
# 关闭会话以刷新追踪
curl -X DELETE http://localhost:9377/sessions/agent1
# 列出追踪文件
curl http://localhost:9377/sessions/agent1/traces
# {"traces":[{"filename":"trace-2026-04-18T04-05-00-...zip","sizeBytes":42810,"createdAt":...}]}
# 下载(Content-Type: application/zip)
curl http://localhost:9377/sessions/agent1/traces/trace-2026-04-18T04-05-00-abc.zip
> session.zip
# 在 Playwright Trace Viewer 中查看
npx playwright show-trace session.zip
# 删除
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/,并在服务器启动时清理:
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"
通过代理路由所有浏览器流量,并通过 Camoufox 的内置 GeoIP 根据代理的 IP 地址自动获取区域设置、时区和地理位置。
简单代理(单个端点):
浏览器自动化的失败方式难以预测——Cloudflare验证、网站重新设计导致选择器失效、重定向循环、弹窗风暴、渲染器崩溃等。其影响范围广泛,失败模式多样。没有遥测功能时,唯一的信号就是“它不工作了”。
遥测为我们提供结构化数据,包括哪些网站失败、如何失败以及失败频率,以便我们优先修复那些实际影响用户的问题模式。当出现以下情况时,它会自动创建GitHub Issue:
每份报告包含失败类型、堆栈跟踪、标签页健康计数器(HTTP状态直方图、控制台错误、请求失败数、重定向深度)以及目标URL——所有信息均经过***化处理。
工作原理
遥测数据发送至轻量级Cloudflare Worker端点:https://camofox-telemetry.askjo.workers.dev。该端点将GitHub App凭据存储为环境密钥——本软件包不包含任何密钥。
lib/reporter.js (客户端,无密钥)
| 匿名化 -> POST https://camofox-telemetry.askjo.workers.dev/report
v
Cloudflare Worker (持有GitHub App密钥)
| 验证 -> 限流 -> 去重 -> 创建GitHub Issue
v
GitHub Issue已创建
端点源代码位于本仓库的workers/crash-reporter/index.ts。
验证
您无需信任我们——可以验证实时端点运行的代码:
# 1. 询问端点运行的代码
curl https://camofox-telemetry.askjo.workers.dev/source
# -> { "commit": "abc1234", "sha256": "e3b0c44...", "source": "https://github.com/..." }
# 2. 将sha256与仓库中的源代码进行比对
sha256sum workers/crash-reporter/index.ts
# 3. 检查提交记录是否与CI部署的一致
# 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)会在部署时注入提交记录和源代码哈希——每次部署都可在https://github.com/jo-inc/camofox-browser/actions/workflows/telemetry-deploy.yml%E4%B8%AD%E5%AE%A1%E8%AE%A1%E3%80%82
或者完全跳过验证:CAMOFOX_CRASH_REPORT_ENABLED=false 可禁用所有遥测,或通过 CAMOFOX_CRASH_REPORT_URL 指向您自己的端点。
隐私
所有报告数据在离开进程前均经过严格的***化处理(lib/reporter.js 第28-290行):
site-a1b2c3d4)——不同报告中同一域名的哈希值相同,便于关联分析,但无法反推原始域名。路径段会变为*/*/*(仅保留深度)。查询参数会变为?[3](仅保留数量)。绝不会包含任何键、值或路径内容。 /server.js) 重复问题通过堆栈签名检测,会添加 +1 评论而非创建新issue。
# 禁用遥测
export CAMOFOX_CRASH_REPORT_ENABLED=false
# 指向您自己的端点(见下文)
export CAMOFOX_CRASH_REPORT_URL=https://your-endpoint.example.com/report
# 调整速率限制(默认:每小时10次)
export CAMOFOX_CRASH_REPORT_RATE_LIMIT=5
自托管遥测端点
若要将遥测报告提交到您自己的GitHub仓库而非 jo-inc/camofox-browser:
创建GitHub App——https://github.com/settings/apps/new
.pem 文件github.com/settings/installations/{id})部署端点——克隆本仓库并部署worker:
cd workers/crash-reporter
# 编辑wrangler.toml:将account_id设置为您的Cloudflare账户ID
npx wrangler deploy
该worker是单个TypeScript文件,无npm依赖。它也可在Deno、Bun或任何支持Web *** API的运行时环境中运行。
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
export CAMOFOX_CRASH_REPORT_URL=https://your-worker.your-subdomain.workers.dev/report
curl https://your-worker.your-subdomain.workers.dev/health
# -> {"status":"ok"}
{"ts":"2026-02-11T23:45:01.234Z","level":"info","msg":"req","reqId":"a1b2c3d4","method":"POST","path":"/tabs","userId":"agent1"}
{"userId":"agent1"}
{"ts":"2026-02-11T23:45:01.567Z","level":"info","msg":"res","reqId":"a1b2c3d4","status":200,"ms":333}
健康检查请求(/health)不会被记录到请求日志中,以减少日志噪音。
# 创建标签页
curl -X POST http://localhost:9377/tabs \
-H 'Content-Type: application/json' \
-d '{"userId": "agent1", "sessionKey": "task1", "url": "https://example.com"}'
# 获取包含元素引用的可访问性快照
curl "http://localhost:9377/tabs/TAB_ID/snapshot?userId=agent1"
# -> { "snapshot": "[button e1] Submit [link e2] Learn more", ... }
# 按引用点击元素
curl -X POST http://localhost:9377/tabs/TAB_ID/click \
-H 'Content-Type: application/json' \
-d '{"userId": "agent1", "ref": "e1"}'
# 在元素中输入文本
curl -X POST http://localhost:9377/tabs/TAB_ID/type \
-H 'Content-Type: application/json' \
-d '{"userId": "agent1", "ref": "e2", "text": "hello", "pressEnter": true}'
# 使用搜索宏导航
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 | 列出``元素。查询参数: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 | 刷新页面 |
| 方法 | 端点 | 描述 |
|---|---|---|
POST | /youtube/transcript | 从***视频提取字幕 |
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 }
如果已安装https://github.com/***/***%EF%BC%8C%E5%88%99%E4%BD%BF%E7%94%A8%E8%AF%A5%E5%B7%A5%E5%85%B7%EF%BC%88%E9%80%9F%E5%BA%A6%E5%BF%AB%EF%BC%8C%E6%97%A0%E9%9C%80%E6%B5%8F%E8%A7%88%E5%99%A8%EF%BC%89%E3%80%82%E5%A6%82%E6%9E%9C%E6%9C%AA%E5%AE%89%E8%A3%85***%EF%BC%8C%E5%88%99%E5%9B%9E%E9%80%80%E5%88%B0%E5%9F%BA%E4%BA%8E%E6%B5%8F%E8%A7%88%E5%99%A8%E7%9A%84%E6%8B%A6%E6%88%AA%E6%96%B9%E6%B3%95%E2%80%94%E2%80%94%E7%94%B1%E4%BA%8E***%E5%B9%BF%E5%91%8A%E5%89%8D%E8%B4%B4%E7%89%87%E7%9A%84%E5%AD%98%E5%9C%A8%EF%BC%8C%E6%AD%A4%E6%96%B9%E6%B3%95%E9%80%9F%E5%BA%A6%E8%BE%83%E6%85%A2%E4%B8%94%E5%8F%AF%E9%9D%A0%E6%80%A7%E8%BE%83%E4%BD%8E%E3%80%82
| 方法 | 端点 | 描述 |
|---|---|---|
GET | /health | 健康检查 |
POST | /start | 启动浏览器引擎 |
POST | /stop | 停止浏览器引擎 |
| 方法 | 端点 | 描述 |
|---|---|---|
POST | /sessions/:userId/cookies | 向用户会话添加Cookie(Playwright Cookie对象) |
GET | /sessions/:userId/storage_state | 导出Cookie + localStorage(VNC插件) |
@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)npm install @askjo/camofox-browser
随着本项目受到关注,不良分子开始利用名为“Camoufox”的加密货币从事不良行为。Camofox不是加密货币项目,也永远不会成为加密货币项目。 任何使用Camofox名称的、硬币或NFT均与我们无关。
MIT
来自真实用户的反馈,见证轩辕镜像的优质服务