@askjo/camofox-browser 1.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,59 @@
1
+ FROM node:20-slim
2
+
3
+ # Pinned Camoufox version for reproducible builds
4
+ # Update these when upgrading Camoufox
5
+ ARG CAMOUFOX_VERSION=135.0.1
6
+ ARG CAMOUFOX_RELEASE=beta.24
7
+ ARG CAMOUFOX_URL=https://github.com/daijro/camoufox/releases/download/v${CAMOUFOX_VERSION}-${CAMOUFOX_RELEASE}/camoufox-${CAMOUFOX_VERSION}-${CAMOUFOX_RELEASE}-lin.x86_64.zip
8
+
9
+ # Install dependencies for Camoufox (Firefox-based)
10
+ RUN apt-get update && apt-get install -y \
11
+ # Firefox dependencies
12
+ libgtk-3-0 \
13
+ libdbus-glib-1-2 \
14
+ libxt6 \
15
+ libasound2 \
16
+ libx11-xcb1 \
17
+ libxcomposite1 \
18
+ libxcursor1 \
19
+ libxdamage1 \
20
+ libxfixes3 \
21
+ libxi6 \
22
+ libxrandr2 \
23
+ libxrender1 \
24
+ libxss1 \
25
+ libxtst6 \
26
+ # Fonts
27
+ fonts-liberation \
28
+ fonts-noto-color-emoji \
29
+ fontconfig \
30
+ # Utils
31
+ ca-certificates \
32
+ curl \
33
+ unzip \
34
+ && rm -rf /var/lib/apt/lists/*
35
+
36
+ # Pre-bake Camoufox browser binary into image
37
+ # This avoids downloading at runtime and pins the version
38
+ # Note: unzip returns exit code 1 for warnings (Unicode filenames), so we use || true and verify
39
+ RUN mkdir -p /root/.cache/camoufox \
40
+ && curl -L -o /tmp/camoufox.zip "${CAMOUFOX_URL}" \
41
+ && (unzip -q /tmp/camoufox.zip -d /root/.cache/camoufox || true) \
42
+ && rm /tmp/camoufox.zip \
43
+ && chmod -R 755 /root/.cache/camoufox \
44
+ && echo "{\"version\":\"${CAMOUFOX_VERSION}\",\"release\":\"${CAMOUFOX_RELEASE}\"}" > /root/.cache/camoufox/version.json \
45
+ && test -f /root/.cache/camoufox/camoufox-bin && echo "Camoufox installed successfully"
46
+
47
+ WORKDIR /app
48
+
49
+ COPY package.json ./
50
+ RUN npm install --production
51
+
52
+ COPY server-camoufox.js ./
53
+
54
+ ENV NODE_ENV=production
55
+ ENV PORT=3000
56
+
57
+ EXPOSE 3000
58
+
59
+ CMD ["node", "server-camoufox.js"]
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Jo, Inc
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,145 @@
1
+ <div align="center">
2
+ <img src="camofox.png" alt="camofox-browser" width="200" />
3
+ <h1>camofox-browser</h1>
4
+ <p><strong>Headless browser server for AI agents with C++ anti-detection</strong></p>
5
+ <p>
6
+ <a href="https://github.com/jo-inc/camofox-browser/actions"><img src="https://img.shields.io/badge/build-passing-brightgreen" alt="Build" /></a>
7
+ <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-blue" alt="License" /></a>
8
+ <a href="https://camoufox.com"><img src="https://img.shields.io/badge/engine-Camoufox-red" alt="Camoufox" /></a>
9
+ <a href="https://hub.docker.com"><img src="https://img.shields.io/badge/docker-ready-blue" alt="Docker" /></a>
10
+ </p>
11
+ <p>
12
+ Powered by <a href="https://camoufox.com">Camoufox</a> — a Firefox fork with fingerprint spoofing at the C++ level.<br/>
13
+ The same engine behind <a href="https://askjo.ai">askjo.ai</a>'s web scraping.
14
+ </p>
15
+ </div>
16
+
17
+ ---
18
+
19
+ ## Why
20
+
21
+ AI agents need to browse the real web. Playwright gets blocked. Headless Chrome gets fingerprinted. Stealth plugins become the fingerprint.
22
+
23
+ Camoufox patches Firefox at the **C++ implementation level** — `navigator.hardwareConcurrency`, WebGL renderers, AudioContext, screen geometry, WebRTC — all spoofed before JavaScript ever sees them. No shims, no wrappers, no tells.
24
+
25
+ This project wraps that engine in a REST API built for agents: accessibility snapshots instead of bloated HTML, stable element refs for clicking, and search macros for common sites.
26
+
27
+ ## Features
28
+
29
+ - **C++ Anti-Detection** — bypasses Google, Cloudflare, and most bot detection
30
+ - **Element Refs** — stable `e1`, `e2`, `e3` identifiers for reliable interaction
31
+ - **Token-Efficient** — accessibility snapshots are 90% smaller than raw HTML
32
+ - **Session Isolation** — separate cookies/storage per user
33
+ - **Search Macros** — `@google_search`, `@youtube_search`, `@amazon_search`, and 10 more
34
+ - **Docker Ready** — production Dockerfile with pre-baked Camoufox binary
35
+
36
+ ## Quick Start
37
+
38
+ ### OpenClaw Plugin
39
+
40
+ ```bash
41
+ openclaw plugins install @askjo/camofox-browser
42
+ ```
43
+
44
+ ```yaml
45
+ # ~/.openclaw/openclaw.json
46
+ plugins:
47
+ entries:
48
+ camofox-browser:
49
+ enabled: true
50
+ config:
51
+ url: "http://localhost:9377"
52
+ ```
53
+
54
+ **Tools:** `camofox_create_tab` · `camofox_snapshot` · `camofox_click` · `camofox_type` · `camofox_navigate` · `camofox_scroll` · `camofox_screenshot` · `camofox_close_tab` · `camofox_list_tabs`
55
+
56
+ ### Standalone
57
+
58
+ ```bash
59
+ git clone https://github.com/jo-inc/camofox-browser
60
+ cd camofox-browser
61
+ npm install
62
+ npm start # downloads Camoufox on first run (~300MB)
63
+ ```
64
+
65
+ ### Docker
66
+
67
+ ```bash
68
+ docker build -f Dockerfile.camoufox -t camofox-browser .
69
+ docker run -p 3000:3000 camofox-browser
70
+ ```
71
+
72
+ ## Usage
73
+
74
+ ```bash
75
+ # Create a tab
76
+ curl -X POST http://localhost:3000/tabs \
77
+ -d '{"userId": "agent1", "sessionKey": "task1", "url": "https://example.com"}'
78
+
79
+ # Get page snapshot with element refs
80
+ curl "http://localhost:3000/tabs/TAB_ID/snapshot?userId=agent1"
81
+ # → { "snapshot": "[button e1] Submit [link e2] Learn more", ... }
82
+
83
+ # Click by ref
84
+ curl -X POST http://localhost:3000/tabs/TAB_ID/click \
85
+ -d '{"userId": "agent1", "ref": "e1"}'
86
+
87
+ # Search with macros
88
+ curl -X POST http://localhost:3000/tabs/TAB_ID/navigate \
89
+ -d '{"userId": "agent1", "macro": "@google_search", "query": "best coffee beans"}'
90
+ ```
91
+
92
+ ## API
93
+
94
+ | Method | Endpoint | Description |
95
+ |--------|----------|-------------|
96
+ | `POST` | `/tabs` | Create tab |
97
+ | `GET` | `/tabs/:id/snapshot` | Accessibility snapshot with refs |
98
+ | `POST` | `/tabs/:id/click` | Click element by ref |
99
+ | `POST` | `/tabs/:id/type` | Type into element |
100
+ | `POST` | `/tabs/:id/navigate` | Navigate to URL or macro |
101
+ | `POST` | `/tabs/:id/scroll` | Scroll page |
102
+ | `GET` | `/tabs/:id/screenshot` | Screenshot |
103
+ | `GET` | `/tabs/:id/links` | All links on page |
104
+ | `POST` | `/tabs/:id/back` | Go back |
105
+ | `POST` | `/tabs/:id/forward` | Go forward |
106
+ | `POST` | `/tabs/:id/refresh` | Refresh |
107
+ | `DELETE` | `/tabs/:id` | Close tab |
108
+ | `GET` | `/tabs?userId=X` | List tabs |
109
+ | `DELETE` | `/sessions/:userId` | Close all user tabs |
110
+ | `GET` | `/health` | Health check |
111
+
112
+ ## Search Macros
113
+
114
+ `@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`
115
+
116
+ ## Architecture
117
+
118
+ ```
119
+ Browser Instance
120
+ └── User Session (BrowserContext) — isolated cookies/storage
121
+ ├── Tab Group (sessionKey: "conv1")
122
+ │ ├── Tab (google.com)
123
+ │ └── Tab (github.com)
124
+ └── Tab Group (sessionKey: "conv2")
125
+ └── Tab (amazon.com)
126
+ ```
127
+
128
+ Sessions auto-expire after 30 minutes of inactivity.
129
+
130
+ ## Testing
131
+
132
+ ```bash
133
+ npm test # e2e tests
134
+ npm run test:live # live Google tests
135
+ npm run test:debug # with server output
136
+ ```
137
+
138
+ ## Credits
139
+
140
+ - [Camoufox](https://camoufox.com) — Firefox-based browser with C++ anti-detection
141
+ - [Amp](https://ampcode.com) — AI coding agent
142
+
143
+ ## License
144
+
145
+ MIT
package/lib/macros.js ADDED
@@ -0,0 +1,30 @@
1
+ const MACROS = {
2
+ '@google_search': (query) => `https://www.google.com/search?q=${encodeURIComponent(query || '')}`,
3
+ '@youtube_search': (query) => `https://www.youtube.com/results?search_query=${encodeURIComponent(query || '')}`,
4
+ '@amazon_search': (query) => `https://www.amazon.com/s?k=${encodeURIComponent(query || '')}`,
5
+ '@reddit_search': (query) => `https://www.reddit.com/search/?q=${encodeURIComponent(query || '')}`,
6
+ '@wikipedia_search': (query) => `https://en.wikipedia.org/wiki/Special:Search?search=${encodeURIComponent(query || '')}`,
7
+ '@twitter_search': (query) => `https://twitter.com/search?q=${encodeURIComponent(query || '')}`,
8
+ '@yelp_search': (query) => `https://www.yelp.com/search?find_desc=${encodeURIComponent(query || '')}`,
9
+ '@spotify_search': (query) => `https://open.spotify.com/search/${encodeURIComponent(query || '')}`,
10
+ '@netflix_search': (query) => `https://www.netflix.com/search?q=${encodeURIComponent(query || '')}`,
11
+ '@linkedin_search': (query) => `https://www.linkedin.com/search/results/all/?keywords=${encodeURIComponent(query || '')}`,
12
+ '@instagram_search': (query) => `https://www.instagram.com/explore/tags/${encodeURIComponent(query || '')}`,
13
+ '@tiktok_search': (query) => `https://www.tiktok.com/search?q=${encodeURIComponent(query || '')}`,
14
+ '@twitch_search': (query) => `https://www.twitch.tv/search?term=${encodeURIComponent(query || '')}`
15
+ };
16
+
17
+ function expandMacro(macro, query) {
18
+ const macroFn = MACROS[macro];
19
+ return macroFn ? macroFn(query) : null;
20
+ }
21
+
22
+ function getSupportedMacros() {
23
+ return Object.keys(MACROS);
24
+ }
25
+
26
+ module.exports = {
27
+ expandMacro,
28
+ getSupportedMacros,
29
+ MACROS
30
+ };
@@ -0,0 +1,39 @@
1
+ {
2
+ "id": "camofox-browser",
3
+ "name": "Camoufox Browser",
4
+ "description": "Anti-detection browser automation for AI agents using Camoufox (Firefox-based)",
5
+ "version": "1.0.11",
6
+ "configSchema": {
7
+ "type": "object",
8
+ "properties": {
9
+ "url": {
10
+ "type": "string",
11
+ "description": "Camoufox browser server URL"
12
+ },
13
+ "port": {
14
+ "type": "number",
15
+ "description": "Server port (used if url not set)",
16
+ "default": 9377
17
+ },
18
+ "autoStart": {
19
+ "type": "boolean",
20
+ "description": "Auto-start the camofox-browser server with the Gateway",
21
+ "default": true
22
+ }
23
+ },
24
+ "additionalProperties": false
25
+ },
26
+ "uiHints": {
27
+ "url": {
28
+ "label": "Server URL",
29
+ "placeholder": "http://localhost:9377"
30
+ },
31
+ "port": {
32
+ "label": "Server Port",
33
+ "placeholder": "9377"
34
+ },
35
+ "autoStart": {
36
+ "label": "Auto-start server with Gateway"
37
+ }
38
+ }
39
+ }
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@askjo/camofox-browser",
3
+ "version": "1.0.12",
4
+ "description": "Headless browser automation server and OpenClaw plugin for AI agents - anti-detection, element refs, and session isolation",
5
+ "main": "server-camoufox.js",
6
+ "license": "MIT",
7
+ "author": "Jo Inc <oss@askjo.ai>",
8
+ "homepage": "https://github.com/jo-inc/camofox-browser#readme",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/jo-inc/camofox-browser.git"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/jo-inc/camofox-browser/issues"
15
+ },
16
+ "keywords": [
17
+ "browser",
18
+ "automation",
19
+ "headless",
20
+ "scraping",
21
+ "camofox",
22
+ "camoufox",
23
+ "anti-detection",
24
+ "ai-agent",
25
+ "openclaw",
26
+ "clawdbot",
27
+ "moltbot",
28
+ "playwright",
29
+ "firefox"
30
+ ],
31
+ "engines": {
32
+ "node": ">=18"
33
+ },
34
+ "files": [
35
+ "server-camoufox.js",
36
+ "lib/",
37
+ "plugin.ts",
38
+ "openclaw.plugin.json",
39
+ "run-camoufox.sh",
40
+ "Dockerfile.camoufox",
41
+ "README.md",
42
+ "LICENSE"
43
+ ],
44
+ "openclaw": {
45
+ "extensions": ["plugin.ts"]
46
+ },
47
+ "scripts": {
48
+ "start": "node server-camoufox.js",
49
+ "start:chrome": "node server.js",
50
+ "test": "jest --runInBand --forceExit",
51
+ "test:e2e": "jest --runInBand --forceExit tests/e2e",
52
+ "test:live": "RUN_LIVE_TESTS=1 jest --runInBand --forceExit tests/live",
53
+ "test:debug": "DEBUG_SERVER=1 jest --runInBand --forceExit",
54
+ "postinstall": "npx camoufox-js fetch || true"
55
+ },
56
+ "dependencies": {
57
+ "camoufox-js": "^0.8.5",
58
+ "dotenv": "^17.2.3",
59
+ "express": "^4.18.2",
60
+ "playwright": "^1.50.0",
61
+ "playwright-core": "^1.58.0",
62
+ "playwright-extra": "^4.3.6",
63
+ "puppeteer-extra-plugin-stealth": "^2.11.2"
64
+ },
65
+ "devDependencies": {
66
+ "jest": "^29.7.0"
67
+ }
68
+ }