Doramagic Project Pack · Human Manual
camofox-browser
Related topics: Quick Start Guide, System Architecture
Overview
Related topics: Quick Start Guide, System Architecture
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Quick Start Guide, System Architecture
Overview
Camofox-browser is an anti-detection browser automation server designed for AI agents. It provides a headless browser infrastructure with sophisticated anti-bot evasion capabilities, enabling reliable web scraping and automation tasks against sites with aggressive detection mechanisms.
Purpose and Scope
Camofox-browser serves as a middleware layer between AI agents and web content. It wraps Playwright-based browser automation with specialized fingerprinting countermeasures, session isolation, and a comprehensive REST API for programmatic control.
Key responsibilities include:
- Anti-detection browsing: Stealth browser sessions that mimic real user behavior patterns
- Session management: Isolated browser contexts per user with independent cookies and storage
- Accessibility snapshots: Structured DOM representations with stable element references for reliable interaction
- Plugin extensibility: Customizable middleware for specialized sites or workflows
- Operational monitoring: Built-in health checks, tracing, and crash reporting
Source: lib/openapi.js:22-29
Architecture Overview
Camofox-browser follows a layered architecture with Express.js as the HTTP layer, Playwright as the browser engine, and a plugin system for extensibility.
graph TD
A[Client / AI Agent] -->|REST API| B[Express Server<br/>server.js]
B --> C[Session Manager<br/>sessions Map]
B --> D[Plugin System<br/>lib/plugins.js]
B --> E[OpenAPI Generator<br/>lib/openapi.js]
C --> F[Browser Pool<br/>Playwright]
C --> G[Tab Groups<br/>per session]
F --> H[Browser Contexts<br/>isolated per user]
H --> I[Tabs / Pages<br/>element refs]
D --> B
J[Reporter<br/>lib/reporter.js] --> K[GitHub Issues<br/>crash reports]Core Components
| Component | File | Purpose |
|---|---|---|
| HTTP Server | server.js | Express app with route handlers for tabs, sessions, navigation |
| Session Store | server.js | In-memory Map storing browser contexts and tab groups per userId |
| Browser Engine | Playwright | Headless browser with stealth modifications |
| Plugin Host | lib/plugins.js | Event-driven plugin lifecycle and hooks |
| API Spec | lib/openapi.js | Auto-generated OpenAPI 3.0.3 documentation |
| Reporter | lib/reporter.js | Anonymized crash/hang reporting to GitHub Issues |
| Schema Validator | lib/extract.js | JSON schema validation for structured outputs |
Source: server.js:1-50, AGENTS.md:1-20
API Structure
The REST API is organized into resource-based endpoints with OpenAPI 3.0.3 specification generated from JSDoc comments.
Endpoint Categories
| Tag | Description | Example Endpoints |
|---|---|---|
System | Health, status, configuration | GET /health, GET /status |
Tabs | Tab lifecycle management | POST /tabs, DELETE /tabs/:tabId |
Navigation | URL navigation, search macros | POST /tabs/:tabId/navigate |
Interaction | User input actions | POST /tabs/:tabId/click, POST /tabs/:tabId/type |
Content | DOM access | GET /tabs/:tabId/snapshot, GET /tabs/:tabId/screenshot |
Sessions | Session management | GET /sessions/:userId/traces/:filename |
Browser | Browser control | POST /browser/relaunch |
Legacy | Deprecated endpoints | Backward compatibility routes |
Source: AGENTS.md:40-55, lib/openapi.js:22-40
OpenAPI Documentation
The API specification is auto-generated from @openapi JSDoc blocks in server.js using swagger-jsdoc. Generated output is served at:
GET /openapi.json- Machine-readable OpenAPI 3.0.3 JSONGET /docs- Interactive three-panel UI via swagger-stripey
graph LR
A[developer writes<br/>@openapi JSDoc] --> B[swagger-jsdoc<br/>scans server.js]
B --> C[openapi.json<br/>generated spec]
C --> D[/docs endpoint<br/>swagger-stripey UI]
C --> E[API consumers<br/>code generation]To update the spec after route changes:
npm run generate-openapi
Source: AGENTS.md:22-45
Session Model
Sessions provide isolated browser contexts per user, enabling multi-tenant operation on a single server instance.
Session Structure
{
userId: string,
lastAccess: number, // timestamp of last API call
context: BrowserContext, // Playwright browser context
tabGroups: Map<listItemId, TabGroup>,
contextOptions: object // viewport, userAgent, proxy, etc.
}
Tab Group Structure
{
listItemId: string,
context: BrowserContext,
tabs: Map<tabId, {
page: Page,
tabState: {
toolCalls: number,
consecutiveTimeouts: number,
consecutiveFailures: number,
navigateAbort: AbortController | null
}
}>
}
Source: server.js:100-150
Session Lifecycle
| Event | Description |
|---|---|
session:creating | Hook before context creation; plugins can mutate contextOptions |
session:created | Context created and stored |
session:destroying | Context about to close |
session:destroyed | Context closed and cleaned up |
session:expired | Idle timeout triggered by reaper |
Source: lib/plugins.js:15-20
Tab Lifecycle
Tabs are created within session contexts and provide the primary interface for browser automation.
Tab Operations
| Endpoint | Method | Description |
|---|---|---|
/tabs | POST | Create new tab |
/tabs/:tabId | DELETE | Close tab |
/tabs/:tabId/navigate | POST | Navigate to URL with macro support |
/tabs/:tabId/snapshot | GET | Get accessibility tree snapshot |
/tabs/:tabId/screenshot | GET | Capture viewport screenshot |
/tabs/:tabId/click | POST | Click element by ref or selector |
/tabs/:tabId/type | POST | Type text into element |
/tabs/:tabId/scroll | POST | Scroll page or element |
/tabs/:tabId/press | POST | Press keyboard key |
/tabs/:tabId/viewport | POST | Set viewport dimensions |
Source: server.js:200-400
Tab Events
| Event | Payload |
|---|---|
tab:created | { userId, tabId, page, url } |
tab:navigated | { userId, tabId, url, prevUrl } |
tab:destroyed | { userId, tabId, reason } |
tab:recycled | { userId, tabId } |
tab:error | { userId, tabId, error } |
Source: lib/plugins.js:22-24
Plugin System
Camofox-browser supports a plugin architecture for extending functionality. Plugins live in plugins/<name>/index.js and export a register(app, ctx) function.
Plugin Context
{
sessions: Map, // session store
config: object, // CONFIG object
log: function, // structured logger
auth: function, // authMiddleware factory
// core functions for plugin use
}
Available Hooks (29 events across 7 categories)
Browser Lifecycle:
browser:launching,browser:launched,browser:restart,browser:closed,browser:error
Session Lifecycle:
session:creating,session:created,session:destroying,session:destroyed,session:expired
Tab Lifecycle:
tab:created,tab:navigated,tab:destroyed,tab:recycled,tab:error
Content:
tab:snapshot,tab:screenshot,tab:evaluate,tab:evaluated
Input:
tab:click,tab:type,tab:scroll,tab:press
Downloads:
tab:download:start,tab:download:complete
Cookies/Auth:
session:cookies:import,session:storage:export
Server:
server:starting,server:started,server:shutdown
Source: lib/plugins.js:1-50
Plugin Management CLI
# Install from git or local path
node scripts/plugin.js install <git-url|local-path>
# List installed plugins
node scripts/plugin.js list
# Remove a plugin
node scripts/plugin.js remove <name>
Source: scripts/plugin.js:1-50
Schema Validation
The lib/extract.js module provides schema validation for structured output extraction.
Supported Types
| Type | Handler |
|---|---|
string | String(raw).trim() |
number | parseFloat() with sanitization |
integer | parseInt() with sanitization |
boolean | Boolean coercion |
object | Object passthrough |
null | Null passthrough |
Source: lib/extract.js:1-30
Validation Rules
- Top-level schema must have
type: object - Must have a
propertiesobject - Property definitions must be objects
- Property types must be in the supported set
Snapshot System
Page snapshots provide structured accessibility trees for reliable element identification.
Snapshot Configuration
| Parameter | Default | Description |
|---|---|---|
MAX_SNAPSHOT_CHARS | 150,000 | Maximum total characters |
SNAPSHOT_TAIL_CHARS | 5,000 | Characters preserved at end |
offset | 0 | Pagination offset |
maxBytes | Configurable | Inline data size limit |
Source: lib/snapshot.js:1-30
Snapshot Response
{
"text": "chunk + marker + tail",
"truncated": true,
"totalChars": 150000,
"offset": 0,
"hasMore": true,
"nextOffset": 150000
}
Health Monitoring
The /health endpoint provides server and browser state visibility.
Health Response
{
"ok": true,
"engine": "camoufox",
"browserConnected": true,
"browserRunning": true,
"activeTabs": 5,
"activeSessions": 3,
"consecutiveFailures": 0,
"memory": {
"rssMb": 150,
"heapUsedMb": 85,
"nativeMemMb": 65
}
}
When recovering from error, returns HTTP 503 with { ok: false, recovering: true }.
Source: server.js:500-520
Crash and Hang Reporting
The lib/reporter.js module provides anonymized issue reporting to GitHub Issues via the camofox-crash-reporter GitHub App.
Reported Domains
The reporter excludes sensitive domains from telemetry but includes sites with known anti-bot measures:
- Social: twitter.com, facebook.com, instagram.com, linkedin.com
- Commerce: amazon.com, ebay.com, etsy.com, walmart.com
- Crypto: coinbase.com, binance.com, opensea.io
- Finance: tradingview.com, robinhood.com, coinbase.com
- Prediction Markets: polymarket.com, kalshi.com, metaculus.com
Source: lib/reporter.js:1-50
Event Loop Monitoring
The crash reporter monitors for Node.js event loop stalls exceeding a 5-second threshold. Community reports indicate these stalls occur across versions 1.6.0-1.7.3 on both macOS (darwin) and Linux platforms, with durations ranging from 6s to 74s.
Known affected versions: 1.6.0, 1.7.2, 1.7.3 Known affected Node versions: v22.22.2, v24.15.0, v25.8.1, v25.8.2
Configuration
Camofox-browser uses environment variables for configuration:
| Variable | Default | Description |
|---|---|---|
PORT | 9377 | Server port |
ENABLE_VNC | 0 | Enable VNC server |
VNC_BIND | 127.0.0.1 | VNC bind address |
LOG_LEVEL | info | Logging verbosity |
Installation and Usage
CLI Binary (npm)
npx @askjo/camofox-browser
Or install globally:
npm install -g @askjo/camofox-browser
camofox-browser
Docker
docker run --rm -it -p 9377:9377 -p 6080:6080 \
-e ENABLE_VNC=1 -e VNC_BIND=0.0.0.0 \
ghcr.io/jo-inc/camofox-browser:latest
Note: VNC environment variable activation regressed in v1.11 (Issue #4314). Use v1.10.0 or check explicit configuration in v1.11+.
Known Issues and Community Concerns
| Issue | Status | Description |
|---|---|---|
| Event loop stalls | Ongoing | Stalls 6-74s on long-running instances |
| VNC regression in 1.11 | Known | VNC doesn't activate from environment variables |
| WSL2 screen flash | Reported | Periodic screen flash every 3 minutes in WSL2 |
| Plugin update failures | Reported | ERR_MODULE_NOT_FOUND during OC plugin updates |
Community feedback also requests automated Docker builds as part of releases (Issue #525) and Cloudflare Turnstile challenge support (Issue #40).
Version History
| Version | Release Type | Notable Changes |
|---|---|---|
| 1.11.2 | Latest | CLI binary available via npm |
| 1.11 | Stable | OpenAPI generation, plugin system improvements |
| 1.10.0 | Legacy | VNC environment variable activation |
| 1.7.3 | Stable | Event loop monitoring improvements |
| 1.6.0 | Legacy | Initial crash reporter integration |
Source: https://github.com/jo-inc/camofox-browser / Human Manual
Quick Start Guide
Related topics: Overview, Deployment Guide
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Overview, Deployment Guide
Quick Start Guide
Camofox-browser is an anti-detection browser automation server designed for AI agents. It provides accessibility snapshots, element refs, session isolation, cookie import, proxy rotation, and structured logs through a REST API.
Prerequisites
System Requirements
| Requirement | Minimum | Recommended |
|---|---|---|
| Node.js | v22.0.0 | v22.x or v24.x LTS |
| Memory | 512 MB | 2 GB+ |
| Disk Space | 200 MB | 500 MB |
| OS | Linux, macOS, Windows | Linux (Docker) |
Required Dependencies
- Playwright-compatible browser: Camofox uses Camoufox under the hood
- Python 3.8+ (for Camoufox browser installation)
- npm or yarn for package management
Installation
Option 1: npm (Recommended for CLI Usage)
# Install globally
npm install -g @askjo/camofox-browser
# Run directly
camofox-browser
Option 2: From Source
# Clone the repository
git clone https://github.com/jo-inc/camofox-browser.git
cd camofox-browser
# Install dependencies
npm install
# Build TypeScript (if present)
npm run build
# Start the server
npm start
Option 3: Docker
# Using the official image
docker run --rm -it -p 9377:9377 \
ghcr.io/jo-inc/camofox-browser:latest
# With VNC enabled for debugging
docker run --rm -it -p 9377:9377 -p 6080:6080 \
-e ENABLE_VNC=1 -e VNC_BIND=0.0.0.0 \
ghcr.io/jo-inc/camofox-browser:latest
Note: Community reports indicate that VNC activation via environment variables had a regression in v1.11. Ensure you are using v1.11.2 or later if you encounter VNC activation issues. Source: #4314
Configuration
The server uses environment variables for configuration. Create a .env file or set variables directly:
Core Configuration
| Environment Variable | Default | Description |
|---|---|---|
PORT | 9377 | Server port |
HOST | 0.0.0.0 | Server host |
CAMOFOX_API_KEY | - | API key for authentication |
ADMIN_KEY | - | Admin authentication key |
LOG_LEVEL | info | Logging level (debug, info, warn, error) |
Browser Configuration
| Environment Variable | Default | Description |
|---|---|---|
PROXY | - | Proxy URL (e.g., http://user:pass@host:port) |
HEADLESS | true | Run browser in headless mode |
DISPLAY | :99 | X11 display for Linux |
Storage Configuration
| Environment Variable | Default | Description |
|---|---|---|
COOKIES_DIR | ./cookies | Cookie storage directory |
TRACES_DIR | ./traces | Trace files directory |
DOWNLOADS_DIR | ./downloads | Download storage directory |
Starting the Server
Basic Start
node server.js
With Custom Configuration
PORT=8080 HOST=127.0.0.1 node server.js
Using the Startup Script
./run.sh
The server will start on http://localhost:9377 by default.
API Overview
Camofox exposes a REST API for browser automation. The API documentation is available at /docs when the server is running.
Base URL
http://localhost:9377
Authentication
Protected endpoints require either:
X-API-KeyheaderuserIdin request body/query
Key Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET | /health | Server health check |
POST | /sessions | Create new session |
GET | /sessions/:userId | Get session info |
DELETE | /sessions/:userId | Destroy session |
POST | /tabs/:tabId/navigate | Navigate to URL |
POST | /tabs/:tabId/click | Click element |
POST | /tabs/:tabId/type | Type text |
GET | /tabs/:tabId/snapshot | Get page snapshot |
POST | /tabs/:tabId/screenshot | Take screenshot |
Core Workflow
graph TD
A[Start Server] --> B[Create Session]
B --> C[Create Tab]
C --> D[Navigate to URL]
D --> E[Get Snapshot]
E --> F{Action Required?}
F -->|Yes| G[Click/Type/Scroll]
G --> E
F -->|No| H[Close Tab]
H --> I{More Tabs?}
I -->|Yes| C
I -->|No| J[Destroy Session]Usage Examples
1. Create a Session
curl -X POST http://localhost:9377/sessions \
-H "Content-Type: application/json" \
-d '{"userId": "my-user-123"}'
Response:
{
"ok": true,
"userId": "my-user-123",
"tabs": []
}
2. Navigate to a Website
curl -X POST http://localhost:9377/tabs/<tabId>/navigate \
-H "Content-Type: application/json" \
-d '{
"userId": "my-user-123",
"url": "https://example.com"
}'
3. Get Page Snapshot
curl "http://localhost:9377/tabs/<tabId>/snapshot?userId=my-user-123"
The snapshot returns an accessibility tree with element refs for interaction.
4. Click an Element
curl -X POST http://localhost:9377/tabs/<tabId>/click \
-H "Content-Type: application/json" \
-d '{
"userId": "my-user-123",
"ref": "element-ref-here"
}'
5. Type Text
curl -X POST http://localhost:9377/tabs/<tabId>/type \
-H "Content-Type: application/json" \
-d '{
"userId": "my-user-123",
"ref": "element-ref-here",
"text": "Hello World",
"submit": true
}'
6. Take Screenshot
curl "http://localhost:9377/tabs/<tabId>/screenshot?userId=my-user-123" \
-o screenshot.png
Plugin System
Camofox supports plugins for extending functionality. Plugins live in plugins/<name>/index.js and export a register(app, ctx) function.
Available Plugin Commands
# Install from git
node scripts/plugin.js install https://github.com/user/repo
# Install from local path
node scripts/plugin.js install ./path/to/local/plugin
# List installed plugins
node scripts/plugin.js list
# Remove a plugin
node scripts/plugin.js remove <plugin-name>
Plugin Events
Plugins can hook into 29 events across 7 categories:
| Category | Events |
|---|---|
| Browser Lifecycle | browser:launching, browser:launched, browser:restart, browser:closed, browser:error |
| Session Lifecycle | session:creating, session:created, session:destroying, session:destroyed, session:expired |
| Tab Lifecycle | tab:created, tab:navigated, tab:destroyed, tab:recycled, tab:error |
| Content | tab:snapshot, tab:screenshot, tab:evaluate, tab:evaluated |
| Input | tab:click, tab:type, tab:scroll, tab:press |
| Downloads | tab:download:start, tab:download:complete |
| Server | server:starting, server:started, server:shutdown |
Source: lib/plugins.js:1-60
Health Monitoring
Health Endpoint
curl http://localhost:9377/health
Response:
{
"ok": true,
"engine": "camoufox",
"browserConnected": true,
"browserRunning": true,
"activeTabs": 3,
"activeSessions": 1,
"consecutiveFailures": 0,
"memory": {
"rssMb": 150,
"heapUsedMb": 45,
"nativeMemMb": 105
}
}
Event Loop Monitoring
The server monitors for event loop stalls. If the event loop is blocked for more than 5 seconds, a warning is logged. This is auto-reported by the crash reporter in high-uptime scenarios. Source: Community Context - Stuck Event Loop Issues
Common causes of event loop stalls:
- Blocking synchronous operations in Node.js
- Heavy CPU usage in page evaluation scripts
- Network delays during page loads
OpenAPI Documentation
The API specification is auto-generated from @openapi JSDoc comments in server.js. Access the interactive documentation:
- Swagger UI:
http://localhost:9377/docs - Raw Spec:
http://localhost:9377/openapi.json
When modifying routes, update the @openapi JSDoc block and regenerate the spec:
npm run generate-openapi
Source: AGENTS.md:45-80
Common Issues
Port Already in Use
Error: listen EADDRINUSE :::9377
Solution: Either stop the existing process using port 9377 or start on a different port:
PORT=9378 node server.js
Browser Launch Failure
Ensure Playwright browsers are installed:
npx playwright install
Event Loop Stalls
If you encounter event loop stall warnings:
- Check for heavy JavaScript execution in page context
- Verify network connectivity is stable
- Consider increasing the timeout thresholds in configuration
Next Steps
- Explore the full API Reference at
/docs - Review AGENTS.md for OpenAPI specification guidelines
- Check the plugin system documentation for extending functionality
- Review community issues for known limitations
Source: https://github.com/jo-inc/camofox-browser / Human Manual
System Architecture
Related topics: Overview, Session & Tab Management
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Overview, Session & Tab Management
System Architecture
Overview
Camofox-browser is an anti-detection browser automation server built on Node.js and Express. It provides a REST API for managing browser sessions, tabs, and user interactions with anti-detection capabilities designed to evade bot detection systems.
The architecture follows a layered design with the Express HTTP server at the boundary, session management in the middle tier, and the camoufox browser engine at the core. A plugin system enables extensibility through lifecycle hooks and custom tools.
High-Level Component Diagram
graph TB
subgraph "Client Layer"
AI[AI Agent / Client]
end
subgraph "HTTP Server Layer"
Express[Express Server<br/>Port 9377]
Routes[Route Handlers]
Middleware[Auth Middleware]
OpenAPI[OpenAPI Spec<br/>/openapi.json]
end
subgraph "Core Services Layer"
Sessions[Session Manager]
Tabs[Tab Manager]
Browser[Browser Engine<br/>camoufox]
Plugins[Plugin System]
Health[Health Monitor]
end
subgraph "Browser Layer"
Contexts[Browser Contexts]
Pages[Tabs/Pages]
CDP[Chrome DevTools<br/>Protocol]
end
AI --> Express
Express --> Routes
Routes --> Middleware
Middleware --> Sessions
Sessions --> Tabs
Tabs --> Browser
Browser --> CDP
Sessions --> Plugins
Plugins --> BrowserCore Components
HTTP Server (Express)
The HTTP server is built on Express.js and serves as the API boundary for all client interactions. Source: server.js:1-100
| Property | Value |
|---|---|
| Default Port | 9377 |
| Protocol | HTTP REST |
| API Format | JSON |
| Documentation | OpenAPI 3.0.3 |
| Docs Endpoint | /docs |
| Spec Endpoint | /openapi.json |
Route Organization
Routes are organized by functional domain using OpenAPI tags. Source: AGENTS.md:1-50
| Tag | Purpose | Example Endpoints |
|---|---|---|
System | Health, status | GET /health |
Tabs | Tab CRUD | POST /tabs, DELETE /tabs/:tabId |
Navigation | URL navigation | POST /tabs/:tabId/navigate |
Interaction | User input | POST /tabs/:tabId/click, POST /tabs/:tabId/type |
Content | Page data | GET /tabs/:tabId/snapshot, GET /tabs/:tabId/images |
Sessions | Session management | GET /sessions/:userId |
Browser | Engine control | POST /browser/restart |
Browser Engine
The browser engine is powered by camoufox, an anti-detection browser built on Chromium. Source: server.js()
graph LR
A[Launch Request] --> B[Launch Options]
B --> C{Hook: browser:launching}
C --> D[Launch camoufox]
D --> E{Hook: browser:launched}
E --> F[Active Browser]
F --> G{Error}
G --> H{Hook: browser:error}
H --> I[Recovery]
I --> DSession Management
Session Architecture
Sessions provide user isolation and state management. Each session maintains browser contexts, tab groups, and access timestamps. Source: server.js()
graph TD
User[User Request] --> Auth[Auth Middleware]
Auth --> Lookup[Session Lookup<br/>normalizeUserId]
Lookup --> Found{Session<br/>Exists?}
Found -->|Yes| Update[Update lastAccess]
Found -->|No| Create[Create Session]
Update --> Tabs[Tab Operations]
Create --> Tabs
Tabs --> Context[Browser Context]
Context --> Pages[Pages/Tabs]Session Data Structure
| Field | Type | Description |
|---|---|---|
userId | string | Normalized user identifier |
lastAccess | number | Unix timestamp of last activity |
context | BrowserContext | Isolated browser context |
tabGroups | Map | Tab groups by listItemId |
consecutiveFailures | number | Failure counter for health |
Sessions are stored in an in-memory Map and automatically cleaned up by an idle reaper. Source: server.js()
User ID Normalization
User IDs are normalized to enable consistent session lookup regardless of input format variations. Source: server.js()
// Normalization happens via normalizeUserId() before session lookup
const session = sessions.get(normalizeUserId(userId));
Tab Management
Tab Lifecycle
Tabs go through a defined lifecycle managed by the Tab Manager. Source: server.js()
stateDiagram-v2
[*] --> Created: POST /tabs
Created --> Ready: Page loaded
Ready --> Navigating: navigate()
Navigating --> Ready: Page loaded
Ready --> Interacting: click/type/scroll
Interacting --> Ready: Action complete
Ready --> Error: Page error
Error --> Ready: Retry
Ready --> Closed: DELETE /tabs/:tabId
Closed --> [*]Tab State Tracking
Each tab maintains state for monitoring and metrics. Source: server.js()
| State Field | Purpose |
|---|---|
toolCalls | Count of operations performed |
consecutiveTimeouts | Timeout tracking |
consecutiveFailures | Failure tracking |
navigateAbort | AbortController for navigation |
page | Playwright Page instance |
group | Parent TabGroup reference |
Tab Locking
Concurrent operations on the same tab are serialized using tab locks to prevent race conditions. Source: server.js()
await withTabLock(tabId, async () => {
await tabState.page.keyboard.press(key);
});
Plugin System
Plugin Architecture
The plugin system provides extensibility through 29 lifecycle events across 7 categories. Source: lib/plugins.js:1-80
graph TD
subgraph "Browser Lifecycle"
BL1[browser:launching]
BL2[browser:launched]
BL3[browser:restart]
BL4[browser:closed]
BL5[browser:error]
end
subgraph "Session Lifecycle"
SL1[session:creating]
SL2[session:created]
SL3[session:destroying]
SL4[session:destroyed]
SL5[session:expired]
end
subgraph "Tab Lifecycle"
TL1[tab:created]
TL2[tab:navigated]
TL3[tab:destroyed]
TL4[tab:recycled]
TL5[tab:error]
end
subgraph "Content"
CT1[tab:snapshot]
CT2[tab:screenshot]
CT3[tab:evaluate]
CT4[tab:evaluated]
end
subgraph "Input"
IN1[tab:click]
IN2[tab:type]
IN3[tab:scroll]
IN4[tab:press]
end
subgraph "Downloads"
DL1[tab:download:start]
DL2[tab:download:complete]
end
subgraph "Server"
SV1[server:starting]
SV2[server:started]
SV3[server:shutdown]
endPlugin Event Categories
| Category | Events | Mutating |
|---|---|---|
| Browser Lifecycle | 5 | browser:launching |
| Session Lifecycle | 5 | session:creating |
| Tab Lifecycle | 5 | None |
| Content | 4 | None |
| Input | 4 | None |
| Downloads | 2 | None |
| Server | 3 | None |
Plugin Registration
Plugins register tools and commands through the Plugin API. Source: plugin.ts:1-80
interface PluginApi {
registerTool: (
tool: ToolDefinition | ToolFactory,
options?: { optional?: boolean }
) => void;
registerCommand: (cmd: {
name: string;
description: string;
handler: (args: string[]) => Promise<void>;
}) => void;
registerCli?: (registrar: CliContext) => void;
}
Plugin Management CLI
Plugin lifecycle is managed via the command-line interface. Source: scripts/plugin.js:1-60
| Command | Description |
|---|---|
plugin install <source> | Install from git URL or local path |
plugin remove <name> | Remove a plugin |
plugin list | List installed plugins |
Built-in Tools
The core plugin provides standard browser automation tools. Source: plugin.js:1-100
| Tool | Purpose |
|---|---|
camofox_navigate | Navigate to URL with macro support |
camofox_snapshot | Get accessibility snapshot |
camofox_click | Click element by ref or selector |
camofox_type | Type text into element |
camofox_scroll | Scroll page or element |
camofox_screenshot | Capture page screenshot |
camofox_evaluate | Execute JavaScript in page |
camofox_list_tabs | List open tabs |
camofox_import_cookies | Import Netscape-format cookies |
API Layer
OpenAPI Specification
API documentation is auto-generated from JSDoc @openapi comments using swagger-jsdoc. Source: lib/openapi.js:1-50
graph LR
A[JSDoc Comments] --> B[swagger-jsdoc]
B --> C[openapi.json]
C --> D[swagger-stripey UI<br/>/docs]
C --> E[Client SDKs]Route Documentation Pattern
Every route handler requires a @openapi JSDoc block. Source: AGENTS.md:20-80
/**
* @openapi
* /tabs/{tabId}/click:
* post:
* tags: [Interaction]
* summary: Click an element
* parameters:
* - name: tabId
* in: path
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Click result.
*/
app.post('/tabs/:tabId/click', async (req, res) => {
// handler
});
OpenAPI Definition
The spec follows OpenAPI 3.0.3 with structured metadata. Source: lib/openapi.js:20-40
| Property | Value |
|---|---|
| Version | 3.0.3 |
| Title | camofox-browser |
| License | MIT |
| Contact | [email protected] |
| Default Server | http://localhost:9377 |
Content Extraction
Snapshot System
The snapshot system captures page accessibility trees with pagination support. Source: lib/snapshot.js:1-50
| Constant | Value | Purpose |
|---|---|---|
MAX_SNAPSHOT_CHARS | ~500KB | Maximum snapshot size |
SNAPSHOT_TAIL_CHARS | ~10KB | Tail preserved on truncation |
Snapshot Pagination
Large snapshots are paginated to manage memory and response sizes. Source: lib/snapshot.js:40-60
return {
text: chunk + marker + tail,
truncated: true,
totalChars: total,
offset: clampedOffset,
hasMore,
nextOffset: hasMore ? chunkEnd : null
};
Schema Validation
Structured data extraction uses JSON Schema validation. Source: lib/extract.js:1-30
| Supported Types | Description |
|---|---|
string | Text content |
number | Numeric values |
integer | Whole numbers |
boolean | True/false |
object | Nested structures |
null | Null values |
Error Handling & Health Monitoring
Health Check Endpoint
The /health endpoint reports system and browser status. Source: server.js()
{
"ok": true,
"engine": "camoufox",
"browserConnected": true,
"browserRunning": true,
"activeTabs": 5,
"activeSessions": 2,
"consecutiveFailures": 0,
"memory": {
"rssMb": 42,
"heapUsedMb": 20,
"nativeMemMb": 22
}
}
Health States
| State | HTTP Code | Trigger |
|---|---|---|
| Healthy | 200 | Browser running normally |
| Recovering | 503 | Browser restarting after crash |
| Error | 503 | Unrecoverable failure |
Event Loop Monitoring
The system monitors Node.js event loop health with a 5-second threshold. Community evidence shows this triggers on long-running operations:
Multiple reports of "Event loop stalled for Xs (threshold: 5s)" across versions 1.6.0-1.7.3 on darwin and linux platforms. Source: Community Context Issues #4483, #4493, #4495, #4855-#4863
Deployment Architecture
Docker Deployment
The system supports containerized deployment with VNC capabilities. Source: Community Context: Latest Release
docker run --rm -it -p 9377:9377 -p 6080:6080 \
-e ENABLE_VNC=1 -e VNC_BIND=0.0.0.0 \
ghcr.io/jo-inc/camofox-browser:latest
CLI Binary
The npm package provides a standalone executable. Source: Community Context: Latest Release
npm install -g @askjo/camofox-browser
camofox-browser
Default port (9377) and environment variables remain consistent across deployment methods.
Key Design Patterns
Middleware Chain
Requests pass through a middleware chain before reaching route handlers:
- Request ID injection
- Body parsing
- Authentication (when enabled)
- Route-specific validation
- Handler execution
Lifecycle Hooks
Mutating hooks pass objects by reference, allowing plugins to modify behavior:
browser:launching- Modify launch options before browser startssession:creating- Customize context options per user
Tab Lock Queue
Tab operations are serialized using a queue-based locking mechanism to prevent concurrent modification conflicts.
Configuration
Environment Variables
| Variable | Purpose | Default |
|---|---|---|
PORT | HTTP server port | 9377 |
ENABLE_VNC | Enable VNC server | 0 |
VNC_BIND | VNC bind address | 127.0.0.1 |
PLUGIN_DIR | Plugin directory | ./plugins |
Summary
The camofox-browser architecture separates concerns into distinct layers:
- HTTP Layer: Express server with REST API, OpenAPI documentation
- Session Layer: User isolation, context management, idle reaping
- Tab Layer: Page lifecycle, locking, state tracking
- Plugin Layer: 29 events, tool registration, CLI management
- Browser Layer: camoufox anti-detection engine
This design enables extensibility through plugins while maintaining robust core functionality for browser automation tasks.
Source: https://github.com/jo-inc/camofox-browser / Human Manual
Session & Tab Management
Related topics: System Architecture, Cookie & Session Persistence
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: System Architecture, Cookie & Session Persistence
Session & Tab Management
Camofox-browser implements a hierarchical session and tab management system built on Playwright's browser context model. Each user session isolates browser state (cookies, storage, proxy settings) while supporting multiple concurrent tabs within that context. The system provides RESTful APIs for all tab operations, lifecycle event hooks for plugins, and automatic resource cleanup through pressure-based reaping.
Architecture Overview
The management layer sits between the HTTP API surface and Playwright's browser instance, coordinating sessions and tabs with concurrency controls, locking mechanisms, and metrics collection.
graph TD
A[HTTP API] --> B[Request Middleware]
B --> C[Auth Middleware]
C --> D[Tab Lock Manager]
D --> E[Session Map]
E --> F[TabGroups per Session]
F --> G[Individual TabState]
G --> H[Playwright Page]
D -.->|Queue Depth Metric| I[Prometheus Metrics]
E -.->|Active Tabs Gauge| IKey Data Structures
| Structure | Type | Purpose |
|---|---|---|
sessions | Map<userId, Session> | User session registry |
tabLocks | Map<tabId, TabLock> | Per-tab operation serialization |
tabLockQueueDepth | Gauge | Prometheus metric for lock contention |
activeTabsGauge | Gauge | Current active tab count |
Source: server.js:1-100 and server.js:200-350
Source: https://github.com/jo-inc/camofox-browser / Human Manual
API Reference
Related topics: Search Macros, Configuration Reference
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Search Macros, Configuration Reference
API Reference
The camofox-browser API is a REST-based HTTP interface for controlling an anti-detection browser automation server designed for AI agents. The API provides programmatic access to browser tab management, page interaction, content extraction, and session administration through a well-documented OpenAPI 3.0.3 specification.
Overview
The API serves as the primary interface for external clients (AI agents, scripts, applications) to control browser automation tasks. It handles:
- Tab Lifecycle Management — Create, navigate, close, and query browser tabs
- Page Interaction — Click elements, type text, press keys, scroll pages
- Content Extraction — Retrieve snapshots, screenshots, images, and structured data via JSON Schema
- Session Administration — Manage user sessions, import cookies, handle proxy rotation
- System Monitoring — Health checks, statistics, trace downloads
The server listens on port 9377 by default and returns JSON responses for all endpoints.
Source: lib/openapi.js:1-25
OpenAPI Documentation
The API specification is automatically generated from JSDoc @openapi comments embedded in route handlers within server.js. This approach ensures documentation stays synchronized with implementation changes.
Accessing the Documentation
Two documentation formats are available:
| Format | Endpoint | Description |
|---|---|---|
| Swagger UI | GET /docs | Interactive three-panel UI (swagger-stripey) |
| OpenAPI JSON | GET /openapi.json | Machine-readable spec for code generation |
Source: lib/openapi.js:1-20
Regenerating the Spec
After modifying any route handler in server.js, run:
npm run generate-openapi
The test suite will fail if the committed openapi.json becomes stale.
Source: AGENTS.md:1-10
Authentication
The API supports two authentication mechanisms configured via environment variables:
| Method | Environment Variable | Description |
|---|---|---|
| API Key | API_KEY | Bearer token passed in Authorization header |
| Loopback Only | — | Restricts access to 127.0.0.1 when no API key is set |
The auth() middleware is applied selectively to sensitive endpoints such as trace downloads. Public endpoints like health checks do not require authentication.
Source: AGENTS.md:1-15
Tab Routes
Tab routes follow the pattern /tabs/:tabId/* and provide core browser interaction capabilities.
Tab Management
| Endpoint | Method | Description |
|---|---|---|
/tabs/:tabId | DELETE | Close a tab and release resources |
/tabs | GET | List all tabs for a user |
/tabs/:tabId/stats | GET | Retrieve tab metadata (URL, tool calls, visited URLs, download count) |
#### Closing a Tab
DELETE /tabs/:tabId?userId=<userId>
Response:
{ "ok": true }
When a tab is closed, the server:
- Aborts any pending navigation
- Clears associated downloads
- Closes the page safely with timeout guard
- Removes the tab from its group
Source: server.js:1-30
Navigation
| Endpoint | Method | Description |
|---|---|---|
/tabs/:tabId/navigate | POST | Navigate to URL or execute search macro |
#### Navigate Request
{
"userId": "string",
"url": "string",
"macro": "@google_search",
"query": "search terms",
"sessionKey": "string",
"listItemId": "string"
}
The endpoint resolves a session key from sessionKey or listItemId to load cookies before navigation, enabling authenticated scraping sessions.
Source: server.js:1-40
Interaction
| Endpoint | Method | Description |
|---|---|---|
/tabs/:tabId/click | POST | Click an element by ref or CSS selector |
/tabs/:tabId/type | POST | Type text into a focused element |
/tabs/:tabId/press | POST | Press a keyboard key |
/tabs/:tabId/scroll | POST | Scroll the page |
#### Click Element
{
"userId": "string",
"ref": "e1",
"selector": "#submit-button"
}
Either ref (snapshot element reference) or selector (CSS selector) is required. The endpoint implements click budget tracking to prevent runaway automation.
Source: server.js:1-50
#### Type Text
{
"userId": "string",
"ref": "e1",
"selector": "input[name='email']",
"text": "[email protected]",
"clear": true,
"submit": false
}
| Parameter | Type | Description |
|---|---|---|
text | string | Text to type |
ref | string | Snapshot element ref (optional) |
selector | string | CSS selector (optional) |
clear | boolean | Clear field before typing |
submit | boolean | Press Enter after typing |
Source: server.js:1-40
#### Press Key
{
"userId": "string",
"key": "Enter"
}
Supported keys: Enter, Escape, Tab, Backspace, arrow keys, etc.
Source: server.js:1-25
Content Extraction
| Endpoint | Method | Description |
|---|---|---|
/tabs/:tabId/snapshot | GET | Get accessibility tree snapshot |
/tabs/:tabId/screenshot | GET | Capture page screenshot |
/tabs/:tabId/images | GET | List page images |
/tabs/:tabId/extract | POST | Extract structured data via JSON Schema |
#### Snapshot Pagination
Large snapshots are paginated to prevent memory issues:
GET /tabs/:tabId/snapshot?offset=5000
Response includes:
{
"text": "...",
"truncated": true,
"totalChars": 25000,
"offset": 5000,
"hasMore": true,
"nextOffset": 10000
}
Source: lib/snapshot.js:1-20
#### Extract Structured Data
{
"userId": "string",
"schema": {
"type": "object",
"properties": {
"title": {
"type": "string",
"x-ref": "e1"
},
"price": {
"type": "number",
"x-ref": "e2"
}
}
}
}
The x-ref hints point to element refs from the accessibility snapshot, allowing precise data extraction without fragile CSS selectors.
Source: server.js:1-30
Viewport and Browser State
| Endpoint | Method | Description |
|---|---|---|
/tabs/:tabId/viewport | POST | Set viewport dimensions |
/tabs/:tabId/back | POST | Navigate back in history |
/tabs/:tabId/reload | POST | Reload the current page |
#### Set Viewport
{
"userId": "string",
"width": 1920,
"height": 1080
}
Constraints: width and height must be between 100 and 4000 pixels.
Source: server.js:1-20
Session Routes
Session routes manage user sessions and associated resources.
| Endpoint | Method | Description |
|---|---|---|
/sessions | GET | List active sessions |
/sessions/:userId | DELETE | Destroy a session |
/sessions/:userId/traces/:filename | GET | Download a trace zip |
Trace Downloads
GET /sessions/:userId/traces/:filename
Authorization: Bearer <apiKey>
Returns a zip stream with Content-Type: application/zip. The filename must be validated to prevent path traversal attacks.
Source: server.js:1-25
Browser Routes
| Endpoint | Method | Description |
|---|---|---|
/browser/launch | POST | Launch browser with options |
/browser/close | POST | Close the browser |
/browser/contexts | GET | List browser contexts |
System Routes
| Endpoint | Method | Description |
|---|---|---|
/health | GET | Health check endpoint |
/system/recycle | POST | Recycle browser |
/system/plugins | GET | List installed plugins |
Health Check Response
{
"ok": true,
"engine": "camoufox",
"browserConnected": true,
"browserRunning": true,
"activeTabs": 5,
"activeSessions": 2,
"consecutiveFailures": 0,
"memory": {
"rssMb": 150,
"heapUsedMb": 66,
"nativeMemMb": 84
}
}
Returns HTTP 503 with { "ok": false, "recovering": true } when the browser is restarting after a crash.
Source: server.js:1-30
Plugin Events
Plugins can subscribe to lifecycle events to extend functionality. The event bus supports the following events:
Session Events
| Event | Payload | Description |
|---|---|---|
session:creating | { userId, contextOptions } | Session about to be created |
session:created | { userId, context } | Session created |
session:destroyed | { userId, reason } | Session destroyed |
session:expired | { userId, idleMs } | Session expired due to inactivity |
Tab Events
| Event | Payload | Description |
|---|---|---|
tab:created | { userId, tabId, page, url } | Tab created |
tab:navigated | { userId, tabId, url, prevUrl } | Tab navigated to new URL |
tab:destroyed | { userId, tabId, reason } | Tab closed |
tab:recycled | { userId, tabId } | Tab recycled for reuse |
Interaction Events
| Event | Payload | Description |
|---|---|---|
tab:click | { userId, tabId, ref, selector } | Element clicked |
tab:type | { userId, tabId, text, ref, mode } | Text typed |
tab:scroll | { userId, tabId, direction, amount } | Page scrolled |
tab:press | { userId, tabId, key } | Key pressed |
Source: AGENTS.md:1-30
Error Handling
All error responses follow a consistent JSON format:
{
"error": "Human-readable error message"
}
| HTTP Status | Meaning |
|---|---|
| 400 | Bad request (missing required parameters) |
| 401 | Unauthorized (missing or invalid API key) |
| 403 | Forbidden (loopback restriction violated) |
| 404 | Tab or resource not found |
| 500 | Internal server error |
| 503 | Service unavailable (browser recovering) |
The safeError() function sanitizes error messages before sending to clients, preventing information leakage.
Source: server.js:1-20
Common Issues and Limitations
Event Loop Stalls
The community has reported multiple instances of event loop stalls where operations block for extended periods (5-74 seconds) before completing. This manifests as:
{ "driftMs": 21700, "thresholdMs": 5000 }
These stalls typically occur during heavy navigation or page interaction workloads. The server monitors event loop health and logs warnings when stalls exceed the 5-second threshold.
VNC in Docker
As of version 1.11, VNC activation via environment variables changed in Docker deployments. Previously working configurations:
docker run --rm -it -p 9377:9377 -p 6080:6080 \
-e ENABLE_VNC=1 -e VNC_BIND=0.0.0.0 \
ghcr.io/jo-inc/camofox-browser:1.10.0
May require adjustment in version 1.11 due to environment variable handling changes.
Plugin Updates
Some users have reported ERR_MODULE_NOT_FOUND errors when updating plugins from versions 4.5 to 4.9, particularly when running on Open Collective infrastructure.
Rate Limits and Budgets
The API implements several protection mechanisms:
| Limit | Description |
|---|---|
| Per-user concurrency | withUserLimit() prevents excessive parallel operations |
| Tab lock | withTabLock() serializes operations on the same tab |
| Click budget | Tracks remaining budget for click operations |
| Memory limits | Snapshot pagination with MAX_SNAPSHOT_CHARS |
These limits help prevent runaway automation and protect against anti-bot detection patterns.
Source: server.js:1-40
NPM Plugin Integration
External tools like @askjo/camofox-browser provide client-side wrappers around the REST API:
// Example plugin tools available
camofox_evaluate // Execute JavaScript in page context
camofox_list_tabs // List open tabs for user
camofox_import_cookies // Import Netscape-format cookies
The plugin automatically routes requests to the server's REST endpoints, handling authentication and response parsing.
Source: plugin.js:1-30
Source: https://github.com/jo-inc/camofox-browser / Human Manual
Search Macros
Related topics: API Reference
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: API Reference
Search Macros
Overview
Search Macros provide a convenient abstraction layer for constructing search URLs across popular platforms. Instead of manually building search URLs with proper encoding, users can invoke named macros that generate correctly formatted URLs for navigation.
The macro system acts as a URL template engine that accepts a search query and returns a fully-qualified search URL for the target platform. This eliminates the need to remember platform-specific URL patterns and ensures proper URL encoding of special characters.
Key Characteristics:
- Platform Abstraction: Macros hide platform-specific URL construction details
- Automatic Encoding: All query parameters are properly URL-encoded
- Type Safety: Macros are enumerated in tool schemas to prevent typos
- Unified Interface: Single
macro+queryparameter pattern across all navigation calls
Source: lib/macros.js:1-20
Source: https://github.com/jo-inc/camofox-browser / Human Manual
Deployment Guide
Related topics: Quick Start Guide, Configuration Reference
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Quick Start Guide, Configuration Reference
Deployment Guide
This guide covers all supported deployment methods for camofox-browser, including Docker containers, Railway, CLI binary installation, and source-based deployments.
Overview
camofox-browser is a Node.js-based anti-detection browser automation server. The application launches a Firefox browser instance (via Camoufox) and exposes a REST API for controlling tabs, navigation, and interaction. Deployments must ensure the server process has access to display infrastructure (X11/Wayland on Linux, native display on macOS/Windows) and sufficient system resources for browser operations.
Deployment Methods
Docker Deployment
Docker is the recommended deployment method for production environments. The container includes pre-installed browser dependencies and default plugin support.
#### Pulling the Image
The official Docker images are hosted on GitHub Container Registry:
# Using a specific version
docker pull ghcr.io/jo-inc/camofox-browser:1.11.2
# Using latest release
docker pull ghcr.io/jo-inc/camofox-browser:latest
#### Basic Usage
docker run --rm -it -p 9377:9377 \
ghcr.io/jo-inc/camofox-browser:latest
#### VNC Support
Enable VNC for visual debugging and monitoring:
docker run --rm -it -p 9377:9377 -p 6080:6080 \
-e ENABLE_VNC=1 \
-e VNC_BIND=0.0.0.0 \
ghcr.io/jo-inc/camofox-browser:latest
# Verify VNC is active
curl -4I localhost:6080
HTTP/1.1 200 OK
| Environment Variable | Description | Default |
|---|---|---|
ENABLE_VNC | Enable VNC server (1/0) | 0 |
VNC_BIND | VNC bind address | 127.0.0.1 |
VNC_PORT | VNC port | 6080 |
Note: VNC environment variable activation had a regression in version 1.11. If VNC does not activate from environment variables, verify the version and consider downgrading to 1.10.0 or using explicit configuration. Source: GitHub Issue #4314
#### Production Docker Configuration
docker run --rm -d \
--name camofox \
-p 9377:9377 \
-p 6080:6080 \
-v camofox-data:/data \
-e ENABLE_VNC=1 \
-e API_KEY=your-secure-api-key \
-e SESSION_TIMEOUT=1800000 \
--restart unless-stopped \
--memory=4g \
--shm-size=2g \
ghcr.io/jo-inc/camofox-browser:latest
#### Docker Health Monitoring
The container exposes health check endpoints for orchestration platforms:
# Check health status
curl http://localhost:9377/health
# Expected response
{
"ok": true,
"engine": "camoufox",
"browserConnected": true,
"browserRunning": true,
"activeTabs": 0,
"activeSessions": 0
}
Railway Deployment
Railway provides one-click deployment with automatic HTTPS and environment variable management.
#### Configuration File
Create railway.toml in the repository root:
[railway]
builder = "nixpacks"
minDockerVersion = 23
[deploy]
numReplicas = 1
restartPolicyType = "ON_FAILURE"
restartPolicyMaxRetries = 10
startCommand = "npm start"
Source: railway.toml
#### Railway Environment Variables
Configure these in the Railway dashboard:
| Variable | Description | Required |
|---|---|---|
API_KEY | Authentication key for API access | Yes |
PORT | Server port (Railway sets this automatically) | No |
SESSION_TIMEOUT | Session timeout in milliseconds | No |
MAX_CONCURRENT_SESSIONS | Maximum concurrent user sessions | No |
CLI Binary Installation
For lightweight deployments without Docker, use the npm package:
# Run directly with npx
npx @askjo/camofox-browser
# Install globally
npm install -g @askjo/camofox-browser
camofox-browser
Source: AGENTS.md
The CLI binary uses the same environment variables as source installations. Default port remains 9377.
Source-Based Deployment
#### Prerequisites
| Requirement | Version | Notes |
|---|---|---|
| Node.js | v22+ | LTS recommended |
| npm | 10+ | Included with Node.js |
| Firefox | Latest | Or use Camoufox bundled browser |
| X11/Wayland | System-dependent | Required for headless browser |
#### Installation Steps
# Clone the repository
git clone https://github.com/jo-inc/camofox-browser.git
cd camofox-browser
# Install dependencies
npm install
# Start the server
npm start
Source: AGENTS.md
#### Running with Camoufox Engine
# Using the run script
./run.sh
# Or directly with npm
npm start
Environment Variables
Core Configuration
| Variable | Default | Description |
|---|---|---|
PORT | 9377 | HTTP server port |
API_KEY | - | Required for production authentication |
NODE_ENV | development | Environment mode |
SESSION_TIMEOUT | 1800000 | Session timeout in ms (30 min default) |
Source: server.js
Browser Configuration
| Variable | Description |
|---|---|
PROXY_URL | Proxy server URL for external requests |
BROWSER_HEADLESS | Run browser in headless mode |
BROWSER_ARGS | Additional Chromium/Firefox arguments |
Logging and Monitoring
| Variable | Default | Description |
|---|---|---|
LOG_LEVEL | info | Log verbosity (debug, info, warn, error) |
ENABLE_TRACES | false | Enable Playwright trace collection |
CRASH_REPORT_URL | - | Custom crash reporter endpoint |
Crash Reporter Setup
The crash reporter supports GitHub App authentication for automated issue creation:
# Configure GitHub App authentication
export GH_APP_ID=your-app-id
export GH_APP_PRIVATE_KEY=your-private-key
export GH_INSTALLATION_ID=your-installation-id
Source: lib/reporter.js
Build System
Makefile Targets
The Makefile provides standardized build commands:
# Development targets
make install # Install dependencies
make build # Build the project
make start # Run the server
make test # Run all tests
make test:e2e # Run end-to-end tests
make test:live # Run live browser tests
make test:plugins # Run plugin tests
make clean # Clean build artifacts
Source: Makefile
Windows Build Script
PowerShell build automation for Windows environments:
# From PowerShell
.\build.ps1
# With options
.\build.ps1 -Task build -Configuration Release
Source: build.ps1
Docker Build
Build custom Docker images locally:
# Production image
docker build -t camofox:local .
# CI image (includes test dependencies)
docker build -f Dockerfile.ci -t camofox:ci .
Architecture Overview
graph TD
A[Client / AI Agent] -->|HTTP/REST| B[camofox-server:9377]
B --> C[Camoufox Engine]
C --> D[Firefox Browser]
D --> E[Page Tabs]
D --> F[Browser Contexts]
B --> G[Session Manager]
G --> H[User Sessions]
H --> I{Cookie Storage}
B --> J[Plugin System]
J --> K[Event Bus]
K --> L[Plugin Hooks]
M[Crash Reporter] -->|Anonymized Reports| N[GitHub Issues]
style A fill:#e1f5fe
style B fill:#b3e5fc
style C fill:#81d4fa
style D fill:#4fc3f7Resource Requirements
Minimum Requirements
| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 2 cores | 4+ cores |
| Memory (RAM) | 2 GB | 4+ GB |
| Disk | 500 MB | 2+ GB |
| Browser Memory | 256 MB/tab | 512 MB/tab |
Docker Resource Limits
# docker-compose.yml excerpt
services:
camofox:
deploy:
resources:
limits:
memory: 4G
reservations:
memory: 2G
shm_size: 2g
Important: Event loop stalls are frequently reported in the community, often correlating with high memory usage and long uptimes. Set appropriate memory limits and consider periodic restarts in long-running deployments. Source: Community Issues
Health Checks
Endpoint Reference
| Endpoint | Method | Description |
|---|---|---|
/health | GET | Server and browser health status |
/health/ready | GET | Readiness probe |
/health/live | GET | Liveness probe |
Health Response Schema
{
"ok": true,
"engine": "camoufox",
"browserConnected": true,
"browserRunning": true,
"activeTabs": 0,
"activeSessions": 0,
"consecutiveFailures": 0,
"memory": {
"rssMb": 45,
"heapUsedMb": 35,
"nativeMemMb": 10
}
}
Source: server.js
Troubleshooting
Common Deployment Issues
| Issue | Cause | Solution |
|---|---|---|
| VNC not activating | Environment variable regression in 1.11 | Use explicit config or downgrade to 1.10.0 |
| Event loop stalls | Memory pressure, long uptimes | Increase memory, add restart policy |
| Plugin install fails | Module not found error | Verify npm plugin compatibility |
| Browser won't launch | Missing display/X11 | Use headless mode or Docker with display |
| High memory usage | Tab leak, no cleanup | Implement session timeouts, monitor tabs |
Source: GitHub Issues #4314, #54
Container Logs
# View logs
docker logs camofox
# Follow logs in real-time
docker logs -f camofox
# Export logs with timestamps
docker logs -t camofox > camofox.log
Debug Mode
Enable verbose logging for troubleshooting:
# Via environment
export LOG_LEVEL=debug
npm start
# Via Docker
docker run ... -e LOG_LEVEL=debug ghcr.io/jo-inc/camofox-browser:latest
Security Considerations
Production Checklist
- [ ] Set a strong
API_KEY - [ ] Enable
NODE_ENV=production - [ ] Configure firewall rules for port
9377 - [ ] Enable TLS/HTTPS via reverse proxy
- [ ] Set appropriate
SESSION_TIMEOUT - [ ] Configure
CRASH_REPORT_URLfor monitoring - [ ] Use read-only container filesystem where possible
- [ ] Limit container privileges with
--read-only
Authentication
All production deployments should use API key authentication:
# All requests require API key
curl -H "X-API-Key: your-secure-api-key" \
http://localhost:9377/health
Updating
Docker Updates
# Pull new version
docker pull ghcr.io/jo-inc/camofox-browser:1.11.2
# Restart container
docker stop camofox && docker rm camofox
docker run ... ghcr.io/jo-inc/camofox-browser:1.11.2
NPM Updates
# Check for updates
npm outdated @askjo/camofox-browser
# Update
npm install -g @askjo/camofox-browser@latest
Source Updates
git pull origin main
npm install
npm start
Plugin Deployment
Plugins extend functionality and are installed at runtime:
# Install from git
node scripts/plugin.js install git:github.com/user/plugin-repo
# Install from local path
node scripts/plugin.js install ./path/to/local/plugin
# List installed plugins
node scripts/plugin.js list
# Remove plugin
node scripts/plugin.js remove plugin-name
Source: scripts/plugin.js
Source: https://github.com/jo-inc/camofox-browser / Human Manual
Plugin System
Related topics: Deployment Guide, Cookie & Session Persistence
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Deployment Guide, Cookie & Session Persistence
Plugin System
Overview
The camofox-browser plugin system provides an extensible architecture for adding custom functionality to the browser automation server. Plugins can hook into browser lifecycle events, modify session behavior, register custom tools, and integrate external services.
Plugins live in the plugins/<name>/ directory and export a register(app, ctx) function that receives the Express app instance and a context object providing access to core functionality.
Architecture
Core Components
graph TD
A[Plugin] --> B[register function]
B --> C[Express App]
B --> D[Context Object]
B --> E[EventEmitter]
C --> F[Route Handlers]
D --> G[sessions]
D --> H[CONFIG]
D --> I[Core Functions]
E --> J[Browser Lifecycle Events]
E --> K[Tab Lifecycle Events]
E --> L[Input Events]
style A fill:#e1f5fe
style C fill:#fff3e0
style E fill:#e8f5e9Context Object API
The context object passed to plugin register functions provides:
| Property | Type | Description | |
|---|---|---|---|
sessions | Map | Active user sessions (userId → session) | |
CONFIG | object | Server configuration (port, apiKey, nodeEnv, proxy, etc.) | |
log | function | log(level, msg, fields) — structured JSON logging | |
events | EventEmitter | Plugin event bus (29 events) | |
auth | function | Express middleware enforcing API key / loopback | |
ensureBrowser | async function | Launch browser if not running | |
getSession | async function | Get or create a session by userId | |
destroySession | function | Tear down a session | |
withUserLimit | async function | Run function within per-user concurrency limit | |
safePageClose | async function | Close page with timeout guard | |
normalizeUserId | function | Coerce to string for map keys | |
validateUrl | function | Returns error string or null | |
safeError | function | Sanitize error for client response | |
buildProxyUrl | function | Get proxy URL for external requests | |
proxyPool | `object\ | null` | Proxy pool instance |
failuresTotal | Counter | Prometheus counter for failures |
*Source: AGENTS.md:1-50*
Plugin Structure
File Organization
plugins/
<name>/
index.js # Main plugin file with register(app, ctx)
package.json # Optional: plugin dependencies
Register Function
Each plugin exports a function that receives the Express app and context:
// plugins/example/index.js
export function register(app, ctx) {
// Register custom routes
app.get('/my-plugin/status', (req, res) => {
res.json({ status: 'ok', plugin: 'example' });
});
// Subscribe to events
ctx.events.on('browser:launched', ({ browser, display }) => {
ctx.log('info', 'example: browser launched');
});
}
Plugin Manager CLI
The scripts/plugin.js script provides plugin management commands:
# Install from git URL or local path
node scripts/plugin.js install <git-url|local-path>
# Install from various sources
node scripts/plugin.js install git:github.com/user/repo
node scripts/plugin.js install https://github.com/user/repo
node scripts/plugin.js install ./path/to/local/plugin
# Remove a plugin
node scripts/plugin.js remove <name>
# List installed plugins
node scripts/plugin.js list
*Source: scripts/plugin.js:1-80*
Event System
The plugin system provides 29 events across 7 categories via the ctx.events EventEmitter.
Event Categories
graph TD
A[29 Plugin Events] --> B[Browser Lifecycle<br/>5 events]
A --> C[Session Lifecycle<br/>5 events]
A --> D[Tab Lifecycle<br/>5 events]
A --> E[Content<br/>3 events]
A --> F[Input<br/>4 events]
A --> G[Downloads<br/>2 events]
A --> H[System<br/>5 events]
style B fill:#e3f2fd
style C fill:#f3e5f5
style D fill:#e8f5e9
style E fill:#fff3e0
style F fill:#fce4ec
style G fill:#e0f7fa
style H fill:#f1f8e9Browser Lifecycle Events
| Event | Payload | Description |
|---|---|---|
browser:launching | { options } | Mutate launch options before browser starts |
browser:launched | { browser, display } | After browser successfully launched |
browser:restart | { reason } | Before restart cycle begins |
browser:closed | { reason } | After browser closed |
browser:error | { error } | Uncaught browser error |
*Source: lib/plugins.js:1-30*
Session Lifecycle Events
| Event | Payload | Description |
|---|---|---|
session:creating | { userId, contextOptions } | Modify context options in-place |
session:created | { userId, context } | After context stored |
session:destroying | { userId, reason } | Before context close |
session:destroyed | { userId, reason } | After cleanup |
session:expired | { userId, idleMs } | Reaper triggered |
Tab Lifecycle Events
| Event | Payload | Description |
|---|---|---|
tab:created | { userId, tabId, page, url } | New tab created |
tab:navigated | { userId, tabId, url, prevUrl } | Tab navigated to new URL |
tab:destroyed | { userId, tabId, reason } | Tab closed |
tab:recycled | { userId, tabId } | Tab recycled for reuse |
tab:error | { userId, tabId, error } | Tab error occurred |
Content Events
| Event | Payload | Description |
|---|---|---|
tab:snapshot | { userId, tabId, snapshot } | Page accessibility snapshot captured |
tab:screenshot | { userId, tabId, buffer } | Screenshot taken |
tab:evaluate | { userId, tabId, expression } | JavaScript evaluation requested |
tab:evaluated | { userId, tabId, result } | JavaScript evaluation completed |
Input Events
| Event | Payload | Description |
|---|---|---|
tab:click | { userId, tabId, ref, selector } | Element click performed |
tab:type | { userId, tabId, text, ref, mode } | Text typed |
tab:scroll | { userId, tabId, direction, amount } | Page scrolled |
tab:press | { userId, tabId, key } | Keyboard key pressed |
*Source: AGENTS.md:80-120*
Built-in Plugins
VNC Plugin
The VNC plugin provides browser screen sharing for debugging and monitoring.
Configuration via environment variables:
| Variable | Description |
|---|---|
ENABLE_VNC | Enable VNC server |
VNC_BIND | Bind address (default: 127.0.0.1) |
VNC_PORT | VNC port (default: 6080) |
Location: plugins/vnc/index.js, plugins/vnc/vnc-launcher.js
Persistence Plugin
Maintains session state across restarts.
Location: plugins/persistence/index.js
YouTube Plugin
YouTube-specific automation helpers.
Location: plugins/youtube/index.js
AI Agent Integration Plugins
camofox-browser provides TypeScript and JavaScript plugins for AI agent integration.
TypeScript Plugin (`plugin.ts`)
Provides typed tools for AI agents to interact with camofox:
| Tool | Description |
|---|---|
camofox_navigate | Navigate to URL with macro support |
camofox_screenshot | Take page screenshot |
camofox_snapshot | Get accessibility tree snapshot |
camofox_click | Click element by ref/selector |
camofox_type | Type text into element |
camofox_scroll | Scroll page |
camofox_press | Press keyboard key |
camofox_evaluate | Execute JavaScript |
camofox_list_tabs | List open tabs |
camofox_import_cookies | Import cookies for authentication |
*Source: plugin.ts:1-200*
JavaScript Plugin (`plugin.js`)
Provides the same tools in JavaScript format for broader compatibility.
Search Macros Supported:
| Macro | Description |
|---|---|
@google_search | Google search |
@youtube_search | YouTube search |
@amazon_search | Amazon search |
@reddit_search | Reddit search |
@wikipedia_search | Wikipedia search |
@twitter_search | Twitter/X search |
@yelp_search | Yelp search |
@spotify_search | Spotify search |
@netflix_search | Netflix search |
@linkedin_search | LinkedIn search |
@instagram_search | Instagram search |
@tiktok_search | TikTok search |
@twitch_search | Twitch search |
*Source: plugin.js:1-150*
Plugin Installation Workflow
sequenceDiagram
participant User
participant CLI as scripts/plugin.js
participant Git as Git Source
participant FS as Local Filesystem
User->>CLI: node scripts/plugin.js install <source>
CLI->>CLI: parseSource(source)
alt Git Source
CLI->>Git: Clone repository
Git-->>CLI: Plugin files
else Local Path
CLI->>FS: Read local directory
FS-->>CLI: Plugin files
end
CLI->>CLI: installPluginDeps(name)
CLI->>CLI: addToConfig(name)
CLI-->>User: Installed: <name>
User->>User: Restart serverTroubleshooting
Plugin Update Failures
Issue: Plugin update fails with ERR_MODULE_NOT_FOUND
Failed to update camofox-browser: Error [ERR_MODULE_NOT_FOUND]: Cannot find module...
This may occur when updating from older versions. Solution: ensure all dependencies are properly installed:
npm install
node scripts/plugin.js list
VNC Not Activating in Docker
Issue: VNC doesn't activate from environment variables in Docker
docker run --rm -it -p 9377:9377 -p 6080:6080 \
-e ENABLE_VNC=1 -e VNC_BIND=0.0.0.0 \
ghcr.io/jo-inc/camofox-browser:1.10.0
In version 1.11+, the VNC plugin may require explicit installation or configuration. Ensure the plugins/vnc directory is included in your Docker image or install it after container start.
*Source: lib/openapi.js:1-40*
Best Practices
- Always unsubscribe from events in cleanup handlers to prevent memory leaks
- Use
ctx.log()instead ofconsole.log()for consistent logging - Handle errors gracefully and use
ctx.safeError()for client responses - Respect concurrency limits using
ctx.withUserLimit()for user-specific operations - Test plugins locally before distribution using local path installation
See Also
- API Documentation — Full REST API reference
- README.md — Getting started guide
- AGENTS.md — Agent integration guide
Source: https://github.com/jo-inc/camofox-browser / Human Manual
Configuration Reference
Related topics: Deployment Guide
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Deployment Guide
Configuration Reference
Camofox-browser is an anti-detection browser automation server designed for AI agents. Configuration controls how the browser engine launches, how sessions are managed, how resources are allocated, and how the server exposes its API. This reference documents the configuration mechanisms, their purposes, and how they interact.
Configuration Overview
Camofox-browser supports three primary configuration mechanisms:
| Mechanism | Priority | Use Case |
|---|---|---|
| Environment variables | Highest | Docker deployments, production secrets |
JSON config file (camofox.config.json) | Medium | Local development, shared team settings |
| Runtime defaults | Lowest | Fresh installations, quick start |
The configuration system is loaded at server startup. Changes to the JSON config file require a server restart. Environment variables override JSON config values. Source: server.js
Server Configuration
Network Settings
The default listening port is 9377. Configure the port through environment variables or the JSON config file.
| Setting | Environment Variable | Default | Description |
|---|---|---|---|
| Port | PORT or CAMOFOX_PORT | 9377 | HTTP server listening port |
| Host | HOST or CAMOFOX_HOST | 0.0.0.0 | Bind address |
| API Key | CAMOFOX_API_KEY | (none) | Required for certain API endpoints |
The server initializes Express and mounts all routes after configuration is loaded. Source: package.json:24-27
# Run with custom port
PORT=8080 node server.js
# Run with API key authentication
CAMOFOX_API_KEY=secret123 node server.js
Health Check Configuration
The /health endpoint reports server and browser state. Configuration affects what metrics are exposed and how recovery is detected.
| Metric | Description |
|---|---|
engine | Always "camoufox" |
browserConnected | Whether the Playwright browser instance is connected |
browserRunning | Whether the browser process is running |
activeTabs | Count of currently open tabs across all sessions |
activeSessions | Number of active user sessions |
consecutiveFailures | Count of consecutive navigation failures |
memory.rssMb | Resident set size in megabytes |
memory.heapUsedMb | V8 heap used in megabytes |
memory.nativeMemMb | Native memory (RSS minus heap) |
Source: server.js (health endpoint implementation)
The health endpoint returns HTTP 503 with { "ok": false, "recovering": true } when the server is in a recovery state after browser crashes.
Browser Engine Configuration
Launch Options
Camofox-browser uses the Camoufox anti-detection browser engine built on Playwright. Browser launch options control fingerprinting, automation detection evasion, and runtime behavior.
Key browser configuration areas:
| Category | Options |
|---|---|
| Stealth | WebGL vendor/renderer spoofing, navigator properties, automation detection hiding |
| Viewport | Width (100-4000px), Height (100-4000px) per tab |
| Proxy | HTTP/HTTPS/SOCKS support with authentication |
| User Agent | Auto-selected based on engine defaults |
| Headers | Custom default headers for all requests |
The /tabs/:tabId/viewport endpoint validates viewport dimensions: both width and height must be between 100 and 4000 pixels. Source: server.js (viewport endpoint)
Tab Management
Each user session can have multiple tab groups. Tab state tracking includes:
tabState.toolCalls++; // Increments on every tool use
tabState.consecutiveTimeouts = 0; // Resets on successful operation
tabState.consecutiveFailures = 0; // Resets on successful operation
Tabs are automatically cleaned up when:
- The tab is explicitly closed via
DELETE /tabs/:tabId - All tabs in a group are closed (group is deleted)
- Browser context resources exceed limits
Source: server.js (tab cleanup logic)
Plugin System Configuration
The plugin system allows extending camofox-browser functionality. Plugins can register tools, CLI commands, and lifecycle hooks.
Plugin Lifecycle Events
Plugins can hook into these events:
| Event | Timing | Mutates Options? |
|---|---|---|
browser:launching | Before browser starts | Yes |
session:creating | Before session created | Yes |
tab:created | After tab created | No |
tab:navigated | After navigation completes | No |
tab:destroyed | When tab closes | No |
tab:recycled | When tab is reused | No |
tab:error | On tab error | No |
Source: lib/plugins.js (event definitions)
Plugin Installation
Use the CLI to manage plugins:
# Install from GitHub
node scripts/plugin.js install git:github.com/user/repo
# Install from local path
node scripts/plugin.js install ./path/to/local/plugin
# Remove a plugin
node scripts/plugin.js remove plugin-name
# List installed plugins
node scripts/plugin.js list
Installed plugins are added to the configuration file and their dependencies are installed via npm. Source: scripts/plugin.js
Plugin Dependencies
Plugins can specify npm dependencies that are installed when the plugin is added. The Dockerfile pre-installs default plugin dependencies. Source: AGENTS.md
Resource Limits
User Limits
Per-user rate limiting and resource quotas prevent individual users from monopolizing server resources:
withUserLimit(userId, () => /* operation */)
This wrapper is applied to navigation, click, and other tool operations. When limits are exceeded, the server returns an appropriate error response.
Memory Management
The server tracks memory usage through the health endpoint:
| Metric | Formula |
|---|---|
rssMb | process.memoryUsage().rss / 1048576 |
heapUsedMb | process.memoryUsage().heapUsed / 1048576 |
nativeMemMb | rssMb - heapUsedMb |
Source: server.js (health endpoint)
Snapshot Size Limits
Snapshot content is paginated to prevent memory exhaustion:
| Constant | Value | Purpose |
|---|---|---|
MAX_SNAPSHOT_CHARS | Configurable | Maximum characters per snapshot chunk |
SNAPSHOT_TAIL_CHARS | Configurable | Characters reserved for tail content |
When content exceeds limits, pagination metadata is returned:
{
text: chunk + marker,
truncated: true,
totalChars: total,
offset: clampedOffset,
hasMore: boolean,
nextOffset: hasMore ? chunkEnd : null
}
Source: lib/snapshot.js (pagination logic)
Image Extraction Limits
The /tabs/:tabId/images endpoint enforces extraction limits:
| Parameter | Query Param | Default | Max |
|---|---|---|---|
| Include base64 data | includeData | false | - |
| Max bytes per image | maxBytes | MAX_DOWNLOAD_INLINE_BYTES | - |
| Max images returned | limit | 8 | 20 |
Source: server.js (images endpoint)
Trace Configuration
Trace Directory
Traces are stored in CONFIG.tracesDir. Trace file paths are validated to prevent directory traversal attacks:
const full = resolveTracePath(CONFIG.tracesDir, userId, req.params.filename);
if (!full) return res.status(400).json({ error: 'invalid filename' });
Trace files are served as ZIP archives with proper Content-Type and Content-Length headers. Source: server.js (trace endpoint)
Schema Validation
The extraction system validates JSON schemas for structured data extraction:
| Type | Supported |
|---|---|
string | Yes |
number | Yes |
integer | Yes |
boolean | Yes |
object | Yes |
array | Yes |
null | Yes |
Type coercion attempts to extract numeric values from strings when possible:
// Number: strips non-numeric characters
parseFloat(String(raw).replace(/[^0-9.eE+-]/g, ''))
// Integer: strips non-numeric except minus
parseInt(String(raw).replace(/[^0-9-]/g, ''), 10)
Schema validation returns { ok: false, error: "..." } for invalid schemas. Source: lib/extract.js (validation functions)
Crash Reporter Configuration
The crash reporter monitors for event loop stalls and browser crashes:
| Setting | Default | Description |
|---|---|---|
| Event loop stall threshold | 5000ms | Time before event loop is considered stuck |
| Report destination | GitHub Issues API | Via camofox-crash-reporter |
Reportable Domains
The reporter maintains a list of "reportable" domains—sites where bot detection is expected and crashes are more meaningful:
- Social platforms:
facebook.com,twitter.com,linkedin.com,instagram.com - E-commerce:
amazon.com,ebay.com,walmart.com,etsy.com - Content sites:
reddit.com,medium.com,nytimes.com - Tech platforms:
github.com,stackoverflow.com,discord.com
Source: lib/reporter.js (domain list)
Anonymization
All auto-reported data is anonymized. The crash reporter adds a random 8-character suffix to issue titles to prevent deduplication and ensure each report is reviewed. Source: lib/reporter.js
Docker Configuration
For Docker deployments, environment variables control runtime behavior:
| Variable | Description | Example |
|---|---|---|
ENABLE_VNC | Enable VNC server on port 6080 | 1 |
VNC_BIND | VNC bind address | 0.0.0.0 |
PORT | HTTP server port | 9377 |
Docker Usage
docker run --rm -it -p 9377:9377 -p 6080:6080 \
-e ENABLE_VNC=1 \
-e VNC_BIND=0.0.0.0 \
ghcr.io/jo-inc/camofox-browser:latest
Source: community context (VNC configuration example)
OpenAPI Documentation
The API specification is auto-generated from JSDoc comments using swagger-jsdoc. The spec is served at:
| Endpoint | Format | Description |
|---|---|---|
GET /openapi.json | JSON | Machine-readable OpenAPI 3.0.3 spec |
GET /docs | HTML | Swagger-stripey three-panel UI |
When modifying routes, update the @openapi JSDoc block and regenerate:
npm run generate-openapi
Source: AGENTS.md (OpenAPI documentation rules)
Route Tags
Routes must be tagged with one of:
System- Health, status, info endpointsTabs- Tab CRUD operationsNavigation- URL navigation, search macrosInteraction- Click, type, scroll, pressContent- Snapshot, screenshot, evaluateSessions- Session managementBrowser- Browser-level operationsLegacy- Backward-compatible deprecated endpoints
Common Configuration Issues
Event Loop Stalls
Multiple community reports indicate event loop stalls occurring with extended server uptime (50000+ minutes). These manifest as:
Event loop stalled for Ns (threshold: 5s)
This typically indicates heavy CPU load or blocking operations. Mitigation strategies:
- Monitor
/healthendpoint memory metrics - Set appropriate
consecutiveFailuresthresholds - Consider server restart on high uptime
Source: community context (event loop stall reports)
VNC in Docker
VNC activation via environment variables changed in version 1.11. If VNC doesn't start in Docker:
- Verify
ENABLE_VNC=1is set - Confirm
VNC_BINDis configured - Check that port 6080 is exposed
Source: community context (VNC regression report)
Plugin Installation Failures
Plugin updates may fail with ERR_MODULE_NOT_FOUND. This typically occurs when:
- NPM dependencies are not installed
- The plugin path is incorrect
- Version incompatibilities exist between Node.js and plugin modules
Solution: Reinstall plugins or check Node.js version compatibility.
Source: community context (plugin update failure)
Source: https://github.com/jo-inc/camofox-browser / Human Manual
Cookie & Session Persistence
Related topics: Session & Tab Management, Plugin System
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Session & Tab Management, Plugin System
Cookie & Session Persistence
Camofox-browser provides a robust cookie and session persistence system that enables AI agents to maintain authenticated states across browser automation tasks. This system handles cookie import/export, session lifecycle management, and maintains persistent browser contexts for isolated user sessions.
Overview
The persistence layer consists of three interconnected systems:
- Cookie Management — Parses Netscape-format cookie files and imports them into browser contexts
- Session Lifecycle — Manages isolated browser contexts per user with configurable timeouts
- Plugin Events — Provides hooks for extending and monitoring session/cookie operations
graph TD
A[Cookie File] -->|Netscape Format| B[lib/cookies.js]
B --> C[Browser Context]
D[User Request] --> E[Session Manager]
E -->|userId| F[Isolated Context]
F --> C
G[Plugin System] -->|Hooks| E
G -->|Hooks| BCookie Management
Netscape Cookie File Format
Camofox-browser imports cookies from files in the Netscape format, the same format used by browser extensions like "EditThisCookie" and tools like curl --cookie-jar.
Source: lib/cookies.js:1-20
The cookie file format consists of tab-separated values with the following columns:
| Column | Description | Example |
|---|---|---|
| domain | Cookie domain (with leading dot for subdomains) | .example.com |
| flag | Include subdomains (TRUE/FALSE) | TRUE |
| path | URL path scope | / |
| secure | HTTPS only (TRUE/FALSE) | TRUE |
| expires | Unix timestamp | 1735689600 |
| name | Cookie name | session_id |
| value | Cookie value | abc123xyz |
Parsing Implementation
The parseNetscapeCookieFile() function handles:
- BOM removal — Strips UTF-8 BOM characters from file start
- Comment handling — Skips lines starting with
#(except#HttpOnly_) - HttpOnly detection — Recognizes
#HttpOnly_prefix and sets the flag accordingly - Tab escaping — Handles tab characters within cookie values by joining remaining parts
Source: lib/cookies.js:24-50
function parseNetscapeCookieFile(text) {
const cookies = [];
const cleaned = text.replace(/^\uFEFF/, '');
for (const rawLine of cleaned.split(/\r?\n/)) {
const line = rawLine.trim();
if (!line) continue;
if (line.startsWith('#') && !line.startsWith('#HttpOnly_')) continue;
let httpOnly = false;
let working = line;
if (working.startsWith('#HttpOnly_')) {
httpOnly = true;
working = working.replace(/^#HttpOnly_/, '');
}
// ... parse parts and push cookie object
}
return cookies;
}
Cookie File Reading
The readCookieFile() function provides secure file access with:
| Feature | Description |
|---|---|
| Path validation | Ensures path stays within cookiesDir using path.sep check |
| Size limit | Enforces 5MB maximum file size (configurable via maxBytes) |
| Domain filtering | Optional domainSuffix parameter to filter cookies by domain |
Source: lib/cookies.js:54-70
async function readCookieFile({ cookiesDir, cookiesPath, domainSuffix, maxBytes = 5 * 1024 * 1024 }) {
const resolved = path.resolve(cookiesDir, cookiesPath);
if (!resolved.startsWith(cookiesDir + path.sep)) {
throw new Error('cookiesPath must be a relative path within the cookies directory');
}
// ... validate size, read file, filter by domain
}
Session Management
Session Isolation
Each session is isolated using a unique userId that maps to a dedicated browser context. This ensures cookies, local storage, and browser state remain separate between different users or tasks.
Source: server.js:150-170
Session Lifecycle Events
The plugin system emits 29 events across 7 categories, with specific events for session and cookie lifecycle:
| Event | Payload | Description |
|---|---|---|
session:creating | { userId, contextOptions } | Mutate context options before creation |
session:created | { userId, context } | After context stored |
session:destroying | { userId, reason } | Before context close |
session:destroyed | { userId, reason } | After cleanup |
session:expired | { userId, idleMs } | Session reaper triggered |
session:cookies:import | { userId, count } | After cookie import |
session:storage:export | { userId } | Export request triggered |
Source: lib/plugins.js:9-30
Session Timeout Configuration
| Parameter | Default | Description |
|---|---|---|
sessionTimeoutMs | 600000 (10 min) | Session inactivity timeout |
browserIdleTimeoutMs | 300000 (5 min) | Kill browser after idle time with no sessions |
maxOldSpaceSize | 128 MB | Node.js V8 heap limit |
Source: openclaw.plugin.json:45-60
Session Cleanup (Pressure Cleanup)
The /pressure/cleanup endpoint provides session maintenance with dry-run capability:
POST /pressure/cleanup
Authorization: Bearer <accessKey>
{
"dryRun": true,
"closeEmptySessions": true,
"maxSessions": 100
}
Response:
{
"ok": true,
"dryRun": true,
"before": { "sessions": 50, "tabs": 120 },
"after": { "sessions": 45, "tabs": 110 },
"candidates": 5,
"closed": [...],
"preserved": { "sessionId1": 3, "sessionId2": 1 }
}
Source: server.js:200-260
Cookie Import API
Endpoint: POST /sessions/{userId}/cookies
Imports cookies into an existing session's browser context.
Authentication: Requires Authorization: Bearer <apiKey> header OR CAMOFOX_API_KEY configured.
Source: lib/auth.js:20-25
Request Body:
{
"cookies": [
{
"name": "session_id",
"value": "abc123",
"domain": ".example.com",
"path": "/",
"expires": 1735689600,
"httpOnly": true,
"secure": true
}
]
}
Response:
{
"ok": true,
"imported": 1
}
OpenClaw Plugin Integration
The OpenClaw plugin provides a camofox_import_cookies tool for AI agents:
parameters: {
cookiesPath: { type: "string", description: "Path to Netscape-format cookies.txt file" },
domainSuffix: { type: "string", description: "Only import cookies whose domain ends with this suffix" },
}
Source: plugin.ts:180-210
Usage Example:
{
"tool": "camofox_import_cookies",
"params": {
"cookiesPath": "sessions/user1/cookies.txt",
"domainSuffix": ".example.com"
}
}
Security
API Key Authentication
Cookie import endpoints require authentication via Bearer token:
if (config.apiKey && req.method === 'POST' && /^\/sessions\/[^/]+\/cookies$/.test(req.path)) return next();
Source: lib/auth.js:15-18
Timing-Safe Comparison
Token comparison uses timingSafeCompare() to prevent timing attacks:
const match = auth.match(/^Bearer\s+(.+)$/i);
const token = match ? match[1]?.trim() : null;
if (!token || !timingSafeCompare(token, config.accessKey)) {
return res.status(401).set('WWW-Authenticate', 'Bearer realm="camofox"').json({ error: 'Unauthorized' });
}
Source: lib/auth.js:26-35
Path Traversal Protection
Cookie file paths are validated to prevent directory traversal attacks:
const resolved = path.resolve(cookiesDir, cookiesPath);
if (!resolved.startsWith(cookiesDir + path.sep)) {
throw new Error('cookiesPath must be a relative path within the cookies directory');
}
Source: lib/cookies.js:58-62
Configuration Security
| Environment Variable | Description | Security Note |
|---|---|---|
CAMOFOX_API_KEY | Secret for cookie import | Must be set for cookie operations |
CAMOFOX_ACCESS_KEY | Global route authentication | Protects all API endpoints |
Source: openclaw.plugin.json:55-65
Plugin Development
Mutating Session Options
Plugins can modify browser context options before session creation:
// In plugin register(app, ctx) function
ctx.on('session:creating', ({ userId, contextOptions }) => {
// Add proxy, modify userAgent, set viewport, etc.
contextOptions.proxyServer = 'http://proxy.example.com:8080';
});
Source: lib/plugins.js:28-30
Monitoring Cookie Operations
Track cookie imports and exports:
ctx.on('session:cookies:import', ({ userId, count }) => {
console.log(`User ${userId} imported ${count} cookies`);
});
ctx.on('session:storage:export', ({ userId }) => {
console.log(`User ${userId} requested storage export`);
});
Troubleshooting
Common Issues
| Issue | Cause | Solution |
|---|---|---|
| Cookie import fails | CAMOFOX_API_KEY not set | Set environment variable on both server and plugin |
| Path traversal error | Invalid cookiesPath | Use relative paths within cookiesDir |
| Session expired | Idle timeout exceeded | Increase sessionTimeoutMs or keep session active |
| 401 Unauthorized | Invalid/missing token | Verify Bearer token matches CAMOFOX_ACCESS_KEY |
Debugging Cookie Imports
Enable verbose logging to trace cookie operations:
// Check server logs for entries like:
log('info', 'pressure cleanup', { dryRun, beforeTabs, afterTabs, candidates, closed, preserved });
Source: server.js:230-240
Related Documentation
- AGENTS.md — OpenAPI specification guidelines
- OpenAPI Docs — Interactive API documentation (when server running)
- lib/plugins.js — Full plugin event reference
Source: https://github.com/jo-inc/camofox-browser / Human Manual
Doramagic Pitfall Log
Source-linked risks stay visible on the manual page so the preview does not read like a recommendation.
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
Doramagic Pitfall Log
Found 37 structured pitfall item(s), including 3 high/blocking item(s). Top priority: Configuration risk - Configuration risk requires verification.
1. Configuration risk: Configuration risk requires verification
- Severity: high
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | cevd_509e4f60bc5b4f59b2f30d8e940b435f | https://github.com/jo-inc/camofox-browser/issues/4493
2. Configuration risk: Configuration risk requires verification
- Severity: high
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | cevd_9b0d643d129c40bba9029a91908b6df8 | https://github.com/jo-inc/camofox-browser/issues/4495
3. Maintenance risk: Maintenance risk requires verification
- Severity: high
- Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | cevd_b64265a647de4b7b87d3c451230683a7 | https://github.com/jo-inc/camofox-browser/issues/4483
4. Configuration risk: Configuration risk requires verification
- Severity: medium
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | cevd_bc5774adce304ebcb8ccd6511fcf24df | https://github.com/jo-inc/camofox-browser/issues/4859
5. Configuration risk: Configuration risk requires verification
- Severity: medium
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | cevd_66b048f511104e1f9c71f1ab5bb753ad | https://github.com/jo-inc/camofox-browser/issues/4854
6. Configuration risk: Configuration risk requires verification
- Severity: medium
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | cevd_34506ec241e243b79da0f0ffc55849da | https://github.com/jo-inc/camofox-browser/issues/4858
7. Configuration risk: Configuration risk requires verification
- Severity: medium
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | cevd_ec01f035f6474fde8b54a78998fcf0e8 | https://github.com/jo-inc/camofox-browser/issues/4851
8. Configuration risk: Configuration risk requires verification
- Severity: medium
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | cevd_ea7990b603954ff98742c9307eaa3873 | https://github.com/jo-inc/camofox-browser/issues/4856
9. Configuration risk: Configuration risk requires verification
- Severity: medium
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | cevd_79456dd0004342acba398cdc03c58748 | https://github.com/jo-inc/camofox-browser/issues/4852
10. Configuration risk: Configuration risk requires verification
- Severity: medium
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | cevd_d5beb836c1824c75b5eedfce488baaeb | https://github.com/jo-inc/camofox-browser/issues/4853
11. Configuration risk: Configuration risk requires verification
- Severity: medium
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | cevd_59fb2f68349c474fb6875fd66c694591 | https://github.com/jo-inc/camofox-browser/issues/4855
12. Configuration risk: Configuration risk requires verification
- Severity: medium
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | cevd_c4c3a2b1654f4286b1c91f91aad1713e | https://github.com/jo-inc/camofox-browser/issues/4863
Source: Doramagic discovery, validation, and Project Pack records
Community Discussion Evidence
These external discussion links are review inputs, not standalone proof that the project is production-ready.
Count of project-level external discussion links exposed on this manual page.
Open the linked issues or discussions before treating the pack as ready for your environment.
Community Discussion Evidence
Doramagic exposes project-level community discussion separately from official documentation. Review these links before using camofox-browser with real data or production workflows.
- [[90cfc6c8] stuck:event-loop: Event loop stalled for 17s (threshold: 5s)](https://github.com/jo-inc/camofox-browser/issues/4863) - github / github_issue
- [[988be9c4] stuck:event-loop: Event loop stalled for 18s (threshold: 5s)](https://github.com/jo-inc/camofox-browser/issues/4862) - github / github_issue
- [[90cfc6c8] stuck:event-loop: Event loop stalled for 17s (threshold: 5s)](https://github.com/jo-inc/camofox-browser/issues/4861) - github / github_issue
- [[0d148b4c] stuck:event-loop: Event loop stalled for 7s (threshold: 5s)](https://github.com/jo-inc/camofox-browser/issues/4493) - github / github_issue
- [[5cf7d100] stuck:event-loop: Event loop stalled for 22s (threshold: 5s)](https://github.com/jo-inc/camofox-browser/issues/4483) - github / github_issue
- [[c665094c] stuck:event-loop: Event loop stalled for 74s (threshold: 5s)](https://github.com/jo-inc/camofox-browser/issues/4860) - github / github_issue
- [[1f7f8070] stuck:event-loop: Event loop stalled for 6s (threshold: 5s)](https://github.com/jo-inc/camofox-browser/issues/4859) - github / github_issue
- [[43752418] stuck:event-loop: Event loop stalled for 46s (threshold: 5s)](https://github.com/jo-inc/camofox-browser/issues/4858) - github / github_issue
- [[50ffc888] stuck:event-loop: Event loop stalled for 12s (threshold: 5s)](https://github.com/jo-inc/camofox-browser/issues/4495) - github / github_issue
- [[1f7f8070] stuck:event-loop: Event loop stalled for 6s (threshold: 5s)](https://github.com/jo-inc/camofox-browser/issues/4857) - github / github_issue
- [[674b19b0] stuck:event-loop: Event loop stalled for 23s (threshold: 5s)](https://github.com/jo-inc/camofox-browser/issues/4856) - github / github_issue
- [[8ffefba3] stuck:event-loop: Event loop stalled for 55s (threshold: 5s)](https://github.com/jo-inc/camofox-browser/issues/4855) - github / github_issue
Source: Project Pack community evidence and pitfall evidence