# camoufox-browser

A headless browser automation server designed for AI agents. Powered by [Camoufox](https://camoufox.com) - a Firefox-based browser with C++ anti-detection that bypasses bot detection including Google captcha.

This is the same browser engine that powers [askjo.ai](https://askjo.ai)'s web scraping capabilities.

**Perfect for:** [OpenClaw](https://openclaw.ai), Claude Code, LangChain agents, AutoGPT, and any AI system that needs to browse the web.

## Motivation

AI agents need to browse the web, but current solutions have significant limitations:

- **Playwright/Puppeteer + stealth plugins** get detected and blocked by Google, Cloudflare, and most anti-bot systems. JavaScript-level evasion isn't enough.
- **Headless Chrome** is trivially fingerprinted. Sites check for hundreds of browser characteristics that reveal automation.
- **API-based scrapers** (Browserless, ScrapingBee) work but cost money per request and add latency.
- **Raw HTTP requests** can't handle JavaScript-rendered content or complex interactions.

Camoufox solves this with **C++ level anti-detection** baked into the Firefox source code itself - not a plugin that can be detected, but fundamental changes to how the browser reports its fingerprint. This is the same approach used by commercial anti-detect browsers.

This project wraps Camoufox in a simple REST API optimized for AI agents: accessibility snapshots instead of bloated HTML, stable element refs for reliable clicking, and search macros for common sites.

## Features

- **Anti-Detection** - Camoufox engine (Firefox-based) with C++ fingerprint spoofing, bypasses Google captcha
- **Element Refs** - Stable `e1`, `e2`, `e3` references for clicking/typing
- **Session Isolation** - Separate cookies/storage per user, tabs grouped by conversation
- **Search Macros** - 13 built-in URL macros (`@google_search`, `@youtube_search`, etc.)
- **Token-Efficient** - Accessibility snapshots instead of full HTML (90% smaller)
- **Docker Ready** - Production Dockerfile with pre-baked Camoufox binary

## Quick Start

### OpenClaw Plugin

Install as an OpenClaw plugin for agent tool access:

```bash
openclaw plugins install @askjo/camoufox-browser
```

Then start the server and configure:

```yaml
# ~/.openclaw/openclaw.json
plugins:
  entries:
    camoufox-browser:
      enabled: true
      config:
        url: "http://localhost:9377"
```

The plugin provides these agent tools:
- `camoufox_create_tab` - Create a browser tab
- `camoufox_snapshot` - Get page snapshot with element refs
- `camoufox_click` - Click elements by ref
- `camoufox_type` - Type into elements
- `camoufox_navigate` - Navigate to URLs or use search macros
- `camoufox_scroll` - Scroll the page
- `camoufox_screenshot` - Take screenshots
- `camoufox_close_tab` - Close tabs
- `camoufox_list_tabs` - List open tabs

### Standalone Server

```bash
# Clone and install
git clone https://github.com/jo-inc/camoufox-browser
cd camoufox-browser
npm install

# Start server (downloads Camoufox browser on first run)
npm start                    # Default port 3000
./run-camoufox.sh -p 3001    # Custom port

# Server runs on http://localhost:3000
```

## API Overview

### Create a Tab
```bash
curl -X POST http://localhost:3000/tabs \
  -H "Content-Type: application/json" \
  -d '{"userId": "user1", "sessionKey": "conv1", "url": "https://example.com"}'
```

### Get Page Snapshot (with element refs)
```bash
curl "http://localhost:3000/tabs/TAB_ID/snapshot?userId=user1"
```

Response includes refs for interaction:
```json
{
  "snapshot": "[button e1] Submit  [link e2] Learn more",
  "refs": {
    "e1": { "role": "button", "name": "Submit" },
    "e2": { "role": "link", "name": "Learn more" }
  },
  "url": "https://example.com"
}
```

### Click an Element
```bash
curl -X POST http://localhost:3000/tabs/TAB_ID/click \
  -H "Content-Type: application/json" \
  -d '{"userId": "user1", "ref": "e1"}'
```

### Search with Macros
```bash
curl -X POST http://localhost:3000/tabs/TAB_ID/navigate \
  -H "Content-Type: application/json" \
  -d '{"userId": "user1", "macro": "@google_search", "query": "best coffee beans"}'
```

## All Endpoints

| Method | Path | Description |
|--------|------|-------------|
| GET | `/health` | Health check |
| GET | `/tabs?userId=X` | List all tab groups for user |
| POST | `/tabs` | Create new tab |
| DELETE | `/tabs/:tabId` | Close tab |
| POST | `/tabs/:tabId/navigate` | Navigate to URL or macro |
| GET | `/tabs/:tabId/snapshot` | Get accessibility snapshot with refs |
| POST | `/tabs/:tabId/click` | Click element by ref or selector |
| POST | `/tabs/:tabId/type` | Type into element |
| POST | `/tabs/:tabId/scroll` | Scroll page |
| POST | `/tabs/:tabId/back` | Go back |
| POST | `/tabs/:tabId/forward` | Go forward |
| POST | `/tabs/:tabId/refresh` | Refresh page |
| GET | `/tabs/:tabId/links` | Get all links |
| GET | `/tabs/:tabId/screenshot` | Get screenshot |
| DELETE | `/sessions/:userId` | Close all tabs for user |

## Search Macros

Navigate supports these macros for common sites:

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

## Architecture

```
Browser Instance
└── User Session (BrowserContext) - isolated cookies/storage
    ├── Tab Group (sessionKey: "conv1") - conversation A
    │   ├── Tab (google.com)
    │   └── Tab (github.com)
    └── Tab Group (sessionKey: "conv2") - conversation B
        └── Tab (amazon.com)
```

- One browser instance shared across users
- Separate BrowserContext per user (isolated cookies/storage)
- Tabs grouped by `sessionKey` (conversation/task)
- 30-minute session timeout with automatic cleanup

## Running Locally

```bash
# Start with default port (3000)
./run-camoufox.sh
# Or: npm start

# Start with custom port
./run-camoufox.sh -p 3001
```

First run downloads the Camoufox browser (~300MB).

### Experimental

See [`experimental/`](experimental/) for alternative browser engines.

## Docker Deployment

```bash
# Build with Camoufox (recommended)
docker build -f Dockerfile.camoufox -t camoufox-browser .

# Run
docker run -p 3000:3000 camoufox-browser
```

## Fly.io Deployment

```bash
fly launch --no-deploy
fly deploy
```

## Testing

```bash
npm test                 # Run all e2e tests
npm run test:live        # Run live Google tests (may hit captcha)
npm run test:debug       # Show server output for debugging
```

## Environment Variables

| Variable | Description | Default |
|----------|-------------|---------|
| `PORT` | Server port | 3000 |
| `NODE_ENV` | Environment | development |

## Contributing

Contributions are welcome! Please open an issue or submit a PR.

## Credits

- [Camoufox](https://camoufox.com) - Firefox-based browser with C++ anti-detection
- [Amp](https://ampcode.com) - AI coding agent

## License

MIT
