@askjo/camofox-browser 1.1.0 → 1.1.1

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.
Files changed (3) hide show
  1. package/README.md +101 -30
  2. package/package.json +1 -1
  3. package/plugin.ts +6 -4
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  <a href="https://hub.docker.com"><img src="https://img.shields.io/badge/docker-ready-blue" alt="Docker" /></a>
10
10
  </p>
11
11
  <p>
12
- Standing on the mighty shoulders of <a href="https://camoufox.com">Camoufox</a> a Firefox fork with fingerprint spoofing at the C++ level.
12
+ Standing on the mighty shoulders of <a href="https://camoufox.com">Camoufox</a> - a Firefox fork with fingerprint spoofing at the C++ level.
13
13
  <br/><br/>
14
14
  The same engine behind <a href="https://askjo.ai">askjo.ai</a>'s web browsing.
15
15
  </p>
@@ -23,21 +23,21 @@
23
23
 
24
24
  AI agents need to browse the real web. Playwright gets blocked. Headless Chrome gets fingerprinted. Stealth plugins become the fingerprint.
25
25
 
26
- 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.
26
+ 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.
27
27
 
28
28
  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.
29
29
 
30
30
  ## Features
31
31
 
32
- - **C++ Anti-Detection** bypasses Google, Cloudflare, and most bot detection
33
- - **Element Refs** stable `e1`, `e2`, `e3` identifiers for reliable interaction
34
- - **Token-Efficient** accessibility snapshots are ~90% smaller than raw HTML
35
- - **Session Isolation** separate cookies/storage per user
36
- - **Cookie Import** inject Netscape-format cookie files for authenticated browsing
37
- - **Proxy + GeoIP** route traffic through residential proxies with automatic locale/timezone
38
- - **Structured Logging** JSON log lines with request IDs for production observability
39
- - **Search Macros** `@google_search`, `@youtube_search`, `@amazon_search`, `@reddit_subreddit`, and 10 more
40
- - **Deploy Anywhere** Docker, Fly.io, Railway
32
+ - **C++ Anti-Detection** - bypasses Google, Cloudflare, and most bot detection
33
+ - **Element Refs** - stable `e1`, `e2`, `e3` identifiers for reliable interaction
34
+ - **Token-Efficient** - accessibility snapshots are ~90% smaller than raw HTML
35
+ - **Session Isolation** - separate cookies/storage per user
36
+ - **Cookie Import** - inject Netscape-format cookie files for authenticated browsing
37
+ - **Proxy + GeoIP** - route traffic through residential proxies with automatic locale/timezone
38
+ - **Structured Logging** - JSON log lines with request IDs for production observability
39
+ - **Search Macros** - `@google_search`, `@youtube_search`, `@amazon_search`, `@reddit_subreddit`, and 10 more
40
+ - **Deploy Anywhere** - Docker, Fly.io, Railway
41
41
 
42
42
  ## Quick Start
43
43
 
@@ -73,26 +73,97 @@ docker run -p 9377:9377 camofox-browser
73
73
 
74
74
  ## Usage
75
75
 
76
- ### Cookie Injection (Netscape cookie file → Playwright cookies)
76
+ ### Cookie Import
77
77
 
78
- If you’re using the OpenClaw plugin, you can import a Netscape-format cookie file (e.g., exported from a browser) to authenticate sessions without interactive login.
78
+ Import cookies from your browser into Camoufox to skip interactive login on sites like LinkedIn, Amazon, etc.
79
79
 
80
- - Tool: `camofox_import_cookies`
81
- - Server endpoint: `POST /sessions/:userId/cookies`
80
+ #### Setup
82
81
 
83
- **Security:** this endpoint is disabled unless `CAMOFOX_API_KEY` is set on the server. When enabled, callers must include `Authorization: Bearer <CAMOFOX_API_KEY>`.
82
+ **1. Generate a secret key:**
84
83
 
85
84
  ```bash
86
- # OpenClaw tool usage (conceptual)
87
- # camofox_import_cookies({ cookiesPath: "linkedin.txt", domainSuffix: "linkedin.com" })
85
+ # macOS / Linux
86
+ openssl rand -hex 32
87
+ ```
88
+
89
+ **2. Set the environment variable before starting OpenClaw:**
90
+
91
+ ```bash
92
+ export CAMOFOX_API_KEY="your-generated-key"
93
+ openclaw start
94
+ ```
95
+
96
+ The same key is used by both the plugin (to authenticate requests) and the server (to verify them). Both run from the same environment — set it once.
97
+
98
+ > **Why an env var?** The key is a secret. Plugin config in `openclaw.json` is stored in plaintext, so secrets don't belong there. Set `CAMOFOX_API_KEY` in your shell profile, systemd unit, Docker env, or Fly.io secrets.
99
+
100
+ > **Cookie import is disabled by default.** If `CAMOFOX_API_KEY` is not set, the server rejects all cookie requests with 403.
101
+
102
+ **3. Export cookies from your browser:**
103
+
104
+ Install a browser extension that exports Netscape-format cookie files (e.g., "cookies.txt" for Chrome/Firefox). Export the cookies for the site you want to authenticate.
105
+
106
+ **4. Place the cookie file:**
107
+
108
+ ```bash
109
+ mkdir -p ~/.camofox/cookies
110
+ cp ~/Downloads/linkedin_cookies.txt ~/.camofox/cookies/linkedin.txt
111
+ ```
112
+
113
+ The default directory is `~/.camofox/cookies/`. Override with `CAMOFOX_COOKIES_DIR`.
114
+
115
+ **5. Ask your agent to import them:**
116
+
117
+ > Import my LinkedIn cookies from linkedin.txt
88
118
 
89
- # Direct server usage (Playwright cookie objects)
119
+ The agent calls `camofox_import_cookies` → reads the file → POSTs to the server with the Bearer token → cookies are injected into the browser session. Subsequent `camofox_create_tab` calls to linkedin.com will be authenticated.
120
+
121
+ #### How it works
122
+
123
+ ```
124
+ ~/.camofox/cookies/linkedin.txt (Netscape format, on disk)
125
+
126
+
127
+ camofox_import_cookies tool (parses file, filters by domain)
128
+
129
+ ▼ POST /sessions/:userId/cookies
130
+ │ Authorization: Bearer <CAMOFOX_API_KEY>
131
+ │ Body: { cookies: [Playwright cookie objects] }
132
+
133
+ camofox server (validates, sanitizes, injects)
134
+
135
+ ▼ context.addCookies(...)
136
+
137
+ Camoufox browser session (authenticated browsing)
138
+ ```
139
+
140
+ - `cookiesPath` is resolved relative to the cookies directory — path traversal outside it is blocked
141
+ - Max 500 cookies per request, 5MB file size limit
142
+ - Cookie objects are sanitized to an allowlist of Playwright fields
143
+
144
+ #### Standalone server usage
145
+
146
+ ```bash
90
147
  curl -X POST http://localhost:9377/sessions/agent1/cookies \
91
148
  -H 'Content-Type: application/json' \
92
149
  -H 'Authorization: Bearer YOUR_CAMOFOX_API_KEY' \
93
150
  -d '{"cookies":[{"name":"foo","value":"bar","domain":"example.com","path":"/","expires":-1,"httpOnly":false,"secure":false}]}'
94
151
  ```
95
152
 
153
+ #### Docker / Fly.io
154
+
155
+ ```bash
156
+ docker run -p 9377:9377 \
157
+ -e CAMOFOX_API_KEY="your-generated-key" \
158
+ -v ~/.camofox/cookies:/home/node/.camofox/cookies:ro \
159
+ camofox-browser
160
+ ```
161
+
162
+ For Fly.io:
163
+ ```bash
164
+ fly secrets set CAMOFOX_API_KEY="your-generated-key"
165
+ ```
166
+
96
167
  ### Proxy + GeoIP
97
168
 
98
169
  Route all browser traffic through a proxy with automatic locale, timezone, and geolocation derived from the proxy's IP address via Camoufox's built-in GeoIP.
@@ -212,27 +283,27 @@ curl -X POST http://localhost:9377/tabs/TAB_ID/navigate \
212
283
  `@google_search` · `@youtube_search` · `@amazon_search` · `@reddit_search` · `@reddit_subreddit` · `@wikipedia_search` · `@twitter_search` · `@yelp_search` · `@spotify_search` · `@netflix_search` · `@linkedin_search` · `@instagram_search` · `@tiktok_search` · `@twitch_search`
213
284
 
214
285
  Reddit macros return JSON directly (no HTML parsing needed):
215
- - `@reddit_search` search all of Reddit, returns JSON with 25 results
216
- - `@reddit_subreddit` browse a subreddit (e.g., query `"programming"` → `/r/programming.json`)
286
+ - `@reddit_search` - search all of Reddit, returns JSON with 25 results
287
+ - `@reddit_subreddit` - browse a subreddit (e.g., query `"programming"` → `/r/programming.json`)
217
288
 
218
289
  ## Environment Variables
219
290
 
220
291
  | Variable | Description | Default |
221
292
  |----------|-------------|---------|
222
293
  | `CAMOFOX_PORT` | Server port | `9377` |
223
- | `CAMOFOX_API_KEY` | Enable cookie import endpoint (disabled if unset) | |
224
- | `CAMOFOX_ADMIN_KEY` | Required for `POST /stop` | |
294
+ | `CAMOFOX_API_KEY` | Enable cookie import endpoint (disabled if unset) | - |
295
+ | `CAMOFOX_ADMIN_KEY` | Required for `POST /stop` | - |
225
296
  | `CAMOFOX_COOKIES_DIR` | Directory for cookie files | `~/.camofox/cookies` |
226
- | `PROXY_HOST` | Proxy hostname or IP | |
227
- | `PROXY_PORT` | Proxy port | |
228
- | `PROXY_USERNAME` | Proxy auth username | |
229
- | `PROXY_PASSWORD` | Proxy auth password | |
297
+ | `PROXY_HOST` | Proxy hostname or IP | - |
298
+ | `PROXY_PORT` | Proxy port | - |
299
+ | `PROXY_USERNAME` | Proxy auth username | - |
300
+ | `PROXY_PASSWORD` | Proxy auth password | - |
230
301
 
231
302
  ## Architecture
232
303
 
233
304
  ```
234
305
  Browser Instance (Camoufox)
235
- └── User Session (BrowserContext) isolated cookies/storage
306
+ └── User Session (BrowserContext) - isolated cookies/storage
236
307
  ├── Tab Group (sessionKey: "conv1")
237
308
  │ ├── Tab (google.com)
238
309
  │ └── Tab (github.com)
@@ -259,9 +330,9 @@ npm install @askjo/camofox-browser
259
330
 
260
331
  ## Credits
261
332
 
262
- - [Camoufox](https://camoufox.com) Firefox-based browser with C++ anti-detection
333
+ - [Camoufox](https://camoufox.com) - Firefox-based browser with C++ anti-detection
263
334
  - [Donate to Camoufox's original creator daijro](https://camoufox.com/about/)
264
- - [OpenClaw](https://openclaw.ai) Open-source AI agent framework
335
+ - [OpenClaw](https://openclaw.ai) - Open-source AI agent framework
265
336
 
266
337
  ## Crypto Scam Warning
267
338
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askjo/camofox-browser",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "Headless browser automation server and OpenClaw plugin for AI agents - anti-detection, element refs, and session isolation",
5
5
  "main": "server.js",
6
6
  "license": "MIT",
package/plugin.ts CHANGED
@@ -93,7 +93,8 @@ interface PluginApi {
93
93
  name: string,
94
94
  check: () => Promise<HealthCheckResult>
95
95
  ) => void;
96
- config: PluginConfig;
96
+ config: Record<string, unknown>;
97
+ pluginConfig?: PluginConfig;
97
98
  log: {
98
99
  info: (msg: string) => void;
99
100
  error: (msg: string) => void;
@@ -246,9 +247,10 @@ function parseNetscapeCookieFile(text: string) {
246
247
  }
247
248
 
248
249
  export default function register(api: PluginApi) {
249
- const port = api.config.port || 9377;
250
- const baseUrl = api.config.url || `http://localhost:${port}`;
251
- const autoStart = api.config.autoStart !== false; // default true
250
+ const cfg = api.pluginConfig ?? (api.config as unknown as PluginConfig);
251
+ const port = cfg.port || 9377;
252
+ const baseUrl = cfg.url || `http://localhost:${port}`;
253
+ const autoStart = cfg.autoStart !== false; // default true
252
254
  const pluginDir = getPluginDir();
253
255
  const fallbackUserId = `camofox-${randomUUID()}`;
254
256