GitPedia

Camofox browser

Anti-detection browser server for AI agents — REST API wrapping Camoufox engine with OpenClaw plugin support

From redf0x1·Updated June 22, 2026·View on GitHub·

> Anti-detection browser server for AI agents — TypeScript REST API wrapping the [Camoufox](https://github.com/daijro/camoufox) stealth browser engine The project is written primarily in TypeScript, distributed under the MIT License license, first published in 2026. Key topics include: ai-agent, anti-detection, automation, bot-detection, browser-automation.

Latest release: v2.4.6camofox-browser v2.4.6
June 17, 2026View Changelog →

CamoFox Browser Server

Anti-detection browser server for AI agents — TypeScript REST API wrapping the Camoufox stealth browser engine

License: MIT
TypeScript
Node
npm

Table of Contents

Why CamoFox?

The Problem: Standard browser automation (Puppeteer, Playwright, Selenium) is easily detected by modern anti-bot systems. JavaScript-level patches are fragile and get bypassed quickly.

The Solution: CamoFox Browser Server wraps Camoufox, a Firefox fork with C++ engine-level fingerprint spoofing. No JavaScript injection — anti-detection happens at the browser engine level.

FeaturePuppeteer/PlaywrightCamoFox Browser Server
Anti-detectionJavaScript patches (fragile)C++ engine-level (robust)
Fingerprint spoofingLimitedFull (engine-level)
Token efficiencyRaw HTML / screenshotsAccessibility snapshots (smaller + structured)
IntegrationDirect SDKREST API for any language / AI agent
AI agent supportVariesMCP + OpenClaw compatible

Features

  • C++ Anti-Detection — fingerprint spoofing at the Camoufox engine level (not JS injection)
  • REST API — language-agnostic HTTP endpoints for browser automation and AI agent integration
  • Multi-Session — concurrent isolated browser contexts per userId (defaults: max 50 sessions, max 10 tabs/session)
  • Persistent Browser Profiles — Each user gets a dedicated Firefox profile. Cookies, localStorage, IndexedDB, and all browser storage persist across sessions automatically.
  • Geo Presets — 8 built-in region presets (locale/timezone/geolocation) + custom presets file
  • Session-Level Proxy/Geo Overrides — per-session proxy configuration via named profiles or raw credentials, with hybrid geo modes (explicit-wins or proxy-locked)
  • 14 Search Macros — Google, YouTube, Amazon, Reddit (search + subreddit JSON), Wikipedia, Twitter, Yelp, Spotify, Netflix, LinkedIn, Instagram, TikTok, Twitch
  • Element Refs — accessibility snapshots annotated with stable eN element references for precise interaction
  • Cookie Persistence — import Netscape/Playwright-style cookies into a session (bearer auth required only when CAMOFOX_API_KEY is set)
  • OpenClaw Plugin — OpenClaw-compatible endpoints (/start, /tabs/open, /act, etc.)
  • TypeScript — strict mode, typed request shapes, modular Express routes
  • YouTube Transcript Extraction — yt-dlp + browser fallback (service-level; no public API route currently exposed)
  • Snapshot Pagination — offset-based windowing for large page snapshots
  • Image Listing Route — image-only extraction over the shared resource extractor with selector, extension, lazy-load, and blob-resolution controls
  • Structured Extract — deterministic schema-driven JSON extraction across core API, CLI, and OpenClaw without arbitrary JavaScript
  • Browser Health Monitoring — health probe with recovery/degraded state tracking
  • 🖥️ CLI Mode — 50+ commands for terminal-based browser automation
  • 🔐 Auth Vault — AES-256-GCM encrypted credential storage (LLM-safe)
  • 📜 Pipeline Scripting — Execute command scripts from files
  • 🔍 Console Capture — capture and filter browser console messages and uncaught errors
  • 📼 Playwright Tracing — record and export Playwright traces for debugging
  • 🗂️ Trace Artifact Management — list, download, and delete managed trace ZIPs per user session

Preview Status

CamoFox Browser Server is in Preview (Phase 1). Preview releases are functional for browser automation and agent integration, but carry specific compatibility commitments and explicit non-goals.

What Preview Means

  • The REST API and CLI are usable for agent workflows today; CamoFox MCP is available as an external companion integration
  • New features may be added between minor versions
  • Backward-compatible aliases are maintained for renamed or moved endpoints (see Compatibility Policy)
  • Local state (profiles, registries, sessions) uses versioned formats with fail-closed integrity checks

What Preview Does NOT Guarantee

  • Frozen API surface — endpoint behavior, request shapes, or response formats may change between minor versions
  • Automatic local-state migration — browser profiles, download registries, and session files use versioned sidecar formats; incompatible upgrades require manual reset (see Local State Recovery)
  • Downgrade safety — rolling back to an older version may require clearing local state
  • Fixed GA timeline — promotion to GA requires meeting evidence-based exit criteria, not a calendar date

Compatibility Policy

During Preview, CamoFox follows an additive-only deprecation model:

  • Legacy aliases (e.g., listItemId accepted alongside sessionKey, OpenClaw /act routing to core endpoints) continue to work alongside their replacements
  • Deprecated fields are accepted silently; no removal until GA or a documented migration window with advance notice in CHANGELOG
  • No existing endpoint is removed in a minor version — removals happen only in major versions with prior CHANGELOG notice

Local State Recovery

Browser profiles, download registries, and CLI session files use versioned sidecar formats. When upgrading CamoFox:

  • Compatible versions: State loads normally
  • Incompatible or corrupt state: The server refuses to load incompatible profiles and download registries; the CLI rejects incompatible saved-session files. Both log an actionable error with the specific recovery path.
  • Recovery: Delete the affected profile directory, session file, or download registry as indicated in the error message. Clean state is recreated on next use.

Supported sidecars include limited forward-migration paths (e.g., fingerprint v0 → v1); when no migration path exists for a given version, the server refuses to load the file and logs an actionable recovery message. There is no silent repair or downgrade path — this fail-closed default prevents data corruption at the cost of manual intervention on unsupported version jumps.

Quick Start

From Source

bash
git clone https://github.com/redf0x1/camofox-browser.git cd camofox-browser npm install npm run build npm start

Using npm (CLI)

bash
npm install -g camofox-browser # Start the server camofox-browser # Or use the CLI for browser automation camofox open https://example.com camofox snapshot camofox click e5

See CLI for the complete command reference.

Using Docker

Docker image: ghcr.io/redf0x1/camofox-browser

bash
docker build -t camofox-browser . docker run -d \ --name camofox-browser \ -p 9377:9377 \ -p 6080:6080 \ -e CAMOFOX_HOST=0.0.0.0 \ -e CAMOFOX_AUTH_MODE=auto \ -e CAMOFOX_API_KEY=change-me \ -v ~/.camofox:/home/node/.camofox \ camofox-browser

To persist browser profiles (cookies, localStorage, IndexedDB, etc.) across container restarts, keep the volume mount shown above.

Using Docker Compose

yaml
services: camofox-browser: build: . ports: - "9377:9377" environment: CAMOFOX_HOST: "0.0.0.0" CAMOFOX_PORT: "9377" # auto requires CAMOFOX_API_KEY when CAMOFOX_HOST is non-loopback CAMOFOX_AUTH_MODE: "auto" CAMOFOX_API_KEY: "change-me" # CAMOFOX_ADMIN_KEY: "change-me" # Optional: proxy routing (also enables Camoufox geoip mode) # PROXY_HOST: "" # PROXY_PORT: "" # PROXY_USERNAME: "" # PROXY_PASSWORD: ""

Verify

bash
curl http://localhost:9377/health # {"ok":true,"engine":"camoufox","browserConnected":true}

CLI

CamoFox Browser includes a powerful CLI for browser automation directly from the terminal. The CLI auto-starts the server when needed.

Installation

bash
# Global install (recommended) npm install -g camofox-browser # Or use npx (no install needed) npx camofox-browser open https://example.com

Quick Start

bash
camofox open https://example.com # Open a page in anti-detection browser camofox snapshot # Get accessibility tree with element refs camofox click e5 # Click element [e5] camofox type e3 "hello world" # Type into element [e3] camofox screenshot --output page.png # Save screenshot camofox close # Close the tab

Core Commands

bash
# Browser lifecycle camofox open <url> # Open URL in new tab camofox close [tabId] # Close tab camofox navigate <url> # Navigate current tab to URL # Inspection camofox snapshot # Get accessibility tree with [eN] refs camofox screenshot [--output file] # Take screenshot (saves to file) camofox annotate # Screenshot + element ref overlay camofox get-url # Get current page URL camofox get-text # Get page text content camofox get-links # Get all links on page camofox get-tabs # List open tabs camofox extract-structured @schema.json # Extract deterministic JSON from a schema # Interaction camofox click <ref> # Click element by ref camofox type <ref> <text> # Type text into element camofox fill '[e1]="user" [e2]="pw"' # Fill multiple fields at once camofox scroll <direction> # Scroll up/down/left/right camofox select <ref> <value> # Select dropdown option camofox hover <ref> # Hover over element camofox press <key> # Press keyboard key camofox drag <from> <to> # Drag element to target # Navigation camofox go-back # Browser back camofox go-forward # Browser forward camofox search "query" --engine google # Search (14 engines supported) camofox eval "document.title" # Execute JavaScript camofox wait <selector> [--timeout ms] # Wait for element

Text input: CamoFox has no character limit for typed or filled text. Short text stays humanized for anti-detection, while long text automatically switches to bulk DOM insertion so large inputs do not truncate.

Session Management

bash
camofox session save <name> # Save current browser state camofox session load <name> # Restore browser state camofox session list # List saved sessions camofox session delete <name> # Delete saved session
bash
camofox cookie export <file> # Export cookies to JSON file camofox cookie import <file> # Import cookies from JSON file

Auth Vault

Securely store credentials locally with AES-256-GCM encryption. Credentials are never output to stdout — safe for LLM agent automation.

bash
camofox auth save <profile> [--url URL] # Save credentials (prompts for master password) camofox auth load <profile> # Show profile info (username only) camofox auth list # List saved profiles (no secrets shown) camofox auth delete <profile> # Delete a profile camofox auth change-password <profile> # Change master password # Inject credentials into a browser tab (LLM-safe) camofox snapshot # Get element refs first camofox auth load gmail --inject --username-ref e5 --password-ref e12

Security: Master passwords use Argon2id KDF (with PBKDF2 fallback). Vault files are stored with 0600 permissions. The --inject flag sends credentials directly to the browser — the LLM agent never sees the password.

Pipeline Scripting

Execute multiple commands from a file for automation workflows:

bash
# Create a script cat > login-flow.txt << 'EOF' # Login automation script open https://example.com/login snapshot type e3 "username" type e5 "password" click e7 wait .dashboard --timeout 5000 screenshot --output result.png close EOF # Run it camofox run login-flow.txt # Continue on errors camofox run login-flow.txt --continue-on-error # Read from stdin echo "get-url" | camofox run -

Server Management

bash
camofox server start # Start server daemon camofox server start --background # Start in background camofox server stop # Stop server daemon camofox server status # Check server status

Diagnostics

bash
camofox health # System health report camofox version # CLI + server version camofox info # Configuration info

Console Capture

bash
camofox console [tabId] # View console messages camofox console [tabId] --type error # Filter by type (log/warning/error/info/debug) camofox console [tabId] --clear # View then clear messages camofox errors [tabId] # View uncaught JavaScript errors camofox errors [tabId] --clear # View then clear errors

Playwright Tracing

bash
camofox trace start [tabId] # Start recording trace camofox trace stop [tabId] [-o file.zip] # Stop and save trace ZIP camofox trace chunk-start [tabId] # Start new trace chunk camofox trace chunk-stop [tabId] [-o f] # Stop chunk and save ZIP camofox trace status [tabId] # Check active trace status

View traces at trace.playwright.dev

Global Options

FlagEnv VarDescriptionDefault
--user <id>CAMOFOX_USERUser/profile IDcli-default
--port <port>PORTServer port9377
--format <fmt>Output: json, text, plaintext
-V, --versionShow version
-h, --helpShow help

Output Formats

bash
camofox get-url --format json # {"url":"https://example.com"} camofox get-url --format text # URL: https://example.com camofox get-url --format plain # https://example.com

Tip: Use --format json for programmatic parsing and LLM agent integration.

Security

Anti-Detection

CamoFox uses Camoufox, a Firefox fork with C++ level fingerprint spoofing. Unlike Chromium-based tools, CamoFox passes bot detection on Google, Cloudflare, and other anti-bot services.

Auth Vault

  • AES-256-GCM encryption with Argon2id key derivation (PBKDF2 fallback)
  • Credentials never appear in stdout (safe for LLM agent pipelines)
  • Vault files stored with 0600 permissions
  • Master password required for all vault operations

LLM Agent Safety

  • The --inject flag sends credentials directly to the browser — the LLM agent orchestrating the CLI never sees raw passwords
  • Output formats are designed for safe parsing without credential exposure
  • Pipeline scripts can reference auth profiles without embedding secrets

Usage with AI Agents

CamoFox works seamlessly with AI coding agents and LLM-powered automation:

Add CamoFox skills to your AI coding assistant for full browser automation context:

bash
npx skills add redf0x1/camofox-browser

This works with Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, Goose, OpenCode, Windsurf, and 40+ other agents.

Available skills:

SkillFocusBest For
camofox-browserFull coverage (CLI + API + OpenClaw)Complete reference
camofox-cliCLI-only (50+ commands)Terminal-first workflows
dogfoodQA testing workflowSystematic web app testing
gemini-imageGemini image generationAI image automation
redditReddit automationReddit posting/commenting

The installer will prompt you to choose which skills and which agents to configure.

Claude Code

bash
npx skills add redf0x1/camofox-browser # Installs to .claude/skills/camofox-browser/SKILL.md

Cursor / GitHub Copilot / Codex

bash
npx skills add redf0x1/camofox-browser # Installs to .agents/skills/ directory

Tip: Skills are symlinked from the repo, so they stay up to date. Do not manually copy SKILL.md files.

Use CamoFox MCP for direct integration with Claude, Cursor, Windsurf, and other MCP-compatible agents. See Used With.

CLI Integration

AI agents can use the CLI with --format json for structured output:

bash
camofox open https://example.com # Open page camofox snapshot --format json # Get structured element tree camofox click e5 # Interact with elements camofox auth load gmail --inject --username-ref e5 --password-ref e12 # Safe credential injection

Pipeline Automation

Create reusable automation scripts that AI agents can execute:

bash
camofox run automation-flow.txt # Execute multi-step workflow

Architecture

text
AI Agent (MCP / OpenClaw / REST Client) ▼ HTTP REST API (port 9377) ┌──────────────────────────────────────────┐ │ CamoFox Browser Server │ │ (Express + TypeScript) │ ├──────────────────────────────────────────┤ │ Routes Services │ │ ├── Core API ├── Browser │ │ └── OpenClaw compat ├── Session │ │ └── Tab ops │ ├──────────────────────────────────────────┤ │ Camoufox Engine (anti-detect) │ │ Firefox fork + engine-level spoofing │ └──────────────────────────────────────────┘

Persistent Profiles (v1.3.0)

  • Each userId runs in its own persistent Firefox process/context (backed by launchPersistentContext(userDataDir))
  • Profile data is stored at ~/.camofox/profiles/{userId}/ (override via CAMOFOX_PROFILES_DIR)
  • Idle user contexts are closed via LRU eviction (profile data remains on disk)

API Reference

Base URL: http://localhost:9377

Security defaults: CAMOFOX_HOST now defaults to 127.0.0.1, and CAMOFOX_AUTH_MODE=auto keeps local loopback usage open while requiring CAMOFOX_API_KEY when you bind beyond loopback (for example 0.0.0.0 in Docker or PaaS). Set CAMOFOX_AUTH_MODE=required to require API-key auth everywhere. Set CAMOFOX_AUTH_MODE=disabled only for trusted private agent networks whose clients cannot send bearer tokens; this disables API-key auth for protected endpoints and keeps private-network navigation blocked. On non-loopback binds, navigation targets on loopback/private/link-local/metadata hosts are blocked by default unless you explicitly set CAMOFOX_ALLOW_PRIVATE_NETWORK=true. If you also configure PROXY_HOST/PROXY_PORT, exposed deployments must opt into CAMOFOX_ALLOW_PRIVATE_NETWORK=true until proxy-side private-target validation exists.

API Documentation

The Camofox Browser API includes OpenAPI 3.1.0 docs for a representative subset of the shipped route surface:

The OpenAPI spec covers a representative subset of core and OpenClaw endpoints, including request schemas, response shapes, authentication requirements, and validation rules.

Core Endpoints

Note: For any endpoint that targets an existing tab (/tabs/:tabId/...), the server resolves tabId within a userId scope. If you omit userId, you will typically get 404 Tab not found.

MethodEndpointDescriptionRequiredAuth
POST/sessions/:userId/cookiesImport cookies into a user session (Playwright cookie objects)Path: userId; Body: { "cookies": Cookie[] }Conditional: Authorization: Bearer $CAMOFOX_API_KEY
GET/healthHealth check (also pre-launches the browser)NoneNone
GET/presetsList available geo presets (built-in + custom)NoneNone
POST/tabsCreate a new tab (supports preset + per-field overrides)Body: userId + (sessionKey or listItemId)Conditional: Authorization: Bearer $CAMOFOX_API_KEY
GET/tabs?userId=...List all tabs for a user (OpenClaw-compatible response shape)Query: userIdNone
POST/tabs/:tabId/navigateNavigate to a URL, or expand a search macro + queryBody: userId + (url or macro)Conditional: Authorization: Bearer $CAMOFOX_API_KEY
GET/tabs/:tabId/snapshot?userId=...Accessibility snapshot annotated with eN element refsQuery: userIdNone
POST/tabs/:tabId/waitWait for page readiness (DOM + optional network idle)Body: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
POST/tabs/:tabId/clickClick by ref (e.g. e12) or CSS selectorBody: userId + (ref or selector)Conditional: Authorization: Bearer $CAMOFOX_API_KEY
POST/tabs/:tabId/typeType into an element by ref or CSS selectorBody: userId + (ref or selector) + textConditional: Authorization: Bearer $CAMOFOX_API_KEY
POST/tabs/:tabId/pressPress a key (e.g. Enter, Escape)Body: userId + keyConditional: Authorization: Bearer $CAMOFOX_API_KEY
POST/tabs/:tabId/scrollScroll up/down/left/right by pixelsBody: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
POST/tabs/:tabId/scroll-elementScroll specific element into viewBody: userId, ref/selectorConditional: Authorization: Bearer $CAMOFOX_API_KEY
POST/tabs/:tabId/backGo backBody: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
POST/tabs/:tabId/forwardGo forwardBody: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
POST/tabs/:tabId/refreshRefreshBody: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
GET/tabs/:tabId/links?userId=...&limit=50&offset=0Extract links (paginated)Query: userIdNone
GET/tabs/:tabId/images?userId=...List extracted imagesQuery: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
GET/tabs/:tabId/screenshot?userId=...&fullPage=trueScreenshot (PNG bytes)Query: userIdNone
GET/tabs/:tabId/stats?userId=...Tab stats + visited URLsQuery: userIdNone
DELETE/tabs/:tabIdClose a tab (expects JSON body: { "userId": "..." })Body: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
DELETE/tabs/group/:listItemIdClose a tab group (expects JSON body: { "userId": "..." })Body: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
DELETE/sessions/:userIdClose all sessions for a userPath: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
POST/sessions/:userId/toggle-displayToggle display mode (headless/headed/virtual)Path: userId; Body: { "headless": true|false|"virtual" }Conditional: Authorization: Bearer $CAMOFOX_API_KEY
GET/tabs/:tabId/cookiesExport tab cookiesQuery: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
GET/tabs/:tabId/downloadsList tab downloadsQuery: userIdNone
GET/users/:userId/downloadsList user downloadsPath: userIdNone
GET/downloads/:downloadIdDownload metadataQuery: userIdNone
GET/downloads/:downloadId/contentStream download contentQuery: userIdNone
DELETE/downloads/:downloadIdDelete tracked downloadBody or Query: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
POST/tabs/:tabId/extract-resourcesExtract downloadable resourcesBody: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
POST/tabs/:tabId/batch-downloadBatch download resourcesBody: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
POST/tabs/:tabId/resolve-blobsResolve blob URLs to base64Body: userId + urls[]None
POST/tabs/:tabId/trace/startStart trace recordingBody: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
POST/tabs/:tabId/trace/stopStop and save trace ZIPBody: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
POST/tabs/:tabId/trace/chunk/startStart trace chunkBody: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
POST/tabs/:tabId/trace/chunk/stopStop chunk and save ZIPBody: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
GET/tabs/:tabId/trace/statusCheck trace statusQuery: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
GET/sessions/:userId/tracesList managed trace ZIPs for a userPath: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
GET/sessions/:userId/traces/:filenameDownload a managed trace ZIPPath: userId, filenameConditional: Authorization: Bearer $CAMOFOX_API_KEY
DELETE/sessions/:userId/traces/:filenameDelete a managed trace ZIPPath: userId, filenameConditional: Authorization: Bearer $CAMOFOX_API_KEY
GET/tabs/:tabId/consoleGet console messagesQuery: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
GET/tabs/:tabId/errorsGet uncaught JS errorsQuery: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
POST/tabs/:tabId/console/clearClear console + errorsBody or Query: userIdConditional: Authorization: Bearer $CAMOFOX_API_KEY
POST/tabs/:tabId/extract-structuredExtract deterministic JSON from a structured schemaBody: userId + schemaConditional: Authorization: Bearer $CAMOFOX_API_KEY

Toggle Display Mode

bash
POST /sessions/:userId/toggle-display {"headless": "virtual"}

Auth: Conditional — requires Authorization: Bearer $CAMOFOX_API_KEY when CAMOFOX_AUTH_MODE=required or when auto mode has an API key configured. No auth is required in CAMOFOX_AUTH_MODE=disabled.
Switch browser between headless and headed mode. When encountering CAPTCHAs or issues requiring visual interaction, switch to headed mode to show the browser window.

Returns:

json
{"ok": true, "headless": "virtual", "vncUrl": "http://localhost:6080/vnc.html?autoconnect=true&resize=scale&token=...", "message": "Browser visible via VNC", "userId": "agent1"}

Note: This restarts the browser context. All tabs are invalidated but cookies/auth state persist via the persistent profile.

Browser Viewer (noVNC)

When the display mode is set to "virtual" or false, the server automatically starts a VNC viewer accessible via web browser.

bash
# 1. Switch to virtual mode POST /sessions/:userId/toggle-display {"headless": "virtual"} # Response includes vncUrl — open in browser to see Firefox # 2. Solve CAPTCHA or interact with the browser # 3. Switch back to headless POST /sessions/:userId/toggle-display {"headless": true} # VNC automatically stops

The VNC session auto-terminates after 2 minutes (configurable via CAMOFOX_VNC_TIMEOUT_MS).

Evaluate JavaScript

Execute a JavaScript expression in the page context and return the JSON-serializable result.

Auth: required when CAMOFOX_AUTH_MODE=required or when auto mode has an API key configured; no auth is required in CAMOFOX_AUTH_MODE=disabled.

Note: async expressions must be wrapped in an async IIFE (for example, (async () => { ... })()). Top-level await is not supported.

bash
POST /tabs/:tabId/evaluate {"userId": "agent1", "expression": "document.title"}

Returns: {"ok": true, "result": "Page Title", "resultType": "string", "truncated": false}

Evaluate JavaScript (Extended)

Execute a long-running JavaScript expression (up to 300s timeout). Conditionally API-key protected. Rate limited.

Auth: required when CAMOFOX_AUTH_MODE=required or when auto mode has an API key configured; no auth is required in CAMOFOX_AUTH_MODE=disabled.

Note: async expressions must be wrapped in an async IIFE (for example, (async () => { ... })()). Top-level await is not supported.

bash
POST /tabs/:tabId/evaluate-extended {"userId": "agent1", "expression": "(async () => { const response = await fetch('/api/data'); return await response.json(); })()", "timeout": 60000}

Returns: {"ok": true, "result": {...}, "resultType": "object", "truncated": false}

OpenClaw Endpoints

OpenClaw-compatible aliases (used by the OpenClaw plugin).

MethodEndpointDescriptionRequiredAuth
GET/Status (alias of /health)NoneNone
POST/tabs/openOpen tab (OpenClaw request/response shape)Body: userId + urlConditional: Authorization: Bearer $CAMOFOX_API_KEY
POST/startStart browser engineNoneNone
POST/stopStop browser engineNonex-admin-key: $CAMOFOX_ADMIN_KEY
POST/navigateNavigate (OpenClaw request shape: targetId in body)Body: userId + targetId + urlConditional: Authorization: Bearer $CAMOFOX_API_KEY
GET/snapshot?userId=...&targetId=...Snapshot (OpenClaw response shape)Query: userId + targetIdNone
POST/actCombined actions (click, type, press, scroll, scrollIntoView, hover, wait, close, extractStructured)Body: userId + targetId + kindConditional: Authorization: Bearer $CAMOFOX_API_KEY

Structured Extract

Structured extract returns deterministic JSON from a DOM schema without arbitrary JavaScript. Use it when you want stable data contracts instead of ad-hoc evaluate() calls.

Core API:

bash
curl -X POST "$CAMOFOX_URL/tabs/$TAB_ID/extract-structured" \ -H 'Content-Type: application/json' \ -d '{ "userId": "agent1", "schema": { "kind": "object", "fields": { "title": { "kind": "text", "selector": "h1", "required": true, "trim": true }, "products": { "kind": "list", "selector": ".product", "item": { "kind": "object", "fields": { "name": { "kind": "text", "selector": ".name", "required": true, "trim": true }, "href": { "kind": "url", "selector": "a.product-link", "attr": "href", "required": true } } } } } } }'

CLI:

bash
camofox extract-structured @schema.json <tabId> --user <userId> --format json

OpenClaw:

bash
curl -X POST "$CAMOFOX_URL/act" \ -H 'Content-Type: application/json' \ -d '{ "kind": "extractStructured", "targetId": "tab-123", "userId": "agent1", "schema": { "kind": "object", "fields": { "title": { "kind": "text", "selector": "h1", "required": true } } } }'

Notes:

  • invalid schemas fail with HTTP 400
  • required runtime misses fail the whole request with HTTP 422 and fieldPath
  • optional scalar/object/list nodes normalize to null / null / []
  • selectors must be CSS; no XPath, arbitrary JavaScript, or AI extraction
  • raw resource extraction and structured extraction stay separate on purpose

Search Macros

Use macros via POST /tabs/:tabId/navigate with { "macro": "@google_search", "query": "..." }.

MacroEngine
@google_searchGoogle
@youtube_searchYouTube
@amazon_searchAmazon
@reddit_searchReddit (JSON)
@reddit_subredditReddit subreddit (JSON)
@wikipedia_searchWikipedia
@twitter_searchTwitter/X
@yelp_searchYelp
@spotify_searchSpotify
@netflix_searchNetflix
@linkedin_searchLinkedIn
@instagram_searchInstagram tags
@tiktok_searchTikTok
@twitch_searchTwitch

Geo Presets

Built-in presets (also exposed via GET /presets):

PresetLocaleTimezoneLocation
us-easten-USAmerica/New_YorkNew York (40.7128, -74.0060)
us-westen-USAmerica/Los_AngelesLos Angeles (34.0522, -118.2437)
japanja-JPAsia/TokyoTokyo (35.6895, 139.6917)
uken-GBEurope/LondonLondon (51.5074, -0.1278)
germanyde-DEEurope/BerlinBerlin (52.5200, 13.4050)
vietnamvi-VNAsia/Ho_Chi_MinhHo Chi Minh City (10.8231, 106.6297)
singaporeen-SGAsia/SingaporeSingapore (1.3521, 103.8198)
australiaen-AUAustralia/SydneySydney (-33.8688, 151.2093)

Create a tab with a preset:

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

Custom presets: set CAMOFOX_PRESETS_FILE=/path/to/presets.json (JSON object; keys become preset names).

Session-Level Proxy and Geo Overrides

CamoFox supports session-level proxy and geolocation configuration with a hybrid model that combines server defaults with per-session overrides.

Proxy Configuration Model

Server-level baseline (via environment variables):

  • PROXY_HOST, PROXY_PORT, PROXY_USERNAME, PROXY_PASSWORD — applied as the default for all sessions
  • Enables Camoufox geoip mode when configured

Session-level overrides (via POST /tabs or CLI):

  • proxyProfile — select a named proxy profile from CAMOFOX_PROXY_PROFILES_FILE
  • proxy — provide raw proxy fields (host, port, username, password) directly
  • Session-level proxy overrides the server baseline for that specific userId + sessionKey combination

Session identity rules:

  • The same userId may run different sessionKey profiles in parallel with different proxy/geo configurations
  • The same userId + sessionKey combination maintains a stable proxy/geo identity — requests with conflicting proxy/geo fields are rejected
  • Session reuse and cleanup scope proxy/geo identity by userId + sessionKey, not just userId

Geo Mode Behavior

CamoFox offers two geo modes that control how explicit geo fields (locale, timezone, geolocation) interact with proxy-derived geo:

geoMode=explicit-wins (default):

  • Explicit geo fields (locale, timezone, geolocation) remain authoritative
  • Proxy-derived geo suggestions are ignored
  • Use this mode when you want precise geo control regardless of proxy location

geoMode=proxy-locked:

  • Explicit geo fields that conflict with proxy-derived geo are rejected
  • Proxy-derived geo is authoritative
  • Use this mode to ensure geo consistency with proxy exit location

CLI Examples

Session-level proxy with named profile:

bash
camofox open https://example.com --proxy-profile tokyo-exit --user agent1

Session-level proxy with raw fields:

bash
camofox open https://example.com \ --proxy-host proxy.example.com \ --proxy-port 8080 \ --proxy-username user \ --proxy-password pass \ --user agent1

Combine proxy with geo mode:

bash
camofox open https://example.com \ --proxy-profile london-exit \ --geo uk \ --geo-mode proxy-locked \ --user agent1

API Examples

Using a named proxy profile with explicit geo:

bash
curl -X POST http://localhost:9377/tabs \ -H 'Content-Type: application/json' \ -d '{ "userId": "agent1", "sessionKey": "task1", "url": "https://example.com", "proxyProfile": "tokyo-exit", "preset": "japan", "geoMode": "explicit-wins" }'

Using raw proxy fields with proxy-locked geo:

bash
curl -X POST http://localhost:9377/tabs \ -H 'Content-Type: application/json' \ -d '{ "userId": "agent1", "sessionKey": "task2", "url": "https://example.com", "proxy": { "host": "proxy.example.com", "port": 8080, "username": "user", "password": "pass" }, "geoMode": "proxy-locked" }'

Named Proxy Profiles

Define proxy profiles in a JSON file and point CAMOFOX_PROXY_PROFILES_FILE to it:

json
{ "tokyo-exit": { "server": "http://tokyo.proxy.example.com:8080", "username": "user", "password": "pass" }, "london-exit": { "server": "http://london.proxy.example.com:8080" } }

Then use profiles by name in API requests or CLI commands.

Environment Variables

VariableDefaultDescription
CAMOFOX_PORT9377Server port
PORT(optional)Alternative port env var (common in PaaS)
NODE_ENVdevelopmentNode environment
CAMOFOX_HOST127.0.0.1Server bind host. Set 0.0.0.0 for Docker/PaaS/network exposure. Non-loopback binds require CAMOFOX_API_KEY unless CAMOFOX_AUTH_MODE=disabled.
CAMOFOX_ADMIN_KEY(empty)Required for POST /stop (sent via x-admin-key)
CAMOFOX_AUTH_MODEautoAPI-key policy: auto allows loopback without auth and requires CAMOFOX_API_KEY for non-loopback binds; required requires CAMOFOX_API_KEY for every bind; disabled disables API-key auth for protected endpoints and is only for trusted private agent networks.
CAMOFOX_API_KEY(empty)Guards protected endpoints (tab creation, navigation, interaction, session management, downloads, image extraction, tracing, console) via Authorization: Bearer header when set. Required in CAMOFOX_AUTH_MODE=required, and required by auto whenever CAMOFOX_HOST exposes the server beyond loopback. Must be unset when CAMOFOX_AUTH_MODE=disabled.
CAMOFOX_ALLOW_PRIVATE_NETWORKtrue on loopback binds, false otherwiseAllows navigation to loopback/private/link-local/metadata targets. Leave unset for the safe default; enable only for trusted deployments that intentionally need internal-network reachability.
CAMOFOX_HEADLESStrueDisplay mode: true (headless), false (headed), virtual (Xvfb)
CAMOFOX_VNC_RESOLUTION1920x1080x24Virtual Xvfb display resolution (WIDTHxHEIGHTxDEPTH)
CAMOFOX_VNC_TIMEOUT_MS120000Max VNC session duration in ms before auto-stop
CAMOFOX_EVAL_EXTENDED_RATE_LIMIT_MAX20Max evaluate-extended requests per user per window
CAMOFOX_EVAL_EXTENDED_RATE_LIMIT_WINDOW_MS60000Rate limit window duration in ms
CAMOFOX_COOKIES_DIR~/.camofox/cookiesDirectory used by the OpenClaw plugin cookie tool
CAMOFOX_PROFILES_DIR~/.camofox/profilesProfile storage directory (persistent per-user Firefox profiles)
CAMOFOX_DOWNLOADS_DIR~/.camofox/downloadsDownload artifact directory
CAMOFOX_DOWNLOAD_TTL_MS86400000Download metadata retention TTL
CAMOFOX_MAX_DOWNLOAD_SIZE_MB100Max single download size
CAMOFOX_MAX_BATCH_CONCURRENCY5Batch download concurrency cap
CAMOFOX_MAX_BLOB_SIZE_MB5Max blob payload size
CAMOFOX_MAX_DOWNLOADS_PER_USER500Per-user download record cap
CAMOFOX_CONSOLE_BUFFER_SIZE1000Per-tab console/error message buffer size (minimum 100)
HANDLER_TIMEOUT_MS30000Handler timeout fallback
MAX_CONCURRENT_PER_USER3Concurrent operations per user
CAMOFOX_VNC_BASE_PORT6080noVNC/websockify base port
CAMOFOX_VNC_HOSTlocalhostnoVNC host in returned URL
CAMOFOX_CLI_USERcli-defaultDefault CLI user id
CAMOFOX_SERVER_PID_FILE(unset)Optional daemon PID file path used by the CLI server manager
CAMOFOX_IDLE_TIMEOUT_MS1800000Stage 1 idle cleanup threshold (ms)
CAMOFOX_IDLE_EXIT_TIMEOUT_MS1800000Stage 2 daemon exit quiet window (ms, defaults to match Stage 1)
CAMOFOX_PRESETS_FILE(unset)Optional JSON file defining/overriding geo presets
CAMOFOX_PROXY_PROFILES_FILE(unset)Optional JSON file defining named proxy profiles for session-level overrides
CAMOFOX_SESSION_TIMEOUT1800000Session idle timeout in ms (min 60000)
CAMOFOX_MAX_SESSIONS50Maximum concurrent sessions
CAMOFOX_MAX_TABS10Maximum tabs per session
PROXY_HOST(empty)Proxy host (server-level default; enables proxy routing)
PROXY_PORT(empty)Proxy port (server-level default)
PROXY_USERNAME(empty)Proxy username (server-level default)
PROXY_PASSWORD(empty)Proxy password (server-level default)
CAMOFOX_MAX_SNAPSHOT_CHARS80000Max characters in snapshot before truncation
CAMOFOX_MAX_SNAPSHOT_NODES2000Max accessibility snapshot nodes before truncation
CAMOFOX_SNAPSHOT_TAIL_CHARS5000Characters preserved at end of truncated snapshot
CAMOFOX_BUILDREFS_TIMEOUT_MS12000Timeout for building element refs
CAMOFOX_TAB_LOCK_TIMEOUT_MS30000Timeout for acquiring tab lock
CAMOFOX_TRACES_DIR~/.camofox/tracesManaged Playwright trace artifact directory
CAMOFOX_TRACE_MAX_DURATION_MS300000Maximum trace recording duration before automatic stop
CAMOFOX_HEALTH_PROBE_INTERVAL_MS60000Health probe check interval
CAMOFOX_FAILURE_THRESHOLD3Consecutive failures before health degradation
CAMOFOX_YT_DLP_TIMEOUT_MS30000Timeout for yt-dlp subtitle extraction
CAMOFOX_YT_BROWSER_TIMEOUT_MS25000Timeout for browser transcript fallback
CAMOFOX_OS(unset)Optional server-wide Camoufox OS override (windows, macos, linux, or comma-separated list for randomization)
CAMOFOX_ALLOW_WEBGL(unset)Optional server-wide WebGL override; malformed values fail startup
CAMOFOX_SCREEN_WIDTH(unset)Optional screen width override; applied only with CAMOFOX_SCREEN_HEIGHT
CAMOFOX_SCREEN_HEIGHT(unset)Optional screen height override; applied only with CAMOFOX_SCREEN_WIDTH
CAMOFOX_HUMANIZE(unset)Optional server-wide humanization override

CAMOFOX_OS and CAMOFOX_SCREEN_* are generation-time controls: they affect only newly generated fingerprints and have no effect while an existing fingerprint.json sidecar is in use. Reset the profile or delete fingerprint.json to force regeneration under the new defaults. CAMOFOX_ALLOW_WEBGL and CAMOFOX_HUMANIZE are launch-time overrides and apply on every browser launch regardless of whether a sidecar is reused.

Idle Lifecycle Policy

CamoFox implements a two-stage idle lifecycle for graceful cleanup and daemon exit:

Stage 1 — Idle Cleanup

  • After CAMOFOX_IDLE_TIMEOUT_MS of idle time (default: 30 minutes), the server runs cleanup to close idle sessions and tabs
  • Cleanup is delayed if browser contexts are launching or sessions are being created
  • New interactive activity (tab creation, navigation, interaction) cancels any pending cleanup

Stage 2 — Daemon Exit

  • After Stage 1 cleanup completes, the server waits for CAMOFOX_IDLE_EXIT_TIMEOUT_MS (default: matches Stage 1 timeout)
  • If no new activity occurs during this quiet window, the daemon process exits gracefully
  • Any new request activity cancels the pending exit timer

Activity detection:

  • Live tabs, launching browser contexts, or staged session creation count as active work and prevent cleanup
  • Empty sessions (sessions with no tabs) do not block cleanup but do disarm pending daemon exit
  • New interactive activity resets both cleanup and exit timers

This two-stage model ensures cleanup runs before daemon exit, preventing resource leaks while allowing the server to shut down cleanly when fully idle.

Deployment

bash
docker build -t camofox-browser . docker run -p 9377:9377 -p 6080:6080 \ -v ~/.camofox:/home/node/.camofox \ -e CAMOFOX_HOST=0.0.0.0 \ -e CAMOFOX_PORT=9377 \ -e CAMOFOX_AUTH_MODE=auto \ -e CAMOFOX_API_KEY=change-me \ camofox-browser

For private Docker networks used by agents such as Hermes, OpenClaw, or GoClaw that cannot send a bearer token, keep the service off published host ports and disable API-key auth explicitly:

bash
docker network create camofox-agents docker run -d \ --name camofox-browser \ --network camofox-agents \ -e CAMOFOX_HOST=0.0.0.0 \ -e CAMOFOX_AUTH_MODE=disabled \ -v ~/.camofox:/home/node/.camofox \ camofox-browser

Then configure the agent with CAMOFOX_URL=http://camofox-browser:9377 from another container on the same Docker network. Do not combine CAMOFOX_AUTH_MODE=disabled with public port publishing or CAMOFOX_ALLOW_PRIVATE_NETWORK=true.

Fly.io

This repo includes a starter fly.toml for one-command deploys.

bash
fly launch fly deploy

Railway

  • Create a new project → deploy from this GitHub repo
  • Set CAMOFOX_HOST=0.0.0.0
  • Set CAMOFOX_API_KEY to a strong secret
  • Set CAMOFOX_PORT=9377 (Railway will also provide PORT, which is supported)
  • Ensure the service exposes port 9377

Render

  • Create a new Web Service → deploy from this GitHub repo
  • Use Docker (recommended) and expose port 9377
  • Set CAMOFOX_HOST=0.0.0.0
  • Set CAMOFOX_API_KEY to a strong secret
  • Set CAMOFOX_PORT=9377 (or rely on Render PORT)

System Requirements

  • Node.js 20+
  • 2GB+ RAM (browser + contexts require significant memory)
  • Linux recommended for production; macOS is fine for development

Used With

ProjectDescription
CamoFox MCPMCP (Model Context Protocol) server for Claude, Cursor, VS Code
OpenClawOpen-source AI agent framework (compat endpoints included)
CamoufoxAnti-detection Firefox browser engine

Project Structure

text
src/ ├── cli/ │ ├── commands/ # Command modules (core, navigation, interaction, etc.) │ │ ├── console.ts # Console capture commands │ │ └── trace.ts # Playwright tracing commands │ ├── vault/ # Auth vault (encryption, storage) │ ├── server/ # Server lifecycle management │ ├── transport/ # HTTP transport layer │ ├── output/ # Output formatting │ └── utils/ # Shared utilities ├── server.ts # Express app entry point ├── types.ts # Shared TypeScript interfaces ├── routes/ │ ├── core.ts # Core REST API (~42 endpoints) │ └── openclaw.ts # OpenClaw compatibility (~7 endpoints) ├── services/ │ ├── browser.ts # Browser lifecycle + persistent context pool │ ├── batch-downloader.ts # Batch download orchestrator │ ├── context-pool.ts # Browser context pool with LRU eviction │ ├── download.ts # Download tracking service │ ├── health.ts # Browser health tracking │ ├── resource-extractor.ts # Page resource extraction │ ├── session.ts # Session management + limits │ ├── tab.ts # Tab operations (snapshot/click/type/etc.) │ ├── tracing.ts # Playwright tracing service │ ├── vnc.ts # VNC/virtual display lifecycle │ └── youtube.ts # YouTube transcript extraction ├── middleware/ │ ├── auth.ts # API/admin auth helpers │ ├── errors.ts # Error handling │ ├── logging.ts # Structured logging │ └── rate-limit.ts # In-memory rate limiter └── utils/ ├── config.ts # Environment config parsing ├── cookies.ts # Cookie utilities ├── download-helpers.ts # Download helper functions ├── launcher.ts # Browser launcher utilities ├── macros.ts # Search macro expansion ├── presets.ts # Geo preset definitions/loader └── snapshot.ts # Snapshot truncation/windowing

Contributing

See CONTRIBUTING.md

Credits

This project is based on camofox-browser by Jo Inc (YC W24) and the Camoufox anti-detection browser engine by daijro.

License

MIT

Crypto Scam Warning

Sketchy people are doing sketchy things with crypto tokens named "Camofox" now that this project is getting attention. Camofox is not a crypto project and will never be one. Any token, coin, or NFT using the Camofox name has nothing to do with us.

Contributors

Showing top 2 contributors by commit count.

View all contributors on GitHub →

This article is auto-generated from redf0x1/camofox-browser via the GitHub API.Last fetched: 6/22/2026