camofox-browser 2.1.0 → 2.4.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 (102) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/README.md +304 -33
  3. package/dist/src/cli/commands/content.d.ts.map +1 -1
  4. package/dist/src/cli/commands/content.js +37 -0
  5. package/dist/src/cli/commands/content.js.map +1 -1
  6. package/dist/src/cli/commands/core.d.ts.map +1 -1
  7. package/dist/src/cli/commands/core.js +21 -4
  8. package/dist/src/cli/commands/core.js.map +1 -1
  9. package/dist/src/cli/commands/interaction.d.ts.map +1 -1
  10. package/dist/src/cli/commands/interaction.js +5 -14
  11. package/dist/src/cli/commands/interaction.js.map +1 -1
  12. package/dist/src/cli/commands/navigation.d.ts.map +1 -1
  13. package/dist/src/cli/commands/navigation.js +12 -6
  14. package/dist/src/cli/commands/navigation.js.map +1 -1
  15. package/dist/src/cli/commands/server.d.ts.map +1 -1
  16. package/dist/src/cli/commands/server.js +9 -3
  17. package/dist/src/cli/commands/server.js.map +1 -1
  18. package/dist/src/cli/commands/session.d.ts.map +1 -1
  19. package/dist/src/cli/commands/session.js +23 -5
  20. package/dist/src/cli/commands/session.js.map +1 -1
  21. package/dist/src/cli/server/manager.d.ts +1 -0
  22. package/dist/src/cli/server/manager.d.ts.map +1 -1
  23. package/dist/src/cli/server/manager.js +7 -12
  24. package/dist/src/cli/server/manager.js.map +1 -1
  25. package/dist/src/middleware/lifecycle-activity.d.ts +9 -0
  26. package/dist/src/middleware/lifecycle-activity.d.ts.map +1 -0
  27. package/dist/src/middleware/lifecycle-activity.js +21 -0
  28. package/dist/src/middleware/lifecycle-activity.js.map +1 -0
  29. package/dist/src/openapi/spec.d.ts +4 -0
  30. package/dist/src/openapi/spec.d.ts.map +1 -0
  31. package/dist/src/openapi/spec.js +730 -0
  32. package/dist/src/openapi/spec.js.map +1 -0
  33. package/dist/src/routes/core.d.ts.map +1 -1
  34. package/dist/src/routes/core.js +428 -53
  35. package/dist/src/routes/core.js.map +1 -1
  36. package/dist/src/routes/docs.d.ts +3 -0
  37. package/dist/src/routes/docs.d.ts.map +1 -0
  38. package/dist/src/routes/docs.js +23 -0
  39. package/dist/src/routes/docs.js.map +1 -0
  40. package/dist/src/routes/openclaw.d.ts.map +1 -1
  41. package/dist/src/routes/openclaw.js +244 -90
  42. package/dist/src/routes/openclaw.js.map +1 -1
  43. package/dist/src/server.js +55 -4
  44. package/dist/src/server.js.map +1 -1
  45. package/dist/src/services/context-pool.d.ts +19 -3
  46. package/dist/src/services/context-pool.d.ts.map +1 -1
  47. package/dist/src/services/context-pool.js +248 -65
  48. package/dist/src/services/context-pool.js.map +1 -1
  49. package/dist/src/services/download.d.ts +2 -0
  50. package/dist/src/services/download.d.ts.map +1 -1
  51. package/dist/src/services/download.js +110 -80
  52. package/dist/src/services/download.js.map +1 -1
  53. package/dist/src/services/lifecycle-controller.d.ts +40 -0
  54. package/dist/src/services/lifecycle-controller.d.ts.map +1 -0
  55. package/dist/src/services/lifecycle-controller.js +106 -0
  56. package/dist/src/services/lifecycle-controller.js.map +1 -0
  57. package/dist/src/services/resource-extractor.d.ts +1 -0
  58. package/dist/src/services/resource-extractor.d.ts.map +1 -1
  59. package/dist/src/services/resource-extractor.js +7 -0
  60. package/dist/src/services/resource-extractor.js.map +1 -1
  61. package/dist/src/services/session.d.ts +84 -2
  62. package/dist/src/services/session.d.ts.map +1 -1
  63. package/dist/src/services/session.js +349 -47
  64. package/dist/src/services/session.js.map +1 -1
  65. package/dist/src/services/structured-extractor.d.ts +39 -0
  66. package/dist/src/services/structured-extractor.d.ts.map +1 -0
  67. package/dist/src/services/structured-extractor.js +487 -0
  68. package/dist/src/services/structured-extractor.js.map +1 -0
  69. package/dist/src/services/tab.d.ts +30 -3
  70. package/dist/src/services/tab.d.ts.map +1 -1
  71. package/dist/src/services/tab.js +877 -124
  72. package/dist/src/services/tab.js.map +1 -1
  73. package/dist/src/services/tracing.d.ts +7 -0
  74. package/dist/src/services/tracing.d.ts.map +1 -1
  75. package/dist/src/services/tracing.js +162 -19
  76. package/dist/src/services/tracing.js.map +1 -1
  77. package/dist/src/services/vnc.d.ts.map +1 -1
  78. package/dist/src/services/vnc.js +5 -3
  79. package/dist/src/services/vnc.js.map +1 -1
  80. package/dist/src/services/youtube.js +1 -1
  81. package/dist/src/services/youtube.js.map +1 -1
  82. package/dist/src/types.d.ts +71 -1
  83. package/dist/src/types.d.ts.map +1 -1
  84. package/dist/src/utils/config.d.ts +79 -3
  85. package/dist/src/utils/config.d.ts.map +1 -1
  86. package/dist/src/utils/config.js +145 -3
  87. package/dist/src/utils/config.js.map +1 -1
  88. package/dist/src/utils/presets.d.ts.map +1 -1
  89. package/dist/src/utils/presets.js +3 -1
  90. package/dist/src/utils/presets.js.map +1 -1
  91. package/dist/src/utils/proxy-profiles.d.ts +18 -0
  92. package/dist/src/utils/proxy-profiles.d.ts.map +1 -0
  93. package/dist/src/utils/proxy-profiles.js +197 -0
  94. package/dist/src/utils/proxy-profiles.js.map +1 -0
  95. package/dist/src/utils/sidecar-version.d.ts +12 -0
  96. package/dist/src/utils/sidecar-version.d.ts.map +1 -0
  97. package/dist/src/utils/sidecar-version.js +63 -0
  98. package/dist/src/utils/sidecar-version.js.map +1 -0
  99. package/dist/tsconfig.tsbuildinfo +1 -1
  100. package/openclaw.plugin.json +39 -0
  101. package/package.json +16 -4
  102. package/plugin.ts +949 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,131 @@
1
1
  # Changelog
2
2
 
3
+ ## [Unreleased]
4
+
5
+ ## Release Audit: v2.3.0 -> v2.4.1
6
+
7
+ ### What shipped in this line
8
+ - **Security hardening** tightened exposed deployment defaults with loopback-only bind, non-loopback API key enforcement, private-network navigation blocking, and fail-fast proxy deployment validation.
9
+ - **Proxy and geo session identity** moved from user-only scoping to `userId + sessionKey`, allowing parallel sessions with distinct proxy and geo profiles without unsafe reuse or eviction collisions.
10
+ - **Lifecycle control** added staged idle cleanup plus daemon exit policy, with activity-aware timer disarming so live sessions are not collected accidentally.
11
+ - **Fingerprint environment controls** added deployment-level defaults for OS, WebGL, screen dimensions, and humanization, with strict parsing and clear generation-time versus launch-time behavior.
12
+ - **Structured extraction** introduced schema-driven extraction across core API, CLI, and OpenClaw, including validation-time 400s and runtime 422s with stable field-path reporting.
13
+ - **OpenAPI and interactive docs** added `/openapi.json` and `/api/docs`, then hardened the spec and origin handling to match real server behavior.
14
+ - **Release-lane hardening** shipped in `v2.4.1`, ensuring Docker/GHCR publication no longer fails solely because optional GeoLite download during `camoufox-js fetch` is temporarily unavailable.
15
+
16
+ ### Reading guide
17
+ - **`2.4.0`** is the main Wave 2 delivery release.
18
+ - **`2.4.1`** is the follow-up patch that fixes the release-distribution lane while inheriting the full `2.4.0` surface.
19
+
20
+ ## [2.4.1] - 2026-05-05
21
+
22
+ ### Upgrade Notes
23
+ - **Patch scope**: `2.4.1` keeps the full Wave 2 surface from `2.4.0` and only changes release-distribution behavior.
24
+ - **Operator impact**: Docker/GHCR publication no longer fails solely because `camoufox-js fetch` cannot download the optional GeoLite database during image build.
25
+
26
+ ### Fixed
27
+ - **Docker release builds** now tolerate transient `camoufox-js fetch` / GeoLite MMDB download failures during image creation.
28
+ - **Release-lane consistency** now matches the existing best-effort `postinstall` fetch contract already used by package installation.
29
+
30
+ ## [2.4.0] - 2026-05-05
31
+
32
+ ### Upgrade Notes
33
+ - **Wave 2 delivery** adds OpenAPI documentation, deployment-level fingerprint controls, staged idle lifecycle management, session-level proxy/geo overrides, and structured extraction without removing previous route aliases.
34
+ - **Operational posture** is more defensive than in `2.3.0`: exposed deployments now default to loopback-only binding, require an API key on non-loopback binds, reject unsafe private-network navigation by default, and fail fast on unsupported proxy deployment assumptions.
35
+
36
+ ### Added
37
+ - **OpenAPI 3.1.0 specification** at `/openapi.json` with request/response schemas, auth requirements, and representative route coverage.
38
+ - **Interactive Swagger UI** at `/api/docs` for live inspection and request testing.
39
+ - **Fingerprint environment controls** for `CAMOFOX_OS`, `CAMOFOX_ALLOW_WEBGL`, `CAMOFOX_SCREEN_WIDTH`, `CAMOFOX_SCREEN_HEIGHT`, and `CAMOFOX_HUMANIZE`.
40
+ - **Idle lifecycle policy** with staged cleanup (`CAMOFOX_IDLE_TIMEOUT_MS`) and daemon exit (`CAMOFOX_IDLE_EXIT_TIMEOUT_MS`).
41
+ - **Session-level proxy/geo overrides** through `proxyProfile`, raw `proxy` fields, and `geoMode`.
42
+ - **OpenClaw proxy/geo parity** for `/tabs/open`.
43
+ - **Structured extraction** across core API, CLI, and OpenClaw with schema validation and deterministic JSON output.
44
+
45
+ ### Changed
46
+ - **Session identity and reuse** now key proxy/geo behavior on `userId + sessionKey` instead of `userId` alone.
47
+ - **Context pool eviction** now uses `profileKey`, preventing sibling sessions from evicting each other incorrectly.
48
+ - **OpenAPI docs behavior** now derives server origin from the incoming request and safe defaults instead of assuming a single static external origin.
49
+
50
+ ### Fixed
51
+ - **Proxy profile validation** now rejects malformed configuration and preserves conflict behavior when an existing session profile disagrees with new proxy/geo input.
52
+ - **Lifecycle cleanup correctness** now avoids cleanup reentry, preserves reused/live contexts, and only arms daemon exit under valid idle conditions.
53
+ - **Fingerprint env application** now routes screen constraints into fingerprint generation rather than launch-only options, preserving the intended sidecar semantics.
54
+ - **Structured extraction contracts** now reject invalid root schemas/selectors and align API, CLI, and OpenClaw error semantics.
55
+ - **OpenAPI request contracts** now mark required fields correctly and remove mismatched schema claims such as unsupported `/act` coverage.
56
+
57
+ ### Security
58
+ - Default server bind is `127.0.0.1` via `CAMOFOX_HOST`, and non-loopback binds require `CAMOFOX_API_KEY`.
59
+ - Navigation target validation blocks loopback/private/link-local/metadata hosts by default on exposed deployments unless `CAMOFOX_ALLOW_PRIVATE_NETWORK=true`.
60
+ - Proxy-enabled exposed deployments fail fast unless the operator explicitly opts into private-network allowance.
61
+
62
+ ### Docs
63
+ - README, skills, and agent-facing references were updated to document the shipped Wave 2 surfaces.
64
+ - OpenAPI discovery wording, subset-scope wording, request contracts, and origin handling were corrected to match actual shipped behavior.
65
+
66
+ ### Tests
67
+ - Added E2E coverage for security hardening, proxy/geo overrides, OpenClaw proxy/geo support, fingerprint env controls, lifecycle cleanup/exit, OpenAPI docs, and structured extraction.
68
+ - Added unit coverage for profile-key eviction, lifecycle state handling, proxy profile parsing, structured extractor schema/runtime contracts, and URL security validation.
69
+
70
+ ## [2.3.0] - 2026-05-03
71
+
72
+ ### Upgrade Notes
73
+ - **New Wave 1 surfaces** add trace artifact retrieval and image-only extraction on top of the existing tracing/resource services. These are additive endpoints and do not remove any previous route or alias.
74
+ - **Conditional auth coverage** now includes the image listing route when `CAMOFOX_API_KEY` is set, aligning it with the surrounding extraction/tracing surfaces.
75
+
76
+ ### Added
77
+ - **Trace artifact management** — `GET /sessions/:userId/traces`, `GET /sessions/:userId/traces/:filename`, and `DELETE /sessions/:userId/traces/:filename`
78
+ - **Image listing route** — `GET /tabs/:tabId/images` for image-only extraction with selector, extension, blob-resolution, and lazy-load options
79
+ - **Wave 1 regression coverage** for trace ownership/path handling, timeout cleanup, chunk-stop coordination, and image-route auth/behavior
80
+
81
+ ### Fixed
82
+ - Trace artifact ownership now uses collision-safe owner tokens rather than lossy userId sanitization
83
+ - Trace artifact handling now rejects spoofed paths, keeps managed files inside the traces root, and tolerates vanished files during list operations
84
+ - Trace timeout cleanup now stays coordinated with both manual stop and in-flight chunk-stop operations
85
+ - `extractImages()` no longer requires a fake `userId` shim in its shared extractor contract
86
+
87
+ ### Changed
88
+ - README and release metadata now reflect shipped Wave 1 trace/image capabilities
89
+ - Package and OpenClaw plugin versions now advance together to `2.3.0`
90
+
91
+ ## [2.2.1] - 2026-04-09
92
+
93
+ ### Changed
94
+ - Version bump for release-prep (v2.2.0 tag exists; this patch carries final release framing)
95
+
96
+ ## [2.2.0] - 2026-04-09
97
+
98
+ ### Upgrade Notes
99
+ - **Local-state sidecar versioning** introduces fail-closed compatibility checks. If local state files are incompatible with the running version, the server will refuse to start the affected session and log an error with the specific path to delete. For sidecar metadata files, only the indicated file needs removal. For profile-level incompatibilities (e.g., Camoufox engine version mismatch), the error may indicate deleting the entire profile directory — follow the error message guidance.
100
+ - **API key guard** is now conditionally applied to core and OpenClaw protected endpoints (tab creation, navigation, interaction, session management, downloads, tracing, console) when `CAMOFOX_API_KEY` is set. The `POST /stop` route requires `CAMOFOX_ADMIN_KEY` unconditionally. Unset deployments are unaffected.
101
+
102
+ ### Added
103
+ - **Conditional API-key guard** (`CAMOFOX_API_KEY`) on core and OpenClaw protected endpoints — tab creation, navigation, interaction, session management, downloads, tracing, console. Guard enforced only when env var is set; unset deployments are unaffected. `POST /stop` uses a separate unconditional `CAMOFOX_ADMIN_KEY` guard
104
+ - **Canonical profile invariants** — staged first-use, rollback-on-failure, cookie race guard
105
+ - **Local-state sidecar versioning** with fail-closed compatibility checks and migration support
106
+ - **Snapshot pagination** with offset-based windowing for large page snapshots
107
+ - **OpenClaw parity** — snapshot, navigate, scroll endpoints aligned with plugin contract
108
+ - **Macro navigate** and scroll parity with initial-download capture
109
+ - **Plugin surface cleanup** — publish/install/plugin artifact contract validation
110
+
111
+ ### Fixed
112
+ - Server env whitelist: added `DISPLAY`, `HANDLER_TIMEOUT_MS`, `MAX_CONCURRENT_PER_USER`
113
+ - Unified CLI port and idle-timeout defaults with canonical config
114
+ - Session lifecycle: staged first-use + rollback, cookie race guard, dist rebuild, tab-cap test
115
+
116
+ ### Changed
117
+ - README, skills, and governance docs synced to shipped behavior
118
+
119
+ ## [2.1.1] - 2026-03-08
120
+
121
+ ### Fixed
122
+ - Unknown element ref now returns HTTP 400 with guidance message instead of ambiguous error
123
+
124
+ ## [2.1.0] - 2026-03-08
125
+
126
+ ### Fixed
127
+ - **Ref system improvements** — strict ref parsing, expanded element roles in snapshot, stale ref detection
128
+
3
129
  ## [2.0.5] - 2026-03-08
4
130
 
5
131
  ### Fixed
package/README.md CHANGED
@@ -11,6 +11,7 @@
11
11
 
12
12
  - [Why CamoFox?](#why-camofox)
13
13
  - [Features](#features)
14
+ - [Preview Status](#preview-status)
14
15
  - [Quick Start](#quick-start)
15
16
  - [CLI](#cli)
16
17
  - [Console Capture](#console-capture)
@@ -19,6 +20,7 @@
19
20
  - [Usage with AI Agents](#usage-with-ai-agents)
20
21
  - [Architecture](#architecture)
21
22
  - [API Reference](#api-reference)
23
+ - [Structured Extract](#structured-extract)
22
24
  - [Search Macros](#search-macros)
23
25
  - [Geo Presets](#geo-presets)
24
26
  - [Environment Variables](#environment-variables)
@@ -50,19 +52,53 @@
50
52
  - **Multi-Session** — concurrent isolated browser contexts per `userId` (defaults: max 50 sessions, max 10 tabs/session)
51
53
  - **Persistent Browser Profiles** — Each user gets a dedicated Firefox profile. Cookies, localStorage, IndexedDB, and all browser storage persist across sessions automatically.
52
54
  - **Geo Presets** — 8 built-in region presets (locale/timezone/geolocation) + custom presets file
55
+ - **Session-Level Proxy/Geo Overrides** — per-session proxy configuration via named profiles or raw credentials, with hybrid geo modes (`explicit-wins` or `proxy-locked`)
53
56
  - **14 Search Macros** — Google, YouTube, Amazon, Reddit (search + subreddit JSON), Wikipedia, Twitter, Yelp, Spotify, Netflix, LinkedIn, Instagram, TikTok, Twitch
54
57
  - **Element Refs** — accessibility snapshots annotated with stable `eN` element references for precise interaction
55
- - **Cookie Persistence** — import Netscape/Playwright-style cookies into a session (optional, gated by API key)
58
+ - **Cookie Persistence** — import Netscape/Playwright-style cookies into a session (bearer auth required only when `CAMOFOX_API_KEY` is set)
56
59
  - **OpenClaw Plugin** — OpenClaw-compatible endpoints (`/start`, `/tabs/open`, `/act`, etc.)
57
60
  - **TypeScript** — strict mode, typed request shapes, modular Express routes
58
- - **YouTube Transcript Extraction** — yt-dlp primary pipeline with browser fallback
61
+ - **YouTube Transcript Extraction** — yt-dlp + browser fallback (service-level; no public API route currently exposed)
59
62
  - **Snapshot Pagination** — offset-based windowing for large page snapshots
63
+ - **Image Listing Route** — image-only extraction over the shared resource extractor with selector, extension, lazy-load, and blob-resolution controls
64
+ - **Structured Extract** — deterministic schema-driven JSON extraction across core API, CLI, and OpenClaw without arbitrary JavaScript
60
65
  - **Browser Health Monitoring** — health probe with recovery/degraded state tracking
61
66
  - 🖥️ **CLI Mode** — 50+ commands for terminal-based browser automation
62
67
  - 🔐 **Auth Vault** — AES-256-GCM encrypted credential storage (LLM-safe)
63
68
  - 📜 **Pipeline Scripting** — Execute command scripts from files
64
69
  - 🔍 **Console Capture** — capture and filter browser console messages and uncaught errors
65
70
  - 📼 **Playwright Tracing** — record and export Playwright traces for debugging
71
+ - 🗂️ **Trace Artifact Management** — list, download, and delete managed trace ZIPs per user session
72
+
73
+ ## Preview Status
74
+
75
+ CamoFox Browser Server is in **Preview** (Phase 1). Preview releases are functional for browser automation and agent integration, but carry specific compatibility commitments and explicit non-goals.
76
+
77
+ ### What Preview Means
78
+ - The REST API and CLI are usable for agent workflows today; [CamoFox MCP](https://github.com/redf0x1/camofox-mcp) is available as an external companion integration
79
+ - New features may be added between minor versions
80
+ - Backward-compatible aliases are maintained for renamed or moved endpoints (see [Compatibility Policy](#compatibility-policy))
81
+ - Local state (profiles, registries, sessions) uses versioned formats with fail-closed integrity checks
82
+
83
+ ### What Preview Does NOT Guarantee
84
+ - **Frozen API surface** — endpoint behavior, request shapes, or response formats may change between minor versions
85
+ - **Automatic local-state migration** — browser profiles, download registries, and session files use versioned sidecar formats; incompatible upgrades require manual reset (see [Local State Recovery](#local-state-recovery))
86
+ - **Downgrade safety** — rolling back to an older version may require clearing local state
87
+ - **Fixed GA timeline** — promotion to GA requires meeting evidence-based exit criteria, not a calendar date
88
+
89
+ ### Compatibility Policy
90
+ During Preview, CamoFox follows an **additive-only deprecation model**:
91
+ - **Legacy aliases** (e.g., `listItemId` accepted alongside `sessionKey`, OpenClaw `/act` routing to core endpoints) continue to work alongside their replacements
92
+ - **Deprecated fields** are accepted silently; no removal until GA or a documented migration window with advance notice in CHANGELOG
93
+ - **No existing endpoint** is removed in a minor version — removals happen only in major versions with prior CHANGELOG notice
94
+
95
+ ### Local State Recovery
96
+ Browser profiles, download registries, and CLI session files use versioned sidecar formats. When upgrading CamoFox:
97
+ - **Compatible versions**: State loads normally
98
+ - **Incompatible or corrupt state**: The server refuses to load incompatible profiles and download registries; the CLI rejects incompatible saved-session files. Both log an actionable error with the specific recovery path.
99
+ - **Recovery**: Delete the affected profile directory, session file, or download registry as indicated in the error message. Clean state is recreated on next use.
100
+
101
+ Supported sidecars include limited forward-migration paths (e.g., fingerprint v0 → v1); when no migration path exists for a given version, the server refuses to load the file and logs an actionable recovery message. There is no silent repair or downgrade path — this fail-closed default prevents data corruption at the cost of manual intervention on unsupported version jumps.
66
102
 
67
103
  ## Quick Start
68
104
 
@@ -102,6 +138,8 @@ docker run -d \
102
138
  --name camofox-browser \
103
139
  -p 9377:9377 \
104
140
  -p 6080:6080 \
141
+ -e CAMOFOX_HOST=0.0.0.0 \
142
+ -e CAMOFOX_API_KEY=change-me \
105
143
  -v ~/.camofox:/home/node/.camofox \
106
144
  camofox-browser
107
145
  ```
@@ -117,9 +155,10 @@ services:
117
155
  ports:
118
156
  - "9377:9377"
119
157
  environment:
158
+ CAMOFOX_HOST: "0.0.0.0"
120
159
  CAMOFOX_PORT: "9377"
121
- # Optional auth gates
122
- # CAMOFOX_API_KEY: "change-me"
160
+ # Required when CAMOFOX_HOST is non-loopback
161
+ CAMOFOX_API_KEY: "change-me"
123
162
  # CAMOFOX_ADMIN_KEY: "change-me"
124
163
  # Optional: proxy routing (also enables Camoufox geoip mode)
125
164
  # PROXY_HOST: ""
@@ -146,7 +185,7 @@ CamoFox Browser includes a powerful CLI for browser automation directly from the
146
185
  npm install -g camofox-browser
147
186
 
148
187
  # Or use npx (no install needed)
149
- npx camofox open https://example.com
188
+ npx camofox-browser open https://example.com
150
189
  ```
151
190
 
152
191
  ### Quick Start
@@ -176,6 +215,7 @@ camofox get-url # Get current page URL
176
215
  camofox get-text # Get page text content
177
216
  camofox get-links # Get all links on page
178
217
  camofox get-tabs # List open tabs
218
+ camofox extract-structured @schema.json # Extract deterministic JSON from a schema
179
219
 
180
220
  # Interaction
181
221
  camofox click <ref> # Click element by ref
@@ -426,57 +466,75 @@ AI Agent (MCP / OpenClaw / REST Client)
426
466
 
427
467
  Base URL: `http://localhost:9377`
428
468
 
469
+ > **Security defaults:** `CAMOFOX_HOST` now defaults to `127.0.0.1`. If you bind beyond loopback (for example `0.0.0.0` in Docker or PaaS), `CAMOFOX_API_KEY` becomes required at startup. On non-loopback binds, navigation targets on loopback/private/link-local/metadata hosts are blocked by default unless you explicitly set `CAMOFOX_ALLOW_PRIVATE_NETWORK=true`. If you also configure `PROXY_HOST`/`PROXY_PORT`, exposed deployments must opt into `CAMOFOX_ALLOW_PRIVATE_NETWORK=true` until proxy-side private-target validation exists.
470
+
471
+ ### API Documentation
472
+
473
+ The Camofox Browser API includes OpenAPI 3.1.0 docs for a representative subset of the shipped route surface:
474
+
475
+ - **Interactive API Explorer**: [http://localhost:9377/api/docs](http://localhost:9377/api/docs) — Swagger UI with live request testing
476
+ - **OpenAPI Specification**: [http://localhost:9377/openapi.json](http://localhost:9377/openapi.json) — Machine-readable OpenAPI 3.1.0 spec
477
+
478
+ The OpenAPI spec covers a representative subset of core and OpenClaw endpoints, including request schemas, response shapes, authentication requirements, and validation rules.
479
+
429
480
  ### Core Endpoints
430
481
 
431
482
  Note: For any endpoint that targets an existing tab (`/tabs/:tabId/...`), the server resolves `tabId` **within a `userId` scope**. If you omit `userId`, you will typically get `404 Tab not found`.
432
483
 
433
484
  | Method | Endpoint | Description | Required | Auth |
434
485
  |--------|----------|-------------|----------|------|
435
- | POST | `/sessions/:userId/cookies` | Import cookies into a user session (Playwright cookie objects) | Path: `userId`; Body: `{ "cookies": Cookie[] }` | `Authorization: Bearer $CAMOFOX_API_KEY` |
486
+ | POST | `/sessions/:userId/cookies` | Import cookies into a user session (Playwright cookie objects) | Path: `userId`; Body: `{ "cookies": Cookie[] }` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
436
487
  | GET | `/health` | Health check (also pre-launches the browser) | None | None |
437
488
  | GET | `/presets` | List available geo presets (built-in + custom) | None | None |
438
- | POST | `/tabs` | Create a new tab (supports `preset` + per-field overrides) | Body: `userId` + (`sessionKey` or `listItemId`) | None |
489
+ | POST | `/tabs` | Create a new tab (supports `preset` + per-field overrides) | Body: `userId` + (`sessionKey` or `listItemId`) | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
439
490
  | GET | `/tabs?userId=...` | List all tabs for a user (OpenClaw-compatible response shape) | Query: `userId` | None |
440
- | POST | `/tabs/:tabId/navigate` | Navigate to a URL, or expand a search `macro` + `query` | Body: `userId` + (`url` or `macro`) | None |
491
+ | POST | `/tabs/:tabId/navigate` | Navigate to a URL, or expand a search `macro` + `query` | Body: `userId` + (`url` or `macro`) | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
441
492
  | GET | `/tabs/:tabId/snapshot?userId=...` | Accessibility snapshot annotated with `eN` element refs | Query: `userId` | None |
442
- | POST | `/tabs/:tabId/wait` | Wait for page readiness (DOM + optional network idle) | Body: `userId` | None |
443
- | POST | `/tabs/:tabId/click` | Click by `ref` (e.g. `e12`) or CSS `selector` | Body: `userId` + (`ref` or `selector`) | None |
444
- | POST | `/tabs/:tabId/type` | Type into an element by `ref` or CSS `selector` | Body: `userId` + (`ref` or `selector`) + `text` | None |
445
- | POST | `/tabs/:tabId/press` | Press a key (e.g. `Enter`, `Escape`) | Body: `userId` + `key` | None |
446
- | POST | `/tabs/:tabId/scroll` | Scroll up/down by pixels | Body: `userId` | None |
447
- | POST | `/tabs/:tabId/scroll-element` | Scroll specific element into view | Body: userId, ref/selector | None |
448
- | POST | `/tabs/:tabId/back` | Go back | Body: `userId` | None |
449
- | POST | `/tabs/:tabId/forward` | Go forward | Body: `userId` | None |
450
- | POST | `/tabs/:tabId/refresh` | Refresh | Body: `userId` | None |
493
+ | POST | `/tabs/:tabId/wait` | Wait for page readiness (DOM + optional network idle) | Body: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
494
+ | POST | `/tabs/:tabId/click` | Click by `ref` (e.g. `e12`) or CSS `selector` | Body: `userId` + (`ref` or `selector`) | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
495
+ | POST | `/tabs/:tabId/type` | Type into an element by `ref` or CSS `selector` | Body: `userId` + (`ref` or `selector`) + `text` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
496
+ | POST | `/tabs/:tabId/press` | Press a key (e.g. `Enter`, `Escape`) | Body: `userId` + `key` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
497
+ | POST | `/tabs/:tabId/scroll` | Scroll up/down/left/right by pixels | Body: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
498
+ | POST | `/tabs/:tabId/scroll-element` | Scroll specific element into view | Body: userId, ref/selector | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
499
+ | POST | `/tabs/:tabId/back` | Go back | Body: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
500
+ | POST | `/tabs/:tabId/forward` | Go forward | Body: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
501
+ | POST | `/tabs/:tabId/refresh` | Refresh | Body: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
451
502
  | GET | `/tabs/:tabId/links?userId=...&limit=50&offset=0` | Extract links (paginated) | Query: `userId` | None |
503
+ | GET | `/tabs/:tabId/images?userId=...` | List extracted images | Query: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
452
504
  | GET | `/tabs/:tabId/screenshot?userId=...&fullPage=true` | Screenshot (PNG bytes) | Query: `userId` | None |
453
505
  | GET | `/tabs/:tabId/stats?userId=...` | Tab stats + visited URLs | Query: `userId` | None |
454
- | DELETE | `/tabs/:tabId` | Close a tab (expects JSON body: `{ "userId": "..." }`) | Body: `userId` | None |
455
- | DELETE | `/tabs/group/:listItemId` | Close a tab group (expects JSON body: `{ "userId": "..." }`) | Body: `userId` | None |
456
- | DELETE | `/sessions/:userId` | Close all sessions for a user | Path: `userId` | None |
506
+ | DELETE | `/tabs/:tabId` | Close a tab (expects JSON body: `{ "userId": "..." }`) | Body: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
507
+ | DELETE | `/tabs/group/:listItemId` | Close a tab group (expects JSON body: `{ "userId": "..." }`) | Body: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
508
+ | DELETE | `/sessions/:userId` | Close all sessions for a user | Path: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
509
+ | POST | `/sessions/:userId/toggle-display` | Toggle display mode (headless/headed/virtual) | Path: `userId`; Body: `{ "headless": true\|false\|"virtual" }` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
457
510
  | GET | `/tabs/:tabId/cookies` | Export tab cookies | Query: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
458
511
  | GET | `/tabs/:tabId/downloads` | List tab downloads | Query: `userId` | None |
459
512
  | GET | `/users/:userId/downloads` | List user downloads | Path: `userId` | None |
460
513
  | GET | `/downloads/:downloadId` | Download metadata | Query: `userId` | None |
461
514
  | GET | `/downloads/:downloadId/content` | Stream download content | Query: `userId` | None |
462
- | DELETE | `/downloads/:downloadId` | Delete tracked download | Body or Query: `userId` | None |
463
- | POST | `/tabs/:tabId/extract-resources` | Extract downloadable resources | Body: `userId` | None |
464
- | POST | `/tabs/:tabId/batch-download` | Batch download resources | Body: `userId` | None |
515
+ | DELETE | `/downloads/:downloadId` | Delete tracked download | Body or Query: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
516
+ | POST | `/tabs/:tabId/extract-resources` | Extract downloadable resources | Body: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
517
+ | POST | `/tabs/:tabId/batch-download` | Batch download resources | Body: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
465
518
  | POST | `/tabs/:tabId/resolve-blobs` | Resolve blob URLs to base64 | Body: `userId` + `urls[]` | None |
466
519
  | POST | `/tabs/:tabId/trace/start` | Start trace recording | Body: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
467
520
  | POST | `/tabs/:tabId/trace/stop` | Stop and save trace ZIP | Body: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
468
521
  | POST | `/tabs/:tabId/trace/chunk/start` | Start trace chunk | Body: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
469
522
  | POST | `/tabs/:tabId/trace/chunk/stop` | Stop chunk and save ZIP | Body: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
470
523
  | GET | `/tabs/:tabId/trace/status` | Check trace status | Query: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
524
+ | GET | `/sessions/:userId/traces` | List managed trace ZIPs for a user | Path: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
525
+ | GET | `/sessions/:userId/traces/:filename` | Download a managed trace ZIP | Path: `userId`, `filename` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
526
+ | DELETE | `/sessions/:userId/traces/:filename` | Delete a managed trace ZIP | Path: `userId`, `filename` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
471
527
  | GET | `/tabs/:tabId/console` | Get console messages | Query: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
472
528
  | GET | `/tabs/:tabId/errors` | Get uncaught JS errors | Query: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
473
529
  | POST | `/tabs/:tabId/console/clear` | Clear console + errors | Body or Query: `userId` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
530
+ | POST | `/tabs/:tabId/extract-structured` | Extract deterministic JSON from a structured schema | Body: `userId` + `schema` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
474
531
 
475
532
  ### Toggle Display Mode
476
533
  ```bash
477
534
  POST /sessions/:userId/toggle-display
478
535
  {"headless": "virtual"}
479
536
  ```
537
+ **Auth:** Conditional — requires `Authorization: Bearer $CAMOFOX_API_KEY` when `CAMOFOX_API_KEY` is set.
480
538
  Switch browser between headless and headed mode. When encountering CAPTCHAs or issues requiring visual interaction, switch to headed mode to show the browser window.
481
539
 
482
540
  Returns:
@@ -538,12 +596,75 @@ OpenClaw-compatible aliases (used by the OpenClaw plugin).
538
596
  | Method | Endpoint | Description | Required | Auth |
539
597
  |--------|----------|-------------|----------|------|
540
598
  | GET | `/` | Status (alias of `/health`) | None | None |
541
- | POST | `/tabs/open` | Open tab (OpenClaw request/response shape) | Body: `userId` + `url` | None |
599
+ | POST | `/tabs/open` | Open tab (OpenClaw request/response shape) | Body: `userId` + `url` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
542
600
  | POST | `/start` | Start browser engine | None | None |
543
601
  | POST | `/stop` | Stop browser engine | None | `x-admin-key: $CAMOFOX_ADMIN_KEY` |
544
- | POST | `/navigate` | Navigate (OpenClaw request shape: `targetId` in body) | Body: `userId` + `targetId` + `url` | None |
602
+ | POST | `/navigate` | Navigate (OpenClaw request shape: `targetId` in body) | Body: `userId` + `targetId` + `url` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
545
603
  | GET | `/snapshot?userId=...&targetId=...` | Snapshot (OpenClaw response shape) | Query: `userId` + `targetId` | None |
546
- | POST | `/act` | Combined actions (`click`, `type`, `press`, `scroll`, `scrollIntoView`, `hover`, `wait`, `close`) | Body: `userId` + `targetId` + `kind` | None |
604
+ | POST | `/act` | Combined actions (`click`, `type`, `press`, `scroll`, `scrollIntoView`, `hover`, `wait`, `close`, `extractStructured`) | Body: `userId` + `targetId` + `kind` | Conditional: `Authorization: Bearer $CAMOFOX_API_KEY` |
605
+
606
+ ### Structured Extract
607
+
608
+ Structured extract returns deterministic JSON from a DOM schema without arbitrary JavaScript. Use it when you want stable data contracts instead of ad-hoc `evaluate()` calls.
609
+
610
+ Core API:
611
+
612
+ ```bash
613
+ curl -X POST "$CAMOFOX_URL/tabs/$TAB_ID/extract-structured" \
614
+ -H 'Content-Type: application/json' \
615
+ -d '{
616
+ "userId": "agent1",
617
+ "schema": {
618
+ "kind": "object",
619
+ "fields": {
620
+ "title": { "kind": "text", "selector": "h1", "required": true, "trim": true },
621
+ "products": {
622
+ "kind": "list",
623
+ "selector": ".product",
624
+ "item": {
625
+ "kind": "object",
626
+ "fields": {
627
+ "name": { "kind": "text", "selector": ".name", "required": true, "trim": true },
628
+ "href": { "kind": "url", "selector": "a.product-link", "attr": "href", "required": true }
629
+ }
630
+ }
631
+ }
632
+ }
633
+ }
634
+ }'
635
+ ```
636
+
637
+ CLI:
638
+
639
+ ```bash
640
+ camofox extract-structured @schema.json <tabId> --user <userId> --format json
641
+ ```
642
+
643
+ OpenClaw:
644
+
645
+ ```bash
646
+ curl -X POST "$CAMOFOX_URL/act" \
647
+ -H 'Content-Type: application/json' \
648
+ -d '{
649
+ "kind": "extractStructured",
650
+ "targetId": "tab-123",
651
+ "userId": "agent1",
652
+ "schema": {
653
+ "kind": "object",
654
+ "fields": {
655
+ "title": { "kind": "text", "selector": "h1", "required": true }
656
+ }
657
+ }
658
+ }'
659
+ ```
660
+
661
+ Notes:
662
+
663
+ - invalid schemas fail with HTTP 400
664
+ - required runtime misses fail the whole request with HTTP 422 and `fieldPath`
665
+ - optional scalar/object/list nodes normalize to `null` / `null` / `[]`
666
+ - selectors must be CSS; no XPath, arbitrary JavaScript, or AI extraction
667
+ - raw resource extraction and structured extraction stay separate on purpose
547
668
 
548
669
  ## Search Macros
549
670
 
@@ -591,6 +712,119 @@ curl -X POST http://localhost:9377/tabs \
591
712
 
592
713
  Custom presets: set `CAMOFOX_PRESETS_FILE=/path/to/presets.json` (JSON object; keys become preset names).
593
714
 
715
+ ## Session-Level Proxy and Geo Overrides
716
+
717
+ CamoFox supports session-level proxy and geolocation configuration with a hybrid model that combines server defaults with per-session overrides.
718
+
719
+ ### Proxy Configuration Model
720
+
721
+ **Server-level baseline** (via environment variables):
722
+ - `PROXY_HOST`, `PROXY_PORT`, `PROXY_USERNAME`, `PROXY_PASSWORD` — applied as the default for all sessions
723
+ - Enables Camoufox geoip mode when configured
724
+
725
+ **Session-level overrides** (via `POST /tabs` or CLI):
726
+ - `proxyProfile` — select a named proxy profile from `CAMOFOX_PROXY_PROFILES_FILE`
727
+ - `proxy` — provide raw proxy fields (`host`, `port`, `username`, `password`) directly
728
+ - Session-level proxy overrides the server baseline for that specific `userId + sessionKey` combination
729
+
730
+ **Session identity rules**:
731
+ - The same `userId` may run different `sessionKey` profiles in parallel with different proxy/geo configurations
732
+ - The same `userId + sessionKey` combination maintains a stable proxy/geo identity — requests with conflicting proxy/geo fields are rejected
733
+ - Session reuse and cleanup scope proxy/geo identity by `userId + sessionKey`, not just `userId`
734
+
735
+ ### Geo Mode Behavior
736
+
737
+ CamoFox offers two geo modes that control how explicit geo fields (locale, timezone, geolocation) interact with proxy-derived geo:
738
+
739
+ **`geoMode=explicit-wins`** (default):
740
+ - Explicit geo fields (locale, timezone, geolocation) remain authoritative
741
+ - Proxy-derived geo suggestions are ignored
742
+ - Use this mode when you want precise geo control regardless of proxy location
743
+
744
+ **`geoMode=proxy-locked`**:
745
+ - Explicit geo fields that conflict with proxy-derived geo are rejected
746
+ - Proxy-derived geo is authoritative
747
+ - Use this mode to ensure geo consistency with proxy exit location
748
+
749
+ ### CLI Examples
750
+
751
+ Session-level proxy with named profile:
752
+ ```bash
753
+ camofox open https://example.com --proxy-profile tokyo-exit --user agent1
754
+ ```
755
+
756
+ Session-level proxy with raw fields:
757
+ ```bash
758
+ camofox open https://example.com \
759
+ --proxy-host proxy.example.com \
760
+ --proxy-port 8080 \
761
+ --proxy-username user \
762
+ --proxy-password pass \
763
+ --user agent1
764
+ ```
765
+
766
+ Combine proxy with geo mode:
767
+ ```bash
768
+ camofox open https://example.com \
769
+ --proxy-profile london-exit \
770
+ --geo uk \
771
+ --geo-mode proxy-locked \
772
+ --user agent1
773
+ ```
774
+
775
+ ### API Examples
776
+
777
+ Using a named proxy profile with explicit geo:
778
+ ```bash
779
+ curl -X POST http://localhost:9377/tabs \
780
+ -H 'Content-Type: application/json' \
781
+ -d '{
782
+ "userId": "agent1",
783
+ "sessionKey": "task1",
784
+ "url": "https://example.com",
785
+ "proxyProfile": "tokyo-exit",
786
+ "preset": "japan",
787
+ "geoMode": "explicit-wins"
788
+ }'
789
+ ```
790
+
791
+ Using raw proxy fields with proxy-locked geo:
792
+ ```bash
793
+ curl -X POST http://localhost:9377/tabs \
794
+ -H 'Content-Type: application/json' \
795
+ -d '{
796
+ "userId": "agent1",
797
+ "sessionKey": "task2",
798
+ "url": "https://example.com",
799
+ "proxy": {
800
+ "host": "proxy.example.com",
801
+ "port": 8080,
802
+ "username": "user",
803
+ "password": "pass"
804
+ },
805
+ "geoMode": "proxy-locked"
806
+ }'
807
+ ```
808
+
809
+ ### Named Proxy Profiles
810
+
811
+ Define proxy profiles in a JSON file and point `CAMOFOX_PROXY_PROFILES_FILE` to it:
812
+
813
+ ```json
814
+ {
815
+ "tokyo-exit": {
816
+ "server": "http://tokyo.proxy.example.com:8080",
817
+ "username": "user",
818
+ "password": "pass"
819
+ },
820
+ "london-exit": {
821
+ "server": "http://london.proxy.example.com:8080"
822
+ }
823
+ }
824
+ ```
825
+
826
+ Then use profiles by name in API requests or CLI commands.
827
+
594
828
  ## Environment Variables
595
829
 
596
830
  | Variable | Default | Description |
@@ -598,8 +832,10 @@ Custom presets: set `CAMOFOX_PRESETS_FILE=/path/to/presets.json` (JSON object; k
598
832
  | `CAMOFOX_PORT` | `9377` | Server port |
599
833
  | `PORT` | (optional) | Alternative port env var (common in PaaS) |
600
834
  | `NODE_ENV` | `development` | Node environment |
835
+ | `CAMOFOX_HOST` | `127.0.0.1` | Server bind host. Set `0.0.0.0` for Docker/PaaS/network exposure. Non-loopback binds require `CAMOFOX_API_KEY`. |
601
836
  | `CAMOFOX_ADMIN_KEY` | (empty) | Required for `POST /stop` (sent via `x-admin-key`) |
602
- | `CAMOFOX_API_KEY` | (empty) | Enables cookie import endpoint; sent via `Authorization: Bearer ...` |
837
+ | `CAMOFOX_API_KEY` | (empty) | Guards protected endpoints (tab creation, navigation, interaction, session management, downloads, image extraction, tracing, console) via `Authorization: Bearer` header when set. Required whenever `CAMOFOX_HOST` exposes the server beyond loopback. |
838
+ | `CAMOFOX_ALLOW_PRIVATE_NETWORK` | `true` on loopback binds, `false` otherwise | Allows navigation to loopback/private/link-local/metadata targets. Leave unset for the safe default; enable only for trusted deployments that intentionally need internal-network reachability. |
603
839
  | `CAMOFOX_HEADLESS` | `true` | Display mode: `true` (headless), `false` (headed), `virtual` (Xvfb) |
604
840
  | `CAMOFOX_VNC_RESOLUTION` | `1920x1080x24` | Virtual Xvfb display resolution (`WIDTHxHEIGHTxDEPTH`) |
605
841
  | `CAMOFOX_VNC_TIMEOUT_MS` | `120000` | Max VNC session duration in ms before auto-stop |
@@ -618,15 +854,17 @@ Custom presets: set `CAMOFOX_PRESETS_FILE=/path/to/presets.json` (JSON object; k
618
854
  | `CAMOFOX_VNC_BASE_PORT` | `6080` | noVNC/websockify base port |
619
855
  | `CAMOFOX_VNC_HOST` | `localhost` | noVNC host in returned URL |
620
856
  | `CAMOFOX_CLI_USER` | `cli-default` | Default CLI user id |
621
- | `CAMOFOX_IDLE_TIMEOUT_MS` | `1800000` | CLI server idle timeout |
857
+ | `CAMOFOX_IDLE_TIMEOUT_MS` | `1800000` | Stage 1 idle cleanup threshold (ms) |
858
+ | `CAMOFOX_IDLE_EXIT_TIMEOUT_MS` | `1800000` | Stage 2 daemon exit quiet window (ms, defaults to match Stage 1) |
622
859
  | `CAMOFOX_PRESETS_FILE` | (unset) | Optional JSON file defining/overriding geo presets |
860
+ | `CAMOFOX_PROXY_PROFILES_FILE` | (unset) | Optional JSON file defining named proxy profiles for session-level overrides |
623
861
  | `CAMOFOX_SESSION_TIMEOUT` | `1800000` | Session idle timeout in ms (min `60000`) |
624
862
  | `CAMOFOX_MAX_SESSIONS` | `50` | Maximum concurrent sessions |
625
863
  | `CAMOFOX_MAX_TABS` | `10` | Maximum tabs per session |
626
- | `PROXY_HOST` | (empty) | Proxy host (enables proxy routing) |
627
- | `PROXY_PORT` | (empty) | Proxy port |
628
- | `PROXY_USERNAME` | (empty) | Proxy username |
629
- | `PROXY_PASSWORD` | (empty) | Proxy password |
864
+ | `PROXY_HOST` | (empty) | Proxy host (server-level default; enables proxy routing) |
865
+ | `PROXY_PORT` | (empty) | Proxy port (server-level default) |
866
+ | `PROXY_USERNAME` | (empty) | Proxy username (server-level default) |
867
+ | `PROXY_PASSWORD` | (empty) | Proxy password (server-level default) |
630
868
  | `CAMOFOX_MAX_SNAPSHOT_CHARS` | `80000` | Max characters in snapshot before truncation |
631
869
  | `CAMOFOX_SNAPSHOT_TAIL_CHARS` | `5000` | Characters preserved at end of truncated snapshot |
632
870
  | `CAMOFOX_BUILDREFS_TIMEOUT_MS` | `12000` | Timeout for building element refs |
@@ -635,6 +873,34 @@ Custom presets: set `CAMOFOX_PRESETS_FILE=/path/to/presets.json` (JSON object; k
635
873
  | `CAMOFOX_FAILURE_THRESHOLD` | `3` | Consecutive failures before health degradation |
636
874
  | `CAMOFOX_YT_DLP_TIMEOUT_MS` | `30000` | Timeout for yt-dlp subtitle extraction |
637
875
  | `CAMOFOX_YT_BROWSER_TIMEOUT_MS` | `25000` | Timeout for browser transcript fallback |
876
+ | `CAMOFOX_OS` | (unset) | Optional server-wide Camoufox OS override (`windows`, `macos`, `linux`, or comma-separated list for randomization) |
877
+ | `CAMOFOX_ALLOW_WEBGL` | (unset) | Optional server-wide WebGL override; malformed values fail startup |
878
+ | `CAMOFOX_SCREEN_WIDTH` | (unset) | Optional screen width override; applied only with `CAMOFOX_SCREEN_HEIGHT` |
879
+ | `CAMOFOX_SCREEN_HEIGHT` | (unset) | Optional screen height override; applied only with `CAMOFOX_SCREEN_WIDTH` |
880
+ | `CAMOFOX_HUMANIZE` | (unset) | Optional server-wide humanization override |
881
+
882
+ > `CAMOFOX_OS` and `CAMOFOX_SCREEN_*` are **generation-time** controls: they affect only newly generated fingerprints and have no effect while an existing `fingerprint.json` sidecar is in use. Reset the profile or delete `fingerprint.json` to force regeneration under the new defaults. `CAMOFOX_ALLOW_WEBGL` and `CAMOFOX_HUMANIZE` are **launch-time** overrides and apply on every browser launch regardless of whether a sidecar is reused.
883
+
884
+ ### Idle Lifecycle Policy
885
+
886
+ CamoFox implements a two-stage idle lifecycle for graceful cleanup and daemon exit:
887
+
888
+ **Stage 1 — Idle Cleanup**
889
+ - After `CAMOFOX_IDLE_TIMEOUT_MS` of idle time (default: 30 minutes), the server runs cleanup to close idle sessions and tabs
890
+ - Cleanup is delayed if browser contexts are launching or sessions are being created
891
+ - New interactive activity (tab creation, navigation, interaction) cancels any pending cleanup
892
+
893
+ **Stage 2 — Daemon Exit**
894
+ - After Stage 1 cleanup completes, the server waits for `CAMOFOX_IDLE_EXIT_TIMEOUT_MS` (default: matches Stage 1 timeout)
895
+ - If no new activity occurs during this quiet window, the daemon process exits gracefully
896
+ - Any new request activity cancels the pending exit timer
897
+
898
+ **Activity detection**:
899
+ - Live tabs, launching browser contexts, or staged session creation count as active work and prevent cleanup
900
+ - Empty sessions (sessions with no tabs) do not block cleanup but do disarm pending daemon exit
901
+ - New interactive activity resets both cleanup and exit timers
902
+
903
+ This two-stage model ensures cleanup runs before daemon exit, preventing resource leaks while allowing the server to shut down cleanly when fully idle.
638
904
 
639
905
  ## Deployment
640
906
 
@@ -644,7 +910,9 @@ Custom presets: set `CAMOFOX_PRESETS_FILE=/path/to/presets.json` (JSON object; k
644
910
  docker build -t camofox-browser .
645
911
  docker run -p 9377:9377 -p 6080:6080 \
646
912
  -v ~/.camofox:/home/node/.camofox \
913
+ -e CAMOFOX_HOST=0.0.0.0 \
647
914
  -e CAMOFOX_PORT=9377 \
915
+ -e CAMOFOX_API_KEY=change-me \
648
916
  camofox-browser
649
917
  ```
650
918
 
@@ -660,6 +928,8 @@ fly deploy
660
928
  ### Railway
661
929
 
662
930
  - Create a new project → deploy from this GitHub repo
931
+ - Set `CAMOFOX_HOST=0.0.0.0`
932
+ - Set `CAMOFOX_API_KEY` to a strong secret
663
933
  - Set `CAMOFOX_PORT=9377` (Railway will also provide `PORT`, which is supported)
664
934
  - Ensure the service exposes port `9377`
665
935
 
@@ -667,6 +937,8 @@ fly deploy
667
937
 
668
938
  - Create a new Web Service → deploy from this GitHub repo
669
939
  - Use Docker (recommended) and expose port `9377`
940
+ - Set `CAMOFOX_HOST=0.0.0.0`
941
+ - Set `CAMOFOX_API_KEY` to a strong secret
670
942
  - Set `CAMOFOX_PORT=9377` (or rely on Render `PORT`)
671
943
 
672
944
  ### System Requirements
@@ -747,4 +1019,3 @@ This project is based on [camofox-browser](https://github.com/jo-inc/camofox-bro
747
1019
  ## Crypto Scam Warning
748
1020
 
749
1021
  Sketchy people are doing sketchy things with crypto tokens named "Camofox" now that this project is getting attention. **Camofox is not a crypto project and will never be one.** Any token, coin, or NFT using the Camofox name has nothing to do with us.
750
-
@@ -1 +1 @@
1
- {"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/content.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAgE3C,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,GAAG,IAAI,CA0RnF"}
1
+ {"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/content.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAkF3C,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,GAAG,IAAI,CAoTnF"}