# https://github.com/jo-inc/camofox-browser Project Manual

Generated at: 2026-05-30 22:45:40 UTC

## Table of Contents

- [Overview](#overview)
- [Quick Start Guide](#quickstart)
- [System Architecture](#architecture)
- [Session & Tab Management](#session-management)
- [API Reference](#api-reference)
- [Search Macros](#search-macros)
- [Deployment Guide](#deployment)
- [Plugin System](#plugins)
- [Configuration Reference](#configuration)
- [Cookie & Session Persistence](#cookie-management)

<a id='overview'></a>

## Overview

### Related Pages

Related topics: [Quick Start Guide](#quickstart), [System Architecture](#architecture)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [server.js](https://github.com/jo-inc/camofox-browser/blob/main/server.js) - Main Express server with route handlers
- [AGENTS.md](https://github.com/jo-inc/camofox-browser/blob/main/AGENTS.md) - Agent API documentation and event system
- [lib/openapi.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/openapi.js) - OpenAPI specification generation
- [lib/plugins.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/plugins.js) - Plugin system implementation
- [lib/reporter.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/reporter.js) - Crash and hang reporting
- [lib/extract.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/extract.js) - Schema validation utilities
- [lib/snapshot.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/snapshot.js) - Page snapshot functionality
- [scripts/plugin.js](https://github.com/jo-inc/camofox-browser/blob/main/scripts/plugin.js) - Plugin management CLI
</details>

# 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.

```mermaid
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](https://github.com/Surnet/swagger-jsdoc). Generated output is served at:

- `GET /openapi.json` - Machine-readable OpenAPI 3.0.3 JSON
- `GET /docs` - Interactive three-panel UI via swagger-stripey

```mermaid
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:

```bash
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

```javascript
{
  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

```javascript
{
  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

```javascript
{
  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

```bash
# 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 `properties` object
- 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

```json
{
  "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

```json
{
  "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](https://github.com/apps/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)

```bash
npx @askjo/camofox-browser
```

Or install globally:

```bash
npm install -g @askjo/camofox-browser
camofox-browser
```

### Docker

```bash
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 |

---

<a id='quickstart'></a>

## Quick Start Guide

### Related Pages

Related topics: [Overview](#overview), [Deployment Guide](#deployment)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [package.json](https://github.com/jo-inc/camofox-browser/blob/main/package.json)
- [server.js](https://github.com/jo-inc/camofox-browser/blob/main/server.js)
- [lib/openapi.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/openapi.js)
- [lib/plugins.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/plugins.js)
- [scripts/plugin.js](https://github.com/jo-inc/camofox-browser/blob/main/scripts/plugin.js)
- [lib/snapshot.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/snapshot.js)
- [AGENTS.md](https://github.com/jo-inc/camofox-browser/blob/main/AGENTS.md)
</details>

# 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](https://github.com/nicholasgonzalezsc/automation-hub) under the hood
- **Python 3.8+** (for Camoufox browser installation)
- **npm or yarn** for package management

## Installation

### Option 1: npm (Recommended for CLI Usage)

```bash
# Install globally
npm install -g @askjo/camofox-browser

# Run directly
camofox-browser
```

### Option 2: From Source

```bash
# 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

```bash
# 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](https://github.com/jo-inc/camofox-browser/issues/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

```bash
node server.js
```

### With Custom Configuration

```bash
PORT=8080 HOST=127.0.0.1 node server.js
```

### Using the Startup Script

```bash
./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-Key` header
- `userId` in 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

```mermaid
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

```bash
curl -X POST http://localhost:9377/sessions \
  -H "Content-Type: application/json" \
  -d '{"userId": "my-user-123"}'
```

Response:
```json
{
  "ok": true,
  "userId": "my-user-123",
  "tabs": []
}
```

### 2. Navigate to a Website

```bash
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

```bash
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

```bash
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

```bash
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

```bash
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

```bash
# 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](https://github.com/jo-inc/camofox-browser/blob/main/lib/plugins.js)

## Health Monitoring

### Health Endpoint

```bash
curl http://localhost:9377/health
```

Response:
```json
{
  "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](https://github.com/jo-inc/camofox-browser/issues?q=stuck%3Aevent-loop)

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:

```bash
npm run generate-openapi
```

Source: [AGENTS.md:45-80](https://github.com/jo-inc/camofox-browser/blob/main/AGENTS.md)

## Common Issues

### Port Already in Use

```bash
Error: listen EADDRINUSE :::9377
```

**Solution**: Either stop the existing process using port 9377 or start on a different port:
```bash
PORT=9378 node server.js
```

### Browser Launch Failure

Ensure Playwright browsers are installed:
```bash
npx playwright install
```

### Event Loop Stalls

If you encounter event loop stall warnings:
1. Check for heavy JavaScript execution in page context
2. Verify network connectivity is stable
3. Consider increasing the timeout thresholds in configuration

## Next Steps

- Explore the full [API Reference](http://localhost:9377/docs) at `/docs`
- Review [AGENTS.md](AGENTS.md) for OpenAPI specification guidelines
- Check the [plugin system documentation](lib/plugins.js) for extending functionality
- Review [community issues](https://github.com/jo-inc/camofox-browser/issues) for known limitations

---

<a id='architecture'></a>

## System Architecture

### Related Pages

Related topics: [Overview](#overview), [Session & Tab Management](#session-management)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [server.js](https://github.com/jo-inc/camofox-browser/blob/main/server.js)
- [lib/plugins.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/plugins.js)
- [lib/openapi.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/openapi.js)
- [plugin.ts](https://github.com/jo-inc/camofox-browser/blob/main/plugin.ts)
- [scripts/plugin.js](https://github.com/jo-inc/camofox-browser/blob/main/scripts/plugin.js)
- [lib/snapshot.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/snapshot.js)
- [lib/extract.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/extract.js)
- [plugin.js](https://github.com/jo-inc/camofox-browser/blob/main/plugin.js)
- [AGENTS.md](https://github.com/jo-inc/camofox-browser/blob/main/AGENTS.md)
</details>

# 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

```mermaid
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 --> Browser
```

## Core 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]()()

```mermaid
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 --> D
```

## Session Management

### Session Architecture

Sessions provide user isolation and state management. Each session maintains browser contexts, tab groups, and access timestamps. Source: [server.js]()()

```mermaid
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]()()

```javascript
// 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]()()

```mermaid
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]()()

```javascript
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]()

```mermaid
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]
    end
```

### Plugin 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]()

```typescript
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]()

```mermaid
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]()

```javascript
/**
 * @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 | oss@askjo.ai |
| 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]()

```javascript
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]()()

```json
{
  "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

```bash
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

```bash
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:

1. Request ID injection
2. Body parsing
3. Authentication (when enabled)
4. Route-specific validation
5. Handler execution

### Lifecycle Hooks

Mutating hooks pass objects by reference, allowing plugins to modify behavior:

- `browser:launching` - Modify launch options before browser starts
- `session: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:

1. **HTTP Layer**: Express server with REST API, OpenAPI documentation
2. **Session Layer**: User isolation, context management, idle reaping
3. **Tab Layer**: Page lifecycle, locking, state tracking
4. **Plugin Layer**: 29 events, tool registration, CLI management
5. **Browser Layer**: camoufox anti-detection engine

This design enables extensibility through plugins while maintaining robust core functionality for browser automation tasks.

---

<a id='session-management'></a>

## Session & Tab Management

### Related Pages

Related topics: [System Architecture](#architecture), [Cookie & Session Persistence](#cookie-management)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [server.js](https://github.com/jo-inc/camofox-browser/blob/main/server.js) - Main server with tab/session API routes
- [lib/plugins.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/plugins.js) - Plugin event system and lifecycle hooks
- [lib/openapi.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/openapi.js) - OpenAPI specification generation
- [lib/request-utils.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/request-utils.js) - Error classification and request utilities
- [plugin.ts](https://github.com/jo-inc/camofox-browser/blob/main/plugin.ts) - TypeScript plugin tools
- [plugin.js](https://github.com/jo-inc/camofox-browser/blob/main/plugin.js) - JavaScript plugin tools
</details>

# 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.

```mermaid
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| I
```

### Key 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]()

---

## Sessions

A session represents a isolated browser context belonging to a single user (`userId`). Sessions persist browser state across tab operations and can survive tab closures until they expire from inactivity.

### Session Lifecycle

Sessions follow a predictable lifecycle managed by the session reaper:

```mermaid
stateDiagram-v2
    [*] --> Active : First API request
    Active --> Active : Regular activity
    Active --> Expiring : Inactivity timeout reached
    Expiring --> Active : Activity detected
    Expiring --> Destroyed : Grace period elapsed
    Destroyed --> [*]
```

### Session Configuration

| Parameter | Default | Description |
|-----------|---------|-------------|
| `sessionTimeoutMs` | 1,800,000 (30 min) | Session inactivity timeout |
| `browserIdleTimeoutMs` | 300,000 (5 min) | Kill browser after this idle time |
| `maxTabsPerSession` | 10 | Maximum tabs per user session |
| `maxConcurrentSessions` | Configured | Global session limit |

Source: [openclaw.plugin.json:1-50]()

### Session Data Model

Each session object contains:

```typescript
interface Session {
  userId: string;
  context: BrowserContext;           // Playwright browser context
  tabGroups: Map<listItemId, Map<tabId, TabState>>;
  lastAccess: number;                // Timestamp of last activity
  createdAt: number;
}
```

Sessions are stored in the global `sessions` Map, keyed by normalized `userId`. Source: [server.js:200-300]()

---

## Tabs

Tabs are individual page instances within a session's browser context. Each tab maintains state including the Playwright `Page` object, navigation tracking, tool call counts, and error metrics.

### TabState Object

```typescript
interface TabState {
  page: Page;                         // Playwright page instance
  tabId: string;                      // Unique tab identifier
  group: Map<tabId, TabState>;        // Reference to parent group
  listItemId: string;                 // Associated list item
  toolCalls: number;                 // Total API calls made
  consecutiveTimeouts: number;        // Timeout tracking
  consecutiveFailures: number;        // Failure tracking
  navigateAbort: AbortController;     // Navigation cancellation
  visitedUrls: string[];              // Navigation history
  downloadCount: number;             // Download events count
  lastAccess: number;                 // Timestamp
}
```

Source: [server.js:300-400]()

### Tab Lifecycle Events

Plugins can hook into tab lifecycle via the event system:

| Event | Payload | Description |
|-------|---------|-------------|
| `tab:created` | `{ userId, tabId, page, url }` | New tab opened |
| `tab:navigated` | `{ userId, tabId, url, prevUrl }` | Navigation completed |
| `tab:destroyed` | `{ userId, tabId, reason }` | Tab closed |
| `tab:recycled` | `{ userId, tabId }` | Tab reused for new session |
| `tab:error` | `{ userId, tabId, error }` | Tab encountered error |

Source: [lib/plugins.js:1-100]()

---

## Tab Locking & Concurrency Control

To prevent race conditions during concurrent requests targeting the same tab, camofox implements a per-tab locking mechanism.

### Lock Mechanism

```mermaid
sequenceDiagram
    participant Client1
    participant Client2
    participant TabLock
    participant TabHandler
    
    Client1->>TabLock: Acquire(tabId)
    TabLock->>TabHandler: Execute operation
    TabHandler-->>TabLock: Complete
    TabLock->>Client1: Release
    
    Client2->>TabLock: Acquire(tabId)
    Note over TabLock: Queued until released
    TabLock->>TabHandler: Execute operation
    TabHandler-->>TabLock: Release
    TabLock->>Client2: Complete
```

### Lock Configuration

| Setting | Default | Description |
|---------|---------|-------------|
| Lock timeout | Per-route | Max wait for lock acquisition |
| Queue depth metric | Enabled | Tracks pending operations |

Operations protected by tab locks:
- `click` - Element interaction
- `type` - Text input
- `press` - Keyboard events
- `navigate` - URL navigation
- `evaluate` - JavaScript execution

Source: [server.js:400-500]()

---

## Tab Management API

### Create Tab

```http
POST /tabs
```

Creates a new tab within the user's session. If no session exists, one is created automatically.

**Response:**
```json
{
  "tabId": "string",
  "targetId": "string",
  "url": "string"
}
```

### List Tabs

```http
GET /tabs?userId={userId}
```

Returns all active tabs for a user session:

| Field | Type | Description |
|-------|------|-------------|
| `tabId` | string | Unique tab identifier |
| `targetId` | string | Playwright target ID |
| `url` | string | Current page URL |
| `title` | string | Page title |
| `listItemId` | string | Associated list item |

Source: [server.js:500-600]()

### Close Tab

```http
DELETE /tabs/{tabId}
```

Gracefully closes a tab, releasing all associated resources:

1. Abort any pending navigation
2. Clear tab downloads
3. Close Playwright page
4. Remove from tab group
5. Delete tab lock
6. Update metrics

```javascript
if (found.tabState.navigateAbort) found.tabState.navigateAbort.abort();
await clearTabDownloads(found.tabState);
await safePageClose(found.tabState.page);
found.group.delete(req.params.tabId);
{ const _l = tabLocks.get(req.params.tabId); if (_l) _l.drain(); tabLocks.delete(req.params.tabId); }
```

Source: [server.js:600-700]()

### Tab Statistics

```http
GET /tabs/{tabId}/stats?userId={userId}
```

Returns tab metadata including:

| Field | Type | Description |
|-------|------|-------------|
| `tabId` | string | Tab identifier |
| `url` | string | Current URL |
| `toolCalls` | integer | Total API calls |
| `visitedUrls` | array | Navigation history |
| `downloadCount` | integer | Downloads triggered |
| `consecutiveFailures` | integer | Failure streak |

Source: [server.js:700-800]()

---

## Navigation

### Navigate Endpoint

```http
POST /tabs/{tabId}/navigate
```

**Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `userId` | string | Yes | Session owner |
| `url` | string | No | Direct URL |
| `macro` | string | No | Search macro (e.g., `@google_search`) |
| `query` | string | No | Search query for macro |
| `sessionKey` | string | No | Session resolution key |
| `listItemId` | string | No | List item context |

**Supported Macros:**

| Macro | Search Engine |
|-------|---------------|
| `@google_search` | Google |
| `@youtube_search` | YouTube |
| `@amazon_search` | Amazon |
| `@reddit_search` | Reddit |
| `@wikipedia_search` | Wikipedia |
| `@twitter_search` | Twitter/X |
| `@yelp_search` | Yelp |
| `@spotify_search` | Spotify |
| `@netflix_search` | Netflix |
| `@linkedin_search` | LinkedIn |
| `@instagram_search` | Instagram |
| `@tiktok_search` | TikTok |
| `@twitch_search` | Twitch |

Source: [plugin.ts:1-100]()

### Macro Resolution

Macros resolve to search URLs and are particularly relevant for avoiding bot detection since they simulate natural search behavior. Source: [server.js:100-200]()

---

## Pressure Cleanup

The pressure cleanup system automatically reclaims resources from idle sessions:

```http
POST /pressure/cleanup
```

**Request Body:**

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `dryRun` | boolean | false | Preview without closing |
| `aggressive` | boolean | false | Close sessions with recent activity |
| `closeEmpty` | boolean | true | Close zero-tab sessions |

**Response:**

```json
{
  "ok": true,
  "dryRun": false,
  "before": { "sessions": 10, "tabs": 25 },
  "after": { "sessions": 8, "tabs": 20 },
  "candidates": 12,
  "closed": [...],
  "preserved": {...}
}
```

Source: [server.js:800-900]()

---

## Error Classification

The system classifies errors by category for metrics and handling:

| Category | Triggers |
|----------|----------|
| `timeout` | Timeout exceeded errors |
| `session_limit` | Maximum concurrent sessions |
| `tab_limit` | Maximum tabs per session or global |
| `concurrency_limit` | Concurrency threshold reached |
| `proxy` | Proxy connection failures |
| `browser_launch` | Launch timeout or failure |
| `click_intercepted` | Element intercepts pointer events |
| `element_error` | Element not visible or not an input |
| `invalid_url` | Blocked URL scheme or invalid URL |
| `network` | Network errors (net::, ERR_) |
| `nav_aborted` | Navigation aborted |

Source: [lib/request-utils.js:1-50]()

---

## Interaction Operations

### Click

```http
POST /tabs/{tabId}/click
```

Clicks an element identified by `ref` or `selector`.

### Type

```http
POST /tabs/{tabId}/type
```

Types text into a focused element:

| Parameter | Type | Description |
|-----------|------|-------------|
| `text` | string | Text to type |
| `clear` | boolean | Clear field before typing |
| `submit` | boolean | Press Enter after typing |

### Press Key

```http
POST /tabs/{tabId}/press
```

Presses a keyboard key (e.g., `Enter`, `Escape`, `Tab`).

### Scroll

```http
POST /tabs/{tabId}/scroll
```

Scrolls the page or element:

| Parameter | Type | Description |
|-----------|------|-------------|
| `direction` | string | `up`, `down`, `left`, `right` |
| `amount` | integer | Pixels to scroll |

Source: [server.js:100-300]()

---

## Content Extraction

### Evaluate JavaScript

```http
POST /tabs/{tabId}/evaluate
```

Executes arbitrary JavaScript in the page context and returns the result. Useful for custom data extraction or page manipulation.

### Extract Structured Data

```http
POST /tabs/{tabId}/extract
```

Extracts structured data using JSON Schema with `x-ref` hints pointing to snapshot element refs:

```json
{
  "schema": {
    "type": "object",
    "properties": {
      "title": { "type": "string", "x-ref": "e1" },
      "price": { "type": "number", "x-ref": "e2" }
    }
  }
}
```

Requires calling `GET /tabs/{tabId}/snapshot` first to populate the ref table. Source: [server.js:900-1000]()

### Page Images

```http
GET /tabs/{tabId}/images
```

**Query Parameters:**

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `includeData` | boolean | false | Include base64 image data |
| `maxBytes` | integer | 512KB | Max data size per image |
| `limit` | integer | 8 | Max images returned (max 20) |

---

## Metrics & Monitoring

The session/tab system exposes Prometheus metrics:

| Metric | Type | Description |
|--------|------|-------------|
| `tabLockQueueDepth` | Gauge | Operations waiting for tab locks |
| `tabLockTimeoutsTotal` | Counter | Lock acquisition timeouts |
| `activeTabsGauge` | Gauge | Current active tabs |
| `failuresTotal` | Counter | Operation failures by type |
| `browserRestartsTotal` | Counter | Browser restart count |
| `tabsDestroyedTotal` | Counter | Tabs closed |
| `sessionsExpiredTotal` | Counter | Sessions reaped |
| `tabsReapedTotal` | Counter | Tabs recycled |
| `tabsRecycledTotal` | Counter | Tab reuse count |

Source: [server.js:350-400]()

---

## Known Issues

### Event Loop Stalls

The community has reported multiple event loop stall incidents where the Node.js event loop stalls for extended periods (17s-74s) exceeding the 5s threshold. These stalls typically occur during:

- Long-running navigation operations
- Browser context operations
- Extended idle periods with no active tabs

All reported cases show zero browser contexts and zero active tabs at the time of detection, suggesting the stalls may occur during cleanup or browser shutdown operations.

**Related Issues:** #4863, #4862, #4861, #4860, #4859, #4858, #4857, #4856, #4855, #4495, #4493, #4483

---

## Plugin Integration

Plugins can interact with the session/tab system through the plugin API:

```typescript
api.registerTool((ctx) => ({
  name: "camofox_list_tabs",
  async execute(_id, _params) {
    const result = await fetchApi(baseUrl, `/tabs?userId=${userId}`);
    return toToolResult(result);
  },
}));
```

### Available Plugin Tools

| Tool | Description |
|------|-------------|
| `camofox_navigate` | Navigate to URL or search |
| `camofox_click` | Click an element |
| `camofox_type` | Type text into field |
| `camofox_scroll` | Scroll page |
| `camofox_evaluate` | Run JavaScript |
| `camofox_screenshot` | Capture screenshot |
| `camofox_snapshot` | Get accessibility tree |
| `camofox_list_tabs` | List all tabs |
| `camofox_import_cookies` | Import cookies |

Source: [plugin.ts:100-300]()

---

<a id='api-reference'></a>

## API Reference

### Related Pages

Related topics: [Search Macros](#search-macros), [Configuration Reference](#configuration)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [server.js](https://github.com/jo-inc/camofox-browser/blob/main/server.js)
- [lib/openapi.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/openapi.js)
- [AGENTS.md](https://github.com/jo-inc/camofox-browser/blob/main/AGENTS.md)
- [lib/snapshot.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/snapshot.js)
- [scripts/generate-openapi.js](https://github.com/jo-inc/camofox-browser/blob/main/scripts/generate-openapi.js)
</details>

# 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:

```bash
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

```http
DELETE /tabs/:tabId?userId=<userId>
```

Response:
```json
{ "ok": true }
```

When a tab is closed, the server:
1. Aborts any pending navigation
2. Clears associated downloads
3. Closes the page safely with timeout guard
4. 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

```json
{
  "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

```json
{
  "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

```json
{
  "userId": "string",
  "ref": "e1",
  "selector": "input[name='email']",
  "text": "user@example.com",
  "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

```json
{
  "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:
```json
{
  "text": "...",
  "truncated": true,
  "totalChars": 25000,
  "offset": 5000,
  "hasMore": true,
  "nextOffset": 10000
}
```

Source: [lib/snapshot.js:1-20]()

#### Extract Structured Data

```json
{
  "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

```json
{
  "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

```http
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

```json
{
  "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:

```json
{
  "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:

```json
{ "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:

```bash
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:

```javascript
// 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]()

---

<a id='search-macros'></a>

## Search Macros

### Related Pages

Related topics: [API Reference](#api-reference)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [lib/macros.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/macros.js)
- [server.js](https://github.com/jo-inc/camofox-browser/blob/main/server.js)
- [plugin.ts](https://github.com/jo-inc/camofox-browser/blob/main/plugin.ts)
- [plugin.js](https://github.com/jo-inc/camofox-browser/blob/main/plugin.js)
- [AGENTS.md](https://github.com/jo-inc/camofox-browser/blob/main/AGENTS.md)
</details>

# 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` + `query` parameter pattern across all navigation calls

Source: [lib/macros.js:1-20](https://github.com/jo-inc/camofox-browser/blob/main/lib/macros.js)

---

## Supported Macros

The following search macros are available in the current release:

| Macro | Platform | URL Pattern |
|-------|----------|-------------|
| `@google_search` | Google | `https://www.google.com/search?q={query}` |
| `@youtube_search` | YouTube | `https://www.youtube.com/results?search_query={query}` |
| `@amazon_search` | Amazon | `https://www.amazon.com/s?k={query}` |
| `@reddit_search` | Reddit | `https://www.reddit.com/search/?q={query}` |
| `@wikipedia_search` | Wikipedia | `https://en.wikipedia.org/w/index.php?search={query}` |
| `@twitter_search` | Twitter/X | `https://twitter.com/search?q={query}` |
| `@yelp_search` | Yelp | `https://www.yelp.com/search?find_desc={query}` |
| `@linkedin_search` | LinkedIn | `https://www.linkedin.com/search/results/all/?keywords={query}` |
| `@instagram_search` | Instagram | `https://www.instagram.com/explore/tags/{query}` |
| `@tiktok_search` | TikTok | `https://www.tiktok.com/search?q={query}` |
| `@twitch_search` | Twitch | `https://www.twitch.tv/search?term={query}` |
| `@spotify_search` | Spotify | `https://open.spotify.com/search/{query}` |
| `@netflix_search` | Netflix | `https://www.netflix.com/search?q={query}` |

Source: [lib/macros.js:1-20](https://github.com/jo-inc/camofox-browser/blob/main/lib/macros.js)

---

## Architecture

### Macro Resolution Flow

```mermaid
graph TD
    A[Navigation Request] --> B{Includes macro?}
    B -->|Yes| C[expandMacro called]
    B -->|No| D[Use raw URL]
    C --> E{Macro Found?}
    E -->|Yes| F[Generate Search URL]
    E -->|No| G[Return null]
    F --> H[Navigate to URL]
    G --> I[Error: Invalid macro]
    D --> H
    H --> J[Page Loaded]
    
    style G fill:#ffcccc
    style I fill:#ffcccc
```

### Component Interactions

```mermaid
graph LR
    A[plugin.ts] -->|tool definition| B[Macro Enum]
    C[plugin.js] -->|tool definition| B
    D[server.js] -->|navigate handler| E[lib/macros.js]
    F[lib/macros.js] -->|MACROS object| E
    E -->|expanded URL| D
    G[AGENTS.md] -->|documentation| H[User Reference]
    
    style B fill:#e1f5fe
    style E fill:#fff3e0
```

---

## API Reference

### Navigate Endpoint with Macros

**Endpoint:** `POST /tabs/:tabId/navigate`

**Request Body Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `userId` | `string` | Yes | User identifier for session isolation |
| `tabId` | `string` | Yes | Target tab identifier |
| `macro` | `string` | No* | Search macro (e.g., `@google_search`) |
| `query` | `string` | No* | Search query for macro expansion |
| `url` | `string` | No* | Direct URL to navigate (cannot use with `macro`) |
| `sessionKey` | `string` | No | Groups tabs by conversation |
| `listItemId` | `string` | No | Legacy session grouping |

*Either `macro` + `query` or `url` must be provided.

**Macro Parameter Enum Values:**

```typescript
"@google_search" | "@youtube_search" | "@amazon_search" | 
"@reddit_search" | "@wikipedia_search" | "@twitter_search" | 
"@yelp_search" | "@spotify_search" | "@netflix_search" | 
"@linkedin_search" | "@instagram_search" | "@tiktok_search" | 
"@twitch_search"
```

Source: [server.js:navigate-handler](https://github.com/jo-inc/camofox-browser/blob/main/server.js)
Source: [plugin.ts:macro-enum](https://github.com/jo-inc/camofox-browser/blob/main/plugin.ts)

---

## Implementation Details

### Macro Definition Format

Each macro is defined as a function that takes a query string and returns a formatted URL:

```javascript
const MACROS = {
  '@google_search': (query) => 
    `https://www.google.com/search?q=${encodeURIComponent(query || '')}`,
  '@youtube_search': (query) => 
    `https://www.youtube.com/results?search_query=${encodeURIComponent(query || '')}`,
  '@linkedin_search': (query) => 
    `https://www.linkedin.com/search/results/all/?keywords=${encodeURIComponent(query || '')}`,
  // ... additional macros
};
```

Source: [lib/macros.js:1-20](https://github.com/jo-inc/camofox-browser/blob/main/lib/macros.js)

### Core Functions

#### `expandMacro(macro, query)`

Expands a macro name and query into a search URL.

**Parameters:**
| Parameter | Type | Description |
|-----------|------|-------------|
| `macro` | `string` | The macro name (e.g., `@google_search`) |
| `query` | `string` | The search query string |

**Returns:** `string | null` — The constructed URL, or `null` if the macro is not found.

**Behavior:**
1. Looks up the macro function in the `MACROS` object
2. If found, calls the function with the query
3. If not found, returns `null`

```javascript
function expandMacro(macro, query) {
  const macroFn = MACROS[macro];
  return macroFn ? macroFn(query) : null;
}
```

Source: [lib/macros.js:22-25](https://github.com/jo-inc/camofox-browser/blob/main/lib/macros.js)

#### `getSupportedMacros()`

Returns an array of all supported macro names.

**Returns:** `string[]` — Array of macro names including the `@` prefix.

```javascript
function getSupportedMacros() {
  return Object.keys(MACROS);
}
```

Source: [lib/macros.js:27-29](https://github.com/jo-inc/camofox-browser/blob/main/lib/macros.js)

### Module Exports

```javascript
export {
  expandMacro,
  getSupportedMacros,
  MACROS
};
```

Source: [lib/macros.js:31-33](https://github.com/jo-inc/camofox-browser/blob/main/lib/macros.js)

---

## Usage Examples

### Via REST API

```bash
# Google Search
curl -X POST http://localhost:9377/tabs/abc123/navigate \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "agent1",
    "macro": "@google_search",
    "query": "web scraping best practices"
  }'

# YouTube Search
curl -X POST http://localhost:9377/tabs/abc123/navigate \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "agent1",
    "macro": "@youtube_search",
    "query": "Node.js tutorial"
  }'

# LinkedIn Search
curl -X POST http://localhost:9377/tabs/abc123/navigate \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "agent1",
    "macro": "@linkedin_search",
    "query": "software engineer"
  }'
```

### Via Plugin Tools

When using the camofox plugin with AI agents, specify the macro and query:

```json
{
  "name": "camofox_navigate",
  "parameters": {
    "tabId": "tab-001",
    "macro": "@reddit_search",
    "query": "programming memes"
  }
}
```

Source: [AGENTS.md:search-macros-section](https://github.com/jo-inc/camofox-browser/blob/main/AGENTS.md)

---

## Error Handling

### Invalid Macro

If an unrecognized macro is provided, the navigation will fail with an appropriate error:

| Error Condition | Response Code | Message |
|-----------------|---------------|---------|
| Unknown macro | 400 | Macro expansion returned null |
| Missing query | 400 | Query required for macro navigation |
| Empty macro | 400 | Macro name cannot be empty |

### Query Encoding

Special characters in queries are automatically URL-encoded by the macro functions using `encodeURIComponent()`. This ensures:

- Spaces become `%20`
- Ampersands become `%26`
- Question marks become `%3F`
- Unicode characters are properly escaped

---

## Integration Points

### Plugin System

The plugin system exposes macros through the `camofox_navigate` tool definition:

```typescript
// From plugin.ts
parameters: {
  macro: {
    type: "string",
    description: "Search macro (e.g., @google_search, @youtube_search)",
    enum: ["@google_search", "@youtube_search", ...]
  },
  query: { 
    type: "string", 
    description: "Search query (when using macro)" 
  },
}
```

### Server Routes

The server handles macro expansion in the navigate route handler:

```javascript
const resolvedSessionKey = sessionKey || listItemId || found;
const resolvedUrl = macro 
  ? expandMacro(macro, query) 
  : url;
```

Source: [server.js:navigate-handler](https://github.com/jo-inc/camofox-browser/blob/main/server.js)

---

## Extending Macros

To add a new search macro:

1. **Update `lib/macros.js`** — Add a new entry to the `MACROS` object:

```javascript
'@newplatform_search': (query) => 
  `https://newplatform.com/search?q=${encodeURIComponent(query || '')}`,
```

2. **Update plugin definitions** — Add to the enum in `plugin.ts` and `plugin.js`:

```typescript
enum: [
  "@google_search",
  "@youtube_search",
  // ... existing
  "@newplatform_search",  // Add here
]
```

3. **Update documentation** — Add to the table in `AGENTS.md`

---

## Related Documentation

| Document | Description |
|----------|-------------|
| [API Reference](server-routes) | Complete REST API documentation |
| [Agents Guide](AGENTS.md) | Usage examples for AI agents |
| [Plugin System](plugins) | Extending browser functionality |

---

## Notes

- Macros with empty queries generate valid URLs with empty search parameters
- All macro URLs point to the primary domain for each platform (e.g., `youtube.com`, not regional variants)
- The `@twitter_search` macro points to `twitter.com/search` which redirects to `x.com/search`

---

<a id='deployment'></a>

## Deployment Guide

### Related Pages

Related topics: [Quick Start Guide](#quickstart), [Configuration Reference](#configuration)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [AGENTS.md](https://github.com/jo-inc/camofox-browser/blob/main/AGENTS.md)
- [package.json](https://github.com/jo-inc/camofox-browser/blob/main/package.json)
- [Dockerfile](https://github.com/jo-inc/camofox-browser/blob/main/Dockerfile)
- [Dockerfile.ci](https://github.com/jo-inc/camofox-browser/blob/main/Dockerfile.ci)
- [Makefile](https://github.com/jo-inc/camofox-browser/blob/main/Makefile)
- [build.ps1](https://github.com/jo-inc/camofox-browser/blob/main/build.ps1)
- [railway.toml](https://github.com/jo-inc/camofox-browser/blob/main/railway.toml)
- [server.js](https://github.com/jo-inc/camofox-browser/blob/main/server.js)
- [lib/reporter.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/reporter.js)
</details>

# 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:

```bash
# 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

```bash
docker run --rm -it -p 9377:9377 \
  ghcr.io/jo-inc/camofox-browser:latest
```

#### VNC Support

Enable VNC for visual debugging and monitoring:

```bash
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](https://github.com/jo-inc/camofox-browser/issues/4314)

#### Production Docker Configuration

```bash
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:

```bash
# 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:

```toml
[railway]
  builder = "nixpacks"
  minDockerVersion = 23

[deploy]
  numReplicas = 1
  restartPolicyType = "ON_FAILURE"
  restartPolicyMaxRetries = 10
  startCommand = "npm start"
```

Source: [railway.toml](https://github.com/jo-inc/camofox-browser/blob/main/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:

```bash
# Run directly with npx
npx @askjo/camofox-browser

# Install globally
npm install -g @askjo/camofox-browser
camofox-browser
```

Source: [AGENTS.md](https://github.com/jo-inc/camofox-browser/blob/main/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

```bash
# 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](https://github.com/jo-inc/camofox-browser/blob/main/AGENTS.md)

#### Running with Camoufox Engine

```bash
# 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](https://github.com/jo-inc/camofox-browser/blob/main/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:

```bash
# 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](https://github.com/jo-inc/camofox-browser/blob/main/lib/reporter.js)

## Build System

### Makefile Targets

The Makefile provides standardized build commands:

```makefile
# 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](https://github.com/jo-inc/camofox-browser/blob/main/Makefile)

### Windows Build Script

PowerShell build automation for Windows environments:

```powershell
# From PowerShell
.\build.ps1

# With options
.\build.ps1 -Task build -Configuration Release
```

Source: [build.ps1](https://github.com/jo-inc/camofox-browser/blob/main/build.ps1)

### Docker Build

Build custom Docker images locally:

```bash
# Production image
docker build -t camofox:local .

# CI image (includes test dependencies)
docker build -f Dockerfile.ci -t camofox:ci .
```

## Architecture Overview

```mermaid
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:#4fc3f7
```

## Resource 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

```yaml
# 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](https://github.com/jo-inc/camofox-browser/issues?q=stuck%3Aevent-loop)

## 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

```json
{
  "ok": true,
  "engine": "camoufox",
  "browserConnected": true,
  "browserRunning": true,
  "activeTabs": 0,
  "activeSessions": 0,
  "consecutiveFailures": 0,
  "memory": {
    "rssMb": 45,
    "heapUsedMb": 35,
    "nativeMemMb": 10
  }
}
```

Source: [server.js](https://github.com/jo-inc/camofox-browser/blob/main/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](https://github.com/jo-inc/camofox-browser/issues/4314), [#54](https://github.com/jo-inc/camofox-browser/issues/54)

### Container Logs

```bash
# 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:

```bash
# 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_URL` for monitoring
- [ ] Use read-only container filesystem where possible
- [ ] Limit container privileges with `--read-only`

### Authentication

All production deployments should use API key authentication:

```bash
# All requests require API key
curl -H "X-API-Key: your-secure-api-key" \
  http://localhost:9377/health
```

## Updating

### Docker Updates

```bash
# 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

```bash
# Check for updates
npm outdated @askjo/camofox-browser

# Update
npm install -g @askjo/camofox-browser@latest
```

### Source Updates

```bash
git pull origin main
npm install
npm start
```

## Plugin Deployment

Plugins extend functionality and are installed at runtime:

```bash
# 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](https://github.com/jo-inc/camofox-browser/blob/main/scripts/plugin.js)

---

<a id='plugins'></a>

## Plugin System

### Related Pages

Related topics: [Deployment Guide](#deployment), [Cookie & Session Persistence](#cookie-management)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [lib/plugins.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/plugins.js)
- [scripts/plugin.js](https://github.com/jo-inc/camofox-browser/blob/main/scripts/plugin.js)
- [plugin.ts](https://github.com/jo-inc/camofox-browser/blob/main/plugin.ts)
- [plugin.js](https://github.com/jo-inc/camofox-browser/blob/main/plugin.js)
- [AGENTS.md](https://github.com/jo-inc/camofox-browser/blob/main/AGENTS.md)
- [server.js](https://github.com/jo-inc/camofox-browser/blob/main/server.js)
- [lib/openapi.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/openapi.js)
</details>

# 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

```mermaid
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:#e8f5e9
```

### Context 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](https://github.com/jo-inc/camofox-browser/blob/main/AGENTS.md)*

## 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:

```javascript
// 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:

```bash
# 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](https://github.com/jo-inc/camofox-browser/blob/main/scripts/plugin.js)*

## Event System

The plugin system provides 29 events across 7 categories via the `ctx.events` EventEmitter.

### Event Categories

```mermaid
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:#f1f8e9
```

### Browser 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](https://github.com/jo-inc/camofox-browser/blob/main/lib/plugins.js)*

### 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](https://github.com/jo-inc/camofox-browser/blob/main/AGENTS.md)*

## 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](https://github.com/jo-inc/camofox-browser/blob/main/plugin.ts)*

### 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](https://github.com/jo-inc/camofox-browser/blob/main/plugin.js)*

## Plugin Installation Workflow

```mermaid
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 server
```

## Troubleshooting

### 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:

```bash
npm install
node scripts/plugin.js list
```

### VNC Not Activating in Docker

**Issue:** VNC doesn't activate from environment variables in Docker

```bash
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](https://github.com/jo-inc/camofox-browser/blob/main/lib/openapi.js)*

## Best Practices

1. **Always unsubscribe from events** in cleanup handlers to prevent memory leaks
2. **Use `ctx.log()`** instead of `console.log()` for consistent logging
3. **Handle errors gracefully** and use `ctx.safeError()` for client responses
4. **Respect concurrency limits** using `ctx.withUserLimit()` for user-specific operations
5. **Test plugins locally** before distribution using local path installation

## See Also

- [API Documentation](https://github.com/jo-inc/camofox-browser/blob/main/docs/api.md) — Full REST API reference
- [README.md](https://github.com/jo-inc/camofox-browser/blob/main/README.md) — Getting started guide
- [AGENTS.md](https://github.com/jo-inc/camofox-browser/blob/main/AGENTS.md) — Agent integration guide

---

<a id='configuration'></a>

## Configuration Reference

### Related Pages

Related topics: [Deployment Guide](#deployment)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [server.js](https://github.com/jo-inc/camofox-browser/blob/main/server.js) - Main server with route handlers and configuration usage
- [package.json](https://github.com/jo-inc/camofox-browser/blob/main/package.json) - NPM configuration and CLI setup
- [lib/reporter.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/reporter.js) - Crash/hang reporter configuration
- [lib/plugins.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/plugins.js) - Plugin system and event hooks
- [lib/openapi.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/openapi.js) - OpenAPI documentation configuration
- [lib/snapshot.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/snapshot.js) - Snapshot configuration constants
- [lib/extract.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/extract.js) - Data extraction schema validation
- [scripts/plugin.js](https://github.com/jo-inc/camofox-browser/blob/main/scripts/plugin.js) - Plugin management CLI
</details>

# 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](https://github.com/jo-inc/camofox-browser/blob/main/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](https://github.com/jo-inc/camofox-browser/blob/main/package.json)

```bash
# 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](https://github.com/jo-inc/camofox-browser/blob/main/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](https://github.com/nicholasgm/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](https://github.com/jo-inc/camofox-browser/blob/main/server.js) (viewport endpoint)

### Tab Management

Each user session can have multiple tab groups. Tab state tracking includes:

```javascript
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](https://github.com/jo-inc/camofox-browser/blob/main/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](https://github.com/jo-inc/camofox-browser/blob/main/lib/plugins.js) (event definitions)

### Plugin Installation

Use the CLI to manage plugins:

```bash
# 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](https://github.com/jo-inc/camofox-browser/blob/main/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](https://github.com/jo-inc/camofox-browser/blob/main/AGENTS.md)

## Resource Limits

### User Limits

Per-user rate limiting and resource quotas prevent individual users from monopolizing server resources:

```javascript
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](https://github.com/jo-inc/camofox-browser/blob/main/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:

```javascript
{
  text: chunk + marker,
  truncated: true,
  totalChars: total,
  offset: clampedOffset,
  hasMore: boolean,
  nextOffset: hasMore ? chunkEnd : null
}
```

Source: [lib/snapshot.js](https://github.com/jo-inc/camofox-browser/blob/main/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](https://github.com/jo-inc/camofox-browser/blob/main/server.js) (images endpoint)

## Trace Configuration

### Trace Directory

Traces are stored in `CONFIG.tracesDir`. Trace file paths are validated to prevent directory traversal attacks:

```javascript
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](https://github.com/jo-inc/camofox-browser/blob/main/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:

```javascript
// 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](https://github.com/jo-inc/camofox-browser/blob/main/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](https://github.com/jo-inc/camofox-browser/blob/main/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](https://github.com/jo-inc/camofox-browser/blob/main/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

```bash
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](https://github.com/jo-inc/camofox-browser/issues/4314) (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:

```bash
npm run generate-openapi
```

Source: [AGENTS.md](https://github.com/jo-inc/camofox-browser/blob/main/AGENTS.md) (OpenAPI documentation rules)

### Route Tags

Routes must be tagged with one of:

- `System` - Health, status, info endpoints
- `Tabs` - Tab CRUD operations
- `Navigation` - URL navigation, search macros
- `Interaction` - Click, type, scroll, press
- `Content` - Snapshot, screenshot, evaluate
- `Sessions` - Session management
- `Browser` - Browser-level operations
- `Legacy` - 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:

1. Monitor `/health` endpoint memory metrics
2. Set appropriate `consecutiveFailures` thresholds
3. Consider server restart on high uptime

Source: [community context](https://github.com/jo-inc/camofox-browser/issues/4483) (event loop stall reports)

### VNC in Docker

VNC activation via environment variables changed in version 1.11. If VNC doesn't start in Docker:

1. Verify `ENABLE_VNC=1` is set
2. Confirm `VNC_BIND` is configured
3. Check that port 6080 is exposed

Source: [community context](https://github.com/jo-inc/camofox-browser/issues/4314) (VNC regression report)

### Plugin Installation Failures

Plugin updates may fail with `ERR_MODULE_NOT_FOUND`. This typically occurs when:

1. NPM dependencies are not installed
2. The plugin path is incorrect
3. Version incompatibilities exist between Node.js and plugin modules

Solution: Reinstall plugins or check Node.js version compatibility.

Source: [community context](https://github.com/jo-inc/camofox-browser/issues/54) (plugin update failure)

---

<a id='cookie-management'></a>

## Cookie & Session Persistence

### Related Pages

Related topics: [Session & Tab Management](#session-management), [Plugin System](#plugins)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [server.js](https://github.com/jo-inc/camofox-browser/blob/main/server.js)
- [lib/cookies.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/cookies.js)
- [lib/auth.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/auth.js)
- [lib/plugins.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/plugins.js)
- [plugin.ts](https://github.com/jo-inc/camofox-browser/blob/main/plugin.ts)
- [openclaw.plugin.json](https://github.com/jo-inc/camofox-browser/blob/main/openclaw.plugin.json)
</details>

# 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

```mermaid
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| B
```

## Cookie 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]()

```javascript
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]()

```javascript
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:

```bash
POST /pressure/cleanup
Authorization: Bearer <accessKey>

{
  "dryRun": true,
  "closeEmptySessions": true,
  "maxSessions": 100
}
```

Response:
```json
{
  "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:**
```json
{
  "cookies": [
    {
      "name": "session_id",
      "value": "abc123",
      "domain": ".example.com",
      "path": "/",
      "expires": 1735689600,
      "httpOnly": true,
      "secure": true
    }
  ]
}
```

**Response:**
```json
{
  "ok": true,
  "imported": 1
}
```

### OpenClaw Plugin Integration

The OpenClaw plugin provides a `camofox_import_cookies` tool for AI agents:

```typescript
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:**
```json
{
  "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:

```javascript
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:

```javascript
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:

```javascript
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:

```javascript
// 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:

```javascript
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:

```javascript
// 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](https://github.com/jo-inc/camofox-browser/blob/main/AGENTS.md) — OpenAPI specification guidelines
- [OpenAPI Docs](http://localhost:9377/docs) — Interactive API documentation (when server running)
- [lib/plugins.js](https://github.com/jo-inc/camofox-browser/blob/main/lib/plugins.js) — Full plugin event reference

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Pitfall Log

Project: jo-inc/camofox-browser

Summary: 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
- Evidence strength: source_linked
- 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.
- Suggested 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
- Evidence strength: source_linked
- 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.
- Suggested 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
- Evidence strength: source_linked
- 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.
- Suggested 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
- Evidence strength: source_linked
- 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.
- Suggested 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
- Evidence strength: source_linked
- 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.
- Suggested 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
- Evidence strength: source_linked
- 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.
- Suggested 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
- Evidence strength: source_linked
- 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.
- Suggested 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
- Evidence strength: source_linked
- 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.
- Suggested 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
- Evidence strength: source_linked
- 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.
- Suggested 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
- Evidence strength: source_linked
- 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.
- Suggested 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
- Evidence strength: source_linked
- 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.
- Suggested 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
- Evidence strength: source_linked
- 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.
- Suggested 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

## 13. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- 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.
- Suggested check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | cevd_734e663855e842ce92efed98a8cbd0b3 | https://github.com/jo-inc/camofox-browser/issues/4862

## 14. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- 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.
- Suggested check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | cevd_defd39095ef14988a51da35554363f33 | https://github.com/jo-inc/camofox-browser/issues/4860

## 15. Capability evidence risk - Capability evidence risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: README/documentation is current enough for a first validation pass.
- User impact: May increase setup, validation, or first-run risk for the user.
- Suggested check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: capability.assumptions | github_repo:1142274728 | https://github.com/jo-inc/camofox-browser

## 16. Runtime risk - Runtime risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this runtime risk before relying on the project: [5cf7d100] stuck:event-loop: Event loop stalled for 22s (threshold: 5s)
- User impact: Developers may hit a documented source-backed failure mode: [5cf7d100] stuck:event-loop: Event loop stalled for 22s (threshold: 5s)
- Suggested check: Before packaging this project, run the relevant install/config/quickstart check for: [5cf7d100] stuck:event-loop: Event loop stalled for 22s (threshold: 5s). Context: Observed when using macos
- Guardrail: State this as source-backed community evidence, not as Doramagic reproduction.
- Evidence: failure_mode_cluster:github_issue | fmev_adfbf6e2a8851ffb888977db14835ee7 | https://github.com/jo-inc/camofox-browser/issues/4483

## 17. Runtime risk - Runtime risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this runtime risk before relying on the project: [ef2f639f] stuck:event-loop: Event loop stalled for 103s (threshold: 5s)
- User impact: Developers may hit a documented source-backed failure mode: [ef2f639f] stuck:event-loop: Event loop stalled for 103s (threshold: 5s)
- Suggested check: Before packaging this project, run the relevant install/config/quickstart check for: [ef2f639f] stuck:event-loop: Event loop stalled for 103s (threshold: 5s). Context: Observed when using macos
- Guardrail: State this as source-backed community evidence, not as Doramagic reproduction.
- Evidence: failure_mode_cluster:github_issue | fmev_e1e537c82dc9bc903c25afaff458ef37 | https://github.com/jo-inc/camofox-browser/issues/4484

## 18. Runtime risk - Runtime risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a runtime risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Suggested check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: packet_text.keyword_scan | github_repo:1142274728 | https://github.com/jo-inc/camofox-browser

## 19. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this migration risk before relying on the project: [1f7f8070] stuck:event-loop: Event loop stalled for 6s (threshold: 5s)
- User impact: Developers may hit a documented source-backed failure mode: [1f7f8070] stuck:event-loop: Event loop stalled for 6s (threshold: 5s)
- Suggested check: Before packaging this project, run the relevant install/config/quickstart check for: [1f7f8070] stuck:event-loop: Event loop stalled for 6s (threshold: 5s). Context: Observed when using node, macos
- Guardrail: State this as source-backed community evidence, not as Doramagic reproduction.
- Evidence: failure_mode_cluster:github_issue | fmev_4f4c6975103e49767f988cddded1c5a3 | https://github.com/jo-inc/camofox-browser/issues/4857

## 20. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this migration risk before relying on the project: [1f8af390] stuck:event-loop: Event loop stalled for 80s (threshold: 5s)
- User impact: Developers may hit a documented source-backed failure mode: [1f8af390] stuck:event-loop: Event loop stalled for 80s (threshold: 5s)
- Suggested check: Before packaging this project, run the relevant install/config/quickstart check for: [1f8af390] stuck:event-loop: Event loop stalled for 80s (threshold: 5s). Context: Observed when using node, macos
- Guardrail: State this as source-backed community evidence, not as Doramagic reproduction.
- Evidence: failure_mode_cluster:github_issue | fmev_7f437cba05011955428eb8555b0dd70c | https://github.com/jo-inc/camofox-browser/issues/4854

## 21. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this migration risk before relying on the project: [43752418] stuck:event-loop: Event loop stalled for 46s (threshold: 5s)
- User impact: Developers may hit a documented source-backed failure mode: [43752418] stuck:event-loop: Event loop stalled for 46s (threshold: 5s)
- Suggested check: Before packaging this project, run the relevant install/config/quickstart check for: [43752418] stuck:event-loop: Event loop stalled for 46s (threshold: 5s). Context: Observed when using node, macos
- Guardrail: State this as source-backed community evidence, not as Doramagic reproduction.
- Evidence: failure_mode_cluster:github_issue | fmev_f75614730f93a7ca81e759ec5b88bf03 | https://github.com/jo-inc/camofox-browser/issues/4858

## 22. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this migration risk before relying on the project: [51f1f89c] stuck:event-loop: Event loop stalled for 38s (threshold: 5s)
- User impact: Developers may hit a documented source-backed failure mode: [51f1f89c] stuck:event-loop: Event loop stalled for 38s (threshold: 5s)
- Suggested check: Before packaging this project, run the relevant install/config/quickstart check for: [51f1f89c] stuck:event-loop: Event loop stalled for 38s (threshold: 5s). Context: Observed when using node, macos
- Guardrail: State this as source-backed community evidence, not as Doramagic reproduction.
- Evidence: failure_mode_cluster:github_issue | fmev_a3790117e4c346db5a241874d5355c6d | https://github.com/jo-inc/camofox-browser/issues/4851

## 23. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this migration risk before relying on the project: [674b19b0] stuck:event-loop: Event loop stalled for 23s (threshold: 5s)
- User impact: Developers may hit a documented source-backed failure mode: [674b19b0] stuck:event-loop: Event loop stalled for 23s (threshold: 5s)
- Suggested check: Before packaging this project, run the relevant install/config/quickstart check for: [674b19b0] stuck:event-loop: Event loop stalled for 23s (threshold: 5s). Context: Observed when using node, macos
- Guardrail: State this as source-backed community evidence, not as Doramagic reproduction.
- Evidence: failure_mode_cluster:github_issue | fmev_5f800f182f246903f0b004ebdf189ce5 | https://github.com/jo-inc/camofox-browser/issues/4856

## 24. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this migration risk before relying on the project: [7506c020] stuck:event-loop: Event loop stalled for 70s (threshold: 5s)
- User impact: Developers may hit a documented source-backed failure mode: [7506c020] stuck:event-loop: Event loop stalled for 70s (threshold: 5s)
- Suggested check: Before packaging this project, run the relevant install/config/quickstart check for: [7506c020] stuck:event-loop: Event loop stalled for 70s (threshold: 5s). Context: Observed when using node, macos
- Guardrail: State this as source-backed community evidence, not as Doramagic reproduction.
- Evidence: failure_mode_cluster:github_issue | fmev_5cbd66fe3eb622d1f5e34730b742dbac | https://github.com/jo-inc/camofox-browser/issues/4852

## 25. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this migration risk before relying on the project: [8c732f44] stuck:event-loop: Event loop stalled for 93s (threshold: 5s)
- User impact: Developers may hit a documented source-backed failure mode: [8c732f44] stuck:event-loop: Event loop stalled for 93s (threshold: 5s)
- Suggested check: Before packaging this project, run the relevant install/config/quickstart check for: [8c732f44] stuck:event-loop: Event loop stalled for 93s (threshold: 5s). Context: Observed when using node, macos
- Guardrail: State this as source-backed community evidence, not as Doramagic reproduction.
- Evidence: failure_mode_cluster:github_issue | fmev_1c9813603e614996e1e705a49f5d9459 | https://github.com/jo-inc/camofox-browser/issues/4853

## 26. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this migration risk before relying on the project: [8ffefba3] stuck:event-loop: Event loop stalled for 55s (threshold: 5s)
- User impact: Developers may hit a documented source-backed failure mode: [8ffefba3] stuck:event-loop: Event loop stalled for 55s (threshold: 5s)
- Suggested check: Before packaging this project, run the relevant install/config/quickstart check for: [8ffefba3] stuck:event-loop: Event loop stalled for 55s (threshold: 5s). Context: Observed when using node, macos
- Guardrail: State this as source-backed community evidence, not as Doramagic reproduction.
- Evidence: failure_mode_cluster:github_issue | fmev_dcf762017f14fd0f1ff0f2fd7938023e | https://github.com/jo-inc/camofox-browser/issues/4855

## 27. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this migration risk before relying on the project: [90cfc6c8] stuck:event-loop: Event loop stalled for 17s (threshold: 5s)
- User impact: Developers may hit a documented source-backed failure mode: [90cfc6c8] stuck:event-loop: Event loop stalled for 17s (threshold: 5s)
- Suggested check: Before packaging this project, run the relevant install/config/quickstart check for: [90cfc6c8] stuck:event-loop: Event loop stalled for 17s (threshold: 5s). Context: Observed when using node, macos
- Guardrail: State this as source-backed community evidence, not as Doramagic reproduction.
- Evidence: failure_mode_cluster:github_issue | fmev_0ae6d0d255bee7d4c76ecadae2a2b89b | https://github.com/jo-inc/camofox-browser/issues/4863, failure_mode_cluster:github_issue | fmev_9b0f7685b8e7a6dc76d4052c3ed229f3 | https://github.com/jo-inc/camofox-browser/issues/4861, failure_mode_cluster:github_issue | fmev_4a9cb6fcef9fa031d0e8ee287b4c4997 | https://github.com/jo-inc/camofox-browser/issues/4849

## 28. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this migration risk before relying on the project: [988be9c4] stuck:event-loop: Event loop stalled for 18s (threshold: 5s)
- User impact: Developers may hit a documented source-backed failure mode: [988be9c4] stuck:event-loop: Event loop stalled for 18s (threshold: 5s)
- Suggested check: Before packaging this project, run the relevant install/config/quickstart check for: [988be9c4] stuck:event-loop: Event loop stalled for 18s (threshold: 5s). Context: Observed when using node, macos
- Guardrail: State this as source-backed community evidence, not as Doramagic reproduction.
- Evidence: failure_mode_cluster:github_issue | fmev_58b8387d3aaf6df3674469afed9e6e2b | https://github.com/jo-inc/camofox-browser/issues/4862

## 29. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this migration risk before relying on the project: [c665094c] stuck:event-loop: Event loop stalled for 74s (threshold: 5s)
- User impact: Developers may hit a documented source-backed failure mode: [c665094c] stuck:event-loop: Event loop stalled for 74s (threshold: 5s)
- Suggested check: Before packaging this project, run the relevant install/config/quickstart check for: [c665094c] stuck:event-loop: Event loop stalled for 74s (threshold: 5s). Context: Observed when using node, macos
- Guardrail: State this as source-backed community evidence, not as Doramagic reproduction.
- Evidence: failure_mode_cluster:github_issue | fmev_aebc2e6751b5e29fe6a44e3dc055a8cd | https://github.com/jo-inc/camofox-browser/issues/4860

## 30. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this migration risk before relying on the project: [fed74e38] stuck:event-loop: Event loop stalled for 96s (threshold: 5s)
- User impact: Developers may hit a documented source-backed failure mode: [fed74e38] stuck:event-loop: Event loop stalled for 96s (threshold: 5s)
- Suggested check: Before packaging this project, run the relevant install/config/quickstart check for: [fed74e38] stuck:event-loop: Event loop stalled for 96s (threshold: 5s). Context: Observed when using node, macos
- Guardrail: State this as source-backed community evidence, not as Doramagic reproduction.
- Evidence: failure_mode_cluster:github_issue | fmev_f1881e686e51f7989cbba960e849e678 | https://github.com/jo-inc/camofox-browser/issues/4850

## 31. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- 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.
- Suggested check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: evidence.maintainer_signals | github_repo:1142274728 | https://github.com/jo-inc/camofox-browser

## 32. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Suggested check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: downstream_validation.risk_items | github_repo:1142274728 | https://github.com/jo-inc/camofox-browser

## 33. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Suggested check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: risks.scoring_risks | github_repo:1142274728 | https://github.com/jo-inc/camofox-browser

## 34. Runtime risk - Runtime risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this performance risk before relying on the project: [0d148b4c] stuck:event-loop: Event loop stalled for 7s (threshold: 5s)
- User impact: Developers may hit a documented source-backed failure mode: [0d148b4c] stuck:event-loop: Event loop stalled for 7s (threshold: 5s)
- Suggested check: Before packaging this project, run the relevant install/config/quickstart check for: [0d148b4c] stuck:event-loop: Event loop stalled for 7s (threshold: 5s). Context: Observed when using node, linux
- Guardrail: State this as source-backed community evidence, not as Doramagic reproduction.
- Evidence: failure_mode_cluster:github_issue | fmev_96d2eca451f642a641a8a7b2525b1746 | https://github.com/jo-inc/camofox-browser/issues/4493

## 35. Runtime risk - Runtime risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this performance risk before relying on the project: [50ffc888] stuck:event-loop: Event loop stalled for 12s (threshold: 5s)
- User impact: Developers may hit a documented source-backed failure mode: [50ffc888] stuck:event-loop: Event loop stalled for 12s (threshold: 5s)
- Suggested check: Before packaging this project, run the relevant install/config/quickstart check for: [50ffc888] stuck:event-loop: Event loop stalled for 12s (threshold: 5s). Context: Observed when using node, linux
- Guardrail: State this as source-backed community evidence, not as Doramagic reproduction.
- Evidence: failure_mode_cluster:github_issue | fmev_4c3438066164124d4582118383fcfdca | https://github.com/jo-inc/camofox-browser/issues/4495

## 36. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: issue_or_pr_quality=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Suggested check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: evidence.maintainer_signals | github_repo:1142274728 | https://github.com/jo-inc/camofox-browser

## 37. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: release_recency=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Suggested check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: evidence.maintainer_signals | github_repo:1142274728 | https://github.com/jo-inc/camofox-browser

<!-- canonical_name: jo-inc/camofox-browser; human_manual_source: deepwiki_human_wiki -->
