MCPcopy
hub / github.com/jo-inc/camofox-browser

github.com/jo-inc/camofox-browser @v1.11.2 sqlite

repository ↗ · DeepWiki ↗ · release v1.11.2 ↗
423 symbols 1,425 edges 107 files 46 documented · 11%
README

camofox-browser

camofox-browser

Anti-detection browser server for AI agents, powered by Camoufox

<a href="https://github.com/jo-inc/camofox-browser/raw/v1.11.2/LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT" /></a>
<a href="https://github.com/jo-inc/camofox-browser/stargazers"><img src="https://img.shields.io/github/stars/jo-inc/camofox-browser" alt="GitHub stars" /></a>
<a href="https://www.npmjs.com/package/camofox-browser"><img src="https://img.shields.io/npm/v/camofox-browser" alt="npm version" /></a>
<a href="https://github.com/jo-inc/camofox-browser/commits"><img src="https://img.shields.io/github/last-commit/jo-inc/camofox-browser" alt="GitHub last commit" /></a>






Standing on the mighty shoulders of <a href="https://camoufox.com">Camoufox</a> - a Firefox fork with fingerprint spoofing at the C++ level.

Jo

Built by the team behind jo, a personal AI agent that runs half on your Mac, half on a dedicated cloud machine just for you -- with zero maintenance needed. Available on macOS, Telegram, WhatsApp, and email. Try the beta free ->

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

Why

AI agents need to browse the real web. Playwright gets blocked. Headless Chrome gets fingerprinted. Stealth plugins become the fingerprint.

Camoufox patches Firefox at the C++ implementation level - navigator.hardwareConcurrency, WebGL renderers, AudioContext, screen geometry, WebRTC - all spoofed before JavaScript ever sees them. No shims, no wrappers, no tells.

This project wraps that engine in a REST API built for agents: accessibility snapshots instead of bloated HTML, stable element refs for clicking, and search macros for common sites.

Features

  • C++ Anti-Detection - bypasses Google, Cloudflare, and most bot detection
  • Element Refs - stable e1, e2, e3 identifiers for reliable interaction
  • Token-Efficient - accessibility snapshots are ~90% smaller than raw HTML
  • Runs on Anything - lazy browser launch + idle shutdown keeps memory at ~40MB when idle. Designed to share a box with the rest of your stack -- Raspberry Pi, $5 VPS, shared infra.
  • Session Isolation - separate cookies/storage per user
  • Cookie Import - inject Netscape-format cookie files for authenticated browsing
  • Proxy + GeoIP - route traffic through residential proxies with automatic locale/timezone
  • Structured Logging - JSON log lines with request IDs for production observability
  • YouTube Transcripts - extract captions from any YouTube video via yt-dlp, no API key needed
  • Search Macros - @google_search, @youtube_search, @amazon_search, @reddit_subreddit, and 10 more
  • Snapshot Screenshots - include a base64 PNG screenshot alongside the accessibility snapshot
  • Large Page Handling - automatic snapshot truncation with offset-based pagination
  • Download Capture - capture browser downloads and fetch them via API (optional inline base64)
  • DOM Image Extraction - list <img> src/alt and optionally return inline data URLs
  • Deploy Anywhere - Docker, Fly.io, Railway
  • VNC Interactive Login - log into sites visually via noVNC, export storage state for agent reuse
  • OpenAPI Docs - auto-generated spec at /openapi.json and interactive docs at /docs
  • Structured Extract - POST /tabs/:tabId/extract with a JSON Schema that maps properties to snapshot refs via x-ref
  • Session Tracing - opt-in per-session Playwright trace capture (screenshots + DOM snapshots + network) with API endpoints to list, fetch, and delete trace zips
  • Telemetry - automatic anonymized crash/hang telemetry via GitHub Issues. Identifies which sites cause failures and common failure patterns. Private domains are HMAC-hashed, paths/params stripped, tokens/IPs redacted. Opt-out with CAMOFOX_CRASH_REPORT_ENABLED=false.

Optional Dependencies

Dependency Purpose Install
yt-dlp YouTube transcript extraction (fast path) pip install yt-dlp or brew install yt-dlp

The Docker image includes yt-dlp. For local dev, install it for the /youtube/transcript endpoint. Without it, the endpoint falls back to a slower browser-based method.

Quick Start

OpenClaw Plugin

openclaw plugins install @askjo/camofox-browser

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

Standalone

Run from npm:

npx @askjo/camofox-browser

Or from source:

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

Default port is 9377. See Environment Variables for all options.

Note: the postinstall script unsets PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD for itself before fetching the Camoufox binary. Without that override, an exported PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 (common when Playwright is configured to use system Chrome) would silently skip the binary download and crash the server at runtime.

External Camoufox executable: set CAMOUFOX_EXECUTABLE=/path/to/camoufox-bin before npm install and when starting the server to skip the bundled download and launch that executable. Compatibility aliases are CAMOUFOX_EXECUTABLE_PATH and CAMOFOX_EXECUTABLE_PATH. This is useful for NixOS paths such as /nix/store/.../camoufox-bin; the executable must come from a Camoufox bundle that includes properties.json, version.json, and fontconfig/.

Air-gapped or custom binary management: prefer CAMOUFOX_EXECUTABLE when you already have a Camoufox bundle. Otherwise disable the auto-fetch with npm install --ignore-scripts (skips lifecycle scripts for every dependency -- bluntest option) or, more surgically, npm install --omit=optional plus a manual npx camoufox-js fetch step against your mirror. Note that PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm install no longer skips the Camoufox download (the postinstall sanitizes the env locally); use --ignore-scripts or CAMOUFOX_EXECUTABLE for that.

Docker

The included Makefile auto-detects your CPU architecture and pre-downloads Camoufox + yt-dlp binaries outside the Docker build, so rebuilds are fast (~30s vs ~3min).

# 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

On Windows, make is not available. Use the included build.ps1 PowerShell script instead:

# 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

Note: PowerShell 7+ (pwsh) is recommended but powershell.exe (Windows PowerShell 5.1) also works. The script requires Docker Desktop for Windows with the WSL2 backend.

Line endings: This project includes a .gitattributes file that forces Unix (LF) line endings for .sh files. If you've already cloned the repo and get sh: not found or set: Illegal option - errors during docker build, run: powershell Get-ChildItem -Recurse *.sh | ForEach-Object { (Get-Content $_) -join "`n" + "`n" | Set-Content $_ -NoNewline } This converts shell scripts to LF line endings. Future clones will handle this automatically thanks to .gitattributes.

WARNING: Do not run docker build directly. The Dockerfile uses bind mounts to pull pre-downloaded binaries from dist/. Always use make up (or make fetch then make build) -- it downloads the binaries first.

Fly.io

For Fly.io or other remote CI, you'll need a Dockerfile that downloads binaries at build time instead of using bind mounts.

Railway

A railway.toml is included. It uses Dockerfile.ci (which downloads binaries at build time) and maps Railway's PORT env var to CAMOFOX_PORT automatically.

# Install Railway CLI, then:
railway link
railway up

Set secrets via the Railway dashboard or CLI:

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

Usage

Cookie Import

Import cookies from your browser into Camoufox to skip interactive login on sites like LinkedIn, Amazon, etc.

Setup

1. Generate a secret key:

# macOS / Linux
openssl rand -hex 32

2. Set the environment variable before starting OpenClaw:

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

The same key is used by both the plugin (to authenticate requests) and the server (to verify them). Both run from the same environment -- set it once.

Why an env var? The key is a secret. Plugin config in openclaw.json is stored in plaintext, so secrets don't belong there. Set CAMOFOX_API_KEY in your shell profile, systemd unit, Docker env, or Fly.io secrets.

Cookie import is disabled by default. If CAMOFOX_API_KEY is not set, the server rejects all cookie requests with 403.

3. Export cookies from your browser:

Install a browser extension that exports Netscape-format cookie files (e.g., "cookies.txt" for Chrome/Firefox). Export the cookies for the site you want to authenticate.

4. Place the cookie file:

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

The default directory is ~/.camofox/cookies/. Override with CAMOFOX_COOKIES_DIR.

5. Ask your agent to import them:

Import my LinkedIn cookies from linkedin.txt

The agent calls camofox_import_cookies -> reads the file -> POSTs to the server with the Bearer token -> cookies are injected into the browser session. Subsequent camofox_create_tab calls to linkedin.com will be authenticated.

How it works

~/.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 is resolved relative to the cookies directory -- path traversal outside it is blocked
  • Max 500 cookies per request, 5MB file size limit
  • Cookie objects are sanitized to an allowlist of Playwright fields

Session Persistence

By default, camofox persists each user's cookies and localStorage to ~/.camofox/profiles/. Sessions survive browser restarts -- log in once (via cookies or VNC), and subsequent sessions restore the authenticated state automatically.

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

Override the directory with CAMOFOX_PROFILE_DIR or set "profileDir" in the persistence plugin config. To disable persistence, set "persistence": { "enabled": false } in camofox.config.json.

Session Tracing

Capture a Playwright trace of every action in a session: page screenshots, DOM snapshots, network requests, and console output. Output is a single .zip file you can open in Playwright's built-in Trace Viewer.

Opt-in per session by passing trace: true when opening the first tab:

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

The trace is written when the session closes. Close the session to flush it, then list, fetch, and view:

# 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

Why traces instead of video: Camoufox is Firefox-based, and Playwright's recordVideo is Chromium-only. Traces work on Firefox and give you more than video (network + DOM + console + screenshots).

Tracing cannot be toggled on an existing session. DELETE /sessions/:userId first if you need to change the flag.

Storage defaults to ~/.camofox/traces/<hashed-userId>/ and is swept on server startup:

  • CAMOFOX_TRACES_DIR - base directory (default: ~/.camofox/traces)
  • CAMOFOX_TRACES_MAX_BYTES - max size per trace,

Extension points exported contracts — how you extend this code

Env (Interface)
* Cloudflare Worker relay for camofox-browser crash reports. * * Accepts anonymized crash/hang/stall reports from clie
workers/crash-reporter/index.ts
PluginConfig (Interface)
(no doc)
plugin.ts
CrashReport (Interface)
(no doc)
workers/crash-reporter/index.ts
ToolResult (Interface)
(no doc)
plugin.ts
HealthCheckResult (Interface)
(no doc)
plugin.ts
CliContext (Interface)
(no doc)
plugin.ts
ToolContext (Interface)
(no doc)
plugin.ts

Core symbols most depended-on inside this repo

log
called by 191
server.js
createTab
called by 104
tests/helpers/client.js
createClient
called by 101
tests/helpers/client.js
cleanup
called by 99
tests/helpers/client.js
getSnapshot
called by 68
tests/helpers/client.js
anonymize
called by 52
lib/reporter.js
fetch
called by 48
workers/crash-reporter/index.ts
normalizeUserId
called by 45
server.js

Shape

Function 368
Method 35
Class 12
Interface 8

Languages

TypeScript100%

Modules by API surface

server.js91 symbols
tests/helpers/client.js28 symbols
lib/reporter.js28 symbols
lib/metrics.js16 symbols
scripts/plugin.js14 symbols
lib/proxy.js14 symbols
workers/crash-reporter/index.ts13 symbols
plugin.ts13 symbols
plugins/youtube/youtube.js12 symbols
lib/tracing.js10 symbols
lib/camoufox-executable.js10 symbols
lib/downloads.js8 symbols

Dependencies from manifests, versioned

@types/node22.0.0 · 1×
camoufox-js>=0.10.0 · 1×
express4.18.2 · 1×
jest29.7.0 · 1×
playwright-core1.58.0 · 1×
pngjs7.0.0 · 1×
prom-client15.1.3 · 1×
swagger-jsdoc6.2.8 · 1×
typescript5.7.0 · 1×

For agents

$ claude mcp add camofox-browser \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact