capiumbrowser 0.1.0 → 0.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 (2) hide show
  1. package/README.md +674 -117
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,19 +1,76 @@
1
- <h3 align="center">Capium — a stealth Chromium built to withstand bot detection, for Node.js.</h3>
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/capzy-ai/capiumbrowser/main/assets/capzy-banner.png" alt="Capium — stealth Chromium for Playwright and Puppeteer" width="820">
3
+ </p>
4
+
5
+ <p align="center">
6
+ <a href="https://www.npmjs.com/package/capiumbrowser"><img src="https://img.shields.io/npm/v/capiumbrowser?color=cb3837" alt="npm"></a>
7
+ <img src="https://img.shields.io/badge/node-18%2B-brightgreen" alt="Node 18+">
8
+ <img src="https://img.shields.io/badge/drivers-Playwright%20%C2%B7%20Puppeteer-45ba4b" alt="Playwright / Puppeteer">
9
+ <a href="https://docs.capiumbrowser.com"><img src="https://img.shields.io/badge/docs-capiumbrowser.com-6741d9" alt="Docs"></a>
10
+ <a href="https://capiumbrowser.com"><img src="https://img.shields.io/badge/website-capiumbrowser.com-1c7ed6" alt="Website"></a>
11
+ </p>
12
+
13
+ <h3 align="center">A stealth Chromium built to withstand bot detection — because it's a real browser.</h3>
14
+
15
+ <table><tr><td>
16
+ Not a patched config. Not a JavaScript injection. A real Chromium binary whose fingerprints are rewritten at the <strong>C++ source level</strong> and compiled in. Page scripts that hunt for injected hooks find nothing to catch — the values a site reads <em>are</em> the persona's values, produced by the engine. Drive it with the <strong>Playwright</strong> or <strong>Puppeteer</strong> API you already know.
17
+ </td></tr></table>
18
+
19
+ <p align="center">
20
+ <sub>Say hi to <b>Capzy</b> 🕵️ — the stealth little guy who helps your automation blend in.</sub>
21
+ </p>
2
22
 
3
23
  <p align="center">
4
24
  <a href="https://capiumbrowser.com">capiumbrowser.com</a> ·
5
25
  <a href="https://docs.capiumbrowser.com">Documentation</a> ·
6
26
  <a href="https://capiumbrowser.com/#pricing">Pricing</a> ·
7
- <a href="https://github.com/capzy-ai/capiumbrowser">Product overview</a> ·
8
- <a href="https://pypi.org/project/capiumbrowser/">Python SDK</a>
27
+ <a href="https://capiumbrowser.com/#demo">Demo</a> ·
28
+ <a href="https://github.com/capzy-ai/capiumbrowser/tree/main/examples">Examples</a>
9
29
  </p>
10
30
 
11
31
  ---
12
32
 
13
- Not a patched config. Not a JavaScript injection. A real Chromium binary whose fingerprints are
14
- rewritten at the **C++ source level** and compiled in. Page scripts that hunt for injected hooks
15
- find nothing to catch — the values a site reads *are* the persona's values, produced by the
16
- engine. Drive it with the **Playwright** or **Puppeteer** API you already know.
33
+ **`npm install capiumbrowser playwright-core`** (or **`puppeteer-core`**) · CLI: `npx capiumbrowser`
34
+
35
+ > Using Python? The same browser ships as a [PyPI package](https://pypi.org/project/capiumbrowser/) with the same options.
36
+
37
+ - **Source-level C++ stealth** — User-Agent & UA-CH, WebGL/GPU, canvas, audio, screen, hardware, fonts, voices, WebRTC, `navigator.webdriver`, DevTools, pointer, client-rects — all rewritten **in the browser's own source**, below the JavaScript layer.
38
+ - **Coherent per-seed identities** — one integer **seed** derives a complete, self-consistent device (OS, GPU, cores, memory, screen, fonts, UA). Same seed ⇒ same machine, on any host, every run.
39
+ - **`humanize: true`** — attaches `page.humanMove` / `humanClick` / `humanType` / `humanScroll`: curved, human-timed mouse, keyboard, and scroll input.
40
+ - **`geoip: true`** — the binary resolves its own exit IP through your proxy and pins timezone, WebRTC IP, geolocation, and `navigator.languages` to match. The clock, locale, and IP all tell one story.
41
+ - **Plain drivers over CDP** — no patched driver, no init-script signature, no `Object.defineProperty` shim to detect. Update the engine with `npm i -U playwright-core` (or `puppeteer-core`).
42
+ - **Always the latest binary** — one license key fetches the newest checksum-verified build for your platform and reuses it thereafter.
43
+ - **Free tier — 1 concurrent session.** Paid tiers raise the concurrent-session cap. [Start free →](https://capiumbrowser.com)
44
+
45
+ ```js
46
+ const { launchContext } = require('capiumbrowser'); // auto-detects the installed driver
47
+
48
+ const { browser, page } = await launchContext({
49
+ seed: 200123, // a coherent, repeatable device
50
+ proxy: 'http://user:pass@host:port', geoip: true, // exit IP + matching tz/geo/WebRTC
51
+ humanize: true, // human-like clicks/typing/scrolls
52
+ url: 'https://fingerprint.com/demo/',
53
+ });
54
+
55
+ await page.humanType('#email', 'alex@example.com');
56
+ await page.humanClick('#submit');
57
+ await browser.close();
58
+ ```
59
+
60
+ > The `capiumbrowser` **npm package is open**; the **Capium browser binary is licensed** per concurrent session. There's a **free tier with 1 concurrent session** — see [Licensing](#licensing).
61
+
62
+ ---
63
+
64
+ ## Table of contents
65
+
66
+ - [Install](#install) · [Why Capium](#why-capium) · [Licensing & tiers](#licensing)
67
+ - [What a persona reads](#what-a-persona-reads) · [How it works](#how-it-works)
68
+ - [API](#api) · [Options](#options) · [Personas & seeds](#personas--seeds) · [Fingerprint switches](#fingerprint-switches)
69
+ - [Human behavior](#human-behavior) · [Proxies & geo](#proxies--geo) · [Fonts](#fonts)
70
+ - [Framework integrations](#framework-integrations) · [Deployment](#deployment) · [Platforms](#platforms)
71
+ - [CLI](#cli--environment) · [Troubleshooting](#troubleshooting) · [FAQ](#faq) · [Security](#security) · [License](#license)
72
+
73
+ ---
17
74
 
18
75
  ## Install
19
76
 
@@ -25,150 +82,650 @@ npm install capiumbrowser playwright-core
25
82
  npm install capiumbrowser puppeteer-core
26
83
  ```
27
84
 
28
- The driver is a normal peer dependency, so you update the engine independently
29
- (`npm install -U playwright-core`). You do **not** run `npx playwright install chromium` —
30
- Capium ships its own binary. On first launch the SDK fetches the per-platform build from the
31
- license service (authenticated, checksum-verified) and caches it under `~/.capium`
32
- (`CAPIUM_HOME` overrides).
85
+ The driver is an **optional peer dependency** — install whichever you use (or both) and update
86
+ it independently. On Linux, install Chromium's OS libraries once:
87
+ `npx playwright-core install-deps chromium` (covers Puppeteer setups too).
33
88
 
34
- ## Quick start
89
+ You do **not** run `npx playwright install chromium` — Capium ships its own binary. On first
90
+ launch the SDK fetches the per-platform build from the license service (authenticated,
91
+ checksum-verified) and caches it under `~/.capium` (`CAPIUM_HOME` overrides — it deliberately
92
+ lives *outside* `node_modules`, so reinstalls never delete it).
35
93
 
36
- ```js
37
- // Auto-detects the installed driver (Playwright preferred when both are present):
38
- const { launchContext } = require('capiumbrowser');
94
+ **Migrating?** It's a one-line change — the returned object is a standard Playwright /
95
+ Puppeteer `Browser`:
39
96
 
40
- // ...or pick one explicitly:
41
- // const { launchContext } = require('capiumbrowser/playwright');
42
- // const { launchContext } = require('capiumbrowser/puppeteer');
97
+ ```diff
98
+ - const { chromium } = require('playwright-core');
99
+ - const browser = await chromium.launch();
100
+ + const { launch } = require('capiumbrowser/playwright');
101
+ + const browser = await launch({ seed: 200123 });
43
102
 
44
- const { browser, page } = await launchContext({
45
- seed: 200123, // a coherent, repeatable device
46
- platform: 'windows', // the spoofed OS persona
47
- proxy: 'http://user:pass@host:port',
48
- geoip: true, // exit IP + matching tz/geo/WebRTC
49
- humanize: true, // human-like clicks/typing/scrolls
50
- url: 'https://fingerprint.com/demo/',
51
- });
103
+ const page = await browser.newPage();
104
+ await page.goto('https://example.com'); // the rest of your code is unchanged
105
+ ```
52
106
 
53
- await page.humanType('#email', 'alex@example.com');
54
- await page.humanClick('#submit');
55
- await browser.close();
107
+ ```diff
108
+ - const puppeteer = require('puppeteer');
109
+ - const browser = await puppeteer.launch();
110
+ + const { launch } = require('capiumbrowser/puppeteer');
111
+ + const browser = await launch({ seed: 200123 });
112
+ ```
113
+
114
+ > ⭐ **Star** [the repo](https://github.com/capzy-ai/capiumbrowser) to follow along — Capium tracks Chrome closely and ships new builds as detection evolves.
115
+
116
+ ---
117
+
118
+ ## Why Capium
119
+
120
+ - **Config-level stealth breaks.** `puppeteer-extra-plugin-stealth`, patched drivers, and
121
+ friends inject JavaScript or flip flags. Every Chrome update breaks them, and modern
122
+ anti-bot ML detects the patches themselves — the very act of hiding trips the alarm.
123
+ - **Capium patches Chromium source.** Fingerprints are modified at the C++ level and compiled
124
+ into the binary. Detection sites see a real browser because it *is* one — no init script,
125
+ no `toString` tampering, no CDP hooks to sniff.
126
+ - **Coherence is the product.** A convincing device isn't one clean signal; it's *every*
127
+ signal telling the same story. Capium derives GPU, screen, fonts, UA-CH, timezone, locale,
128
+ and WebRTC from a single seed + your proxy's geography, so nothing contradicts anything else.
129
+ - **Same behavior everywhere.** Local, Docker, VPS, Lambda — no environment-specific config.
130
+ - **Works with your stack.** Drop-in stealth for Crawlee, @playwright/test,
131
+ puppeteer-cluster, and anything that speaks CDP. See [integrations](#framework-integrations).
132
+
133
+ Capium doesn't solve CAPTCHAs, and no stealth tool can promise you'll never see one. What a
134
+ coherent, real-browser fingerprint does is remove the automation tells that commonly *trigger*
135
+ challenges — it reduces friction, it doesn't guarantee a challenge-free session. No
136
+ CAPTCHA-solving services, no built-in proxy rotation: bring your own proxies and use the
137
+ driver API you already know.
138
+
139
+ > **Responsible use.** Capium is a stealth browser for legitimate automation, testing, QA, and research.
140
+ > It makes **no guarantee** of evading any particular bot-detection or anti-fraud system, and results vary
141
+ > by site, proxy, and configuration. You are responsible for complying with the terms of service of the
142
+ > sites you access and with all applicable laws.
143
+
144
+ ---
145
+
146
+ ## Licensing
147
+
148
+ The **browser binary is licensed per concurrent session** — each running browser holds one seat, freed the
149
+ moment it closes. Installing or activating on many machines is free; only *live* sessions count, across all
150
+ your machines. The `capiumbrowser` SDK never holds a seat itself.
151
+
152
+ | Tier | Concurrent sessions | For |
153
+ |---|---|---|
154
+ | **Free** | 1 | Trying it, one browser at a time |
155
+ | **Solo** | 5 | Solo projects |
156
+ | **Team** | 20 | Small teams |
157
+ | **Business** | 200 | Production scraping / QA / monitoring |
158
+ | **Scale** | 2,000+ | High-volume automation |
159
+
160
+ See **[capiumbrowser.com/#pricing](https://capiumbrowser.com/#pricing)** for current pricing and to create a key.
161
+
162
+ ### Get a key
163
+
164
+ 1. Create an account at **[capiumbrowser.com](https://capiumbrowser.com)** and create a license (start with the
165
+ free 1-session tier). Keys look like `cap_XXXXXXXXXXXXXXXXXXXXXXXX`.
166
+ 2. Make it available to the SDK any one way (checked in this order):
167
+
168
+ ```bash
169
+ export CAPIUM_LICENSE_KEY="cap_xxxxxxxxxxxxxxxxxxxx"
170
+ # optional — defaults to https://license.capzy.ai
171
+ export CAPIUM_LICENSE_SERVER="https://license.capzy.ai"
172
+ ```
173
+
174
+ …or a file at `~/.capium/license` (chmod 600) with a `KEY=cap_…` line, or pass
175
+ `launch({ licenseKey: 'cap_…' })`.
176
+
177
+ The **same key gates the binary download**. The key is passed to the browser **via the
178
+ environment**, never on the command line (so it can't leak through `ps`). Check entitlements
179
+ without spending a session:
180
+
181
+ ```bash
182
+ npx capiumbrowser status
183
+ # plan: free sessions_cap: 1 live_sessions: 0 period_end: ...
56
184
  ```
57
185
 
58
- The returned objects are standard Playwright / Puppeteer objects — the rest of your code is
59
- unchanged.
186
+ Handle license errors with typed error classes — `CapiumSeatLimitError`, `CapiumExpiredError`,
187
+ `CapiumServerDownError`, `CapiumConfigError` (all subclass `CapiumLicenseError` → `CapiumError`). Full model:
188
+ [docs.capiumbrowser.com](https://docs.capiumbrowser.com).
189
+
190
+ ---
191
+
192
+ ## What a persona reads
193
+
194
+ On a **matching-OS host** (a Windows persona on Windows, a macOS persona on macOS), a Capium persona reads
195
+ clean against a modern fingerprinting suite — with the correct GPU, fonts, and voices for the claimed device:
196
+
197
+ | Signal | Stock driver Chromium | Capium |
198
+ |---|---|---|
199
+ | `navigator.webdriver` | `true` | **not flagged** (source-level) |
200
+ | FingerprintJS **bot detection** | detected | **not detected** |
201
+ | FingerprintJS **tampering / anti-detect** | — | **false** |
202
+ | DevTools/CDP console tell (FPJS `developer_tools`) | detected | **false** |
203
+ | User-Agent | `HeadlessChrome/…` | **`Chrome/152.0.0.0`** |
204
+ | `window.chrome` | thin / missing | **present, like real Chrome** |
205
+ | Google TTS voices | absent | **present (matches real Chrome)** |
206
+ | JA4 TLS fingerprint | differs from Chrome | **matches stock Chrome** |
207
+ | WebRTC IP behind a proxy | real IP leaks | **pinned to the proxy exit** |
208
+
209
+ > **Honesty matters more than a green screenshot.** A **GPU-less headless Linux** box makes WebGL fall back
210
+ > to SwiftShader, which any modern suite (and stock Chrome) flags as `virtual_machine` / `anti_detect` — an
211
+ > artifact of the *host*, not the browser. Run **headed** (Xvfb is fine) on a GPU-backed, matching-OS host
212
+ > for the clean verdict. And `os_mismatch` is a **network** signal — genuine Chrome trips it behind some
213
+ > proxies/NATs too, so treat it as a routing concern, not a browser one.
214
+
215
+ ---
216
+
217
+ ## How it works
218
+
219
+ 1. **You install** → `npm install capiumbrowser playwright-core` (or `puppeteer-core`). This
220
+ downloads **nothing** but the SDK — the ~230 MB binary needs your license key, so it can't
221
+ be fetched at npm-install time.
222
+ 2. **First launch** → the license-gated binary auto-downloads for your platform
223
+ (checksum-verified) and caches under `~/.capium`. It's fetched **lazily** on that first
224
+ `launch()` — or eagerly with `npx capiumbrowser install`.
225
+ 3. **Every later launch** → the cached binary is reused instantly; the plain driver starts it with your seed.
226
+ 4. **Upgrade** → when a newer SDK bumps the target build, the next launch notices the cached
227
+ binary is a different version, **removes it, and downloads the new one** — no manual reinstall.
228
+
229
+ The spoofing lives in the compiled binary — not injected via JavaScript, not set via a detectable CDP
230
+ `Emulation` call. Identity comes from one seed; proxy, geolocation, timezone, WebRTC, and locale are all
231
+ aligned to a single coherent story.
232
+
233
+ **Download mechanics.** The binary is fetched from the license service with a signed, path-based GET
234
+ (`/download/distro/chromium-v<version>/capiumbrowser-<os>-<arch>.tar.gz`): the key travels in the
235
+ `X-Capzy-License` header (never the URL) and the request path is HMAC-signed. The response's
236
+ `X-Capzy-SHA256` is verified against the streamed bytes before extraction, so a corrupted or tampered
237
+ archive is rejected. Env overrides: `CAPIUM_LICENSE_KEY` (or `~/.capium/license`), `CAPIUM_VERSION` (target
238
+ a specific build), `CAPIUM_BINARY` (use an exact local binary, skip download), `CAPIUM_DOWNLOAD_URL`
239
+ (unsigned direct URL escape hatch), `CAPIUM_HOME` (where builds cache). A missing platform, an unpublished
240
+ version (404), a rejected license (401/403), an unreachable server, or a checksum mismatch each throw a
241
+ distinct, typed `Capium*` error.
242
+
243
+ ---
244
+
245
+ ## API
246
+
247
+ Everything is async. The root import auto-detects the installed driver (Playwright preferred
248
+ when both are present); pick one explicitly via the subpaths:
249
+
250
+ ```js
251
+ const capium = require('capiumbrowser'); // auto-detect
252
+ const pw = require('capiumbrowser/playwright'); // Playwright explicitly
253
+ const pptr = require('capiumbrowser/puppeteer'); // Puppeteer explicitly
254
+ ```
255
+
256
+ | Function | Returns | Use for |
257
+ |---|---|---|
258
+ | `launch(options)` | `Browser` | full control; create your own contexts/pages (they default to `viewport: null`) |
259
+ | `launchContext(options)` | `{browser, context?, page}` | one-liner: open a page, optionally navigate + humanize |
260
+ | `launchPersistentContext(dir, options)` | Playwright: `BrowserContext` · Puppeteer: `Browser` | **persistent** cookies/localStorage/login across runs |
261
+ | `buildLaunchOptions(options)` | plain object | hand the driver's own `launch()` (or any framework) the ready-made `{executablePath, args, env, …}` |
60
262
 
61
263
  ```js
62
- // Playwright: launch() -> Browser, launchPersistentContext(dir) -> BrowserContext
63
264
  const { launch, launchPersistentContext } = require('capiumbrowser/playwright');
64
- const browser = await launch({ seed: 42 });
65
- const page = await (await browser.newContext({ viewport: null })).newPage();
66
-
67
- // Puppeteer: launch() -> Browser (persistent profile via userDataDir)
68
- const pptr = require('capiumbrowser/puppeteer');
69
- const browser2 = await pptr.launch({ seed: 42, userDataDir: './profile' });
70
- ```
71
-
72
- ## Highlights
73
-
74
- - **Source-level C++ stealth** — User-Agent & UA-CH, WebGL/GPU, canvas, audio, screen,
75
- hardware, fonts, voices, WebRTC, `navigator.webdriver`, DevTools, pointer, client-rects —
76
- all rewritten **in the browser's own source**, below the JavaScript layer.
77
- - **Coherent per-seed identities** — one integer **seed** derives a complete, self-consistent
78
- device (OS, GPU, cores, memory, screen, fonts, UA). Same seed ⇒ same machine, every run.
79
- - **`humanize: true`** — attaches `page.humanMove/humanClick/humanType/humanScroll`: curved,
80
- human-timed mouse, keyboard, and scroll.
81
- - **`geoip: true`** — the binary resolves its own exit IP through your proxy and pins timezone,
82
- WebRTC IP, geolocation, and `navigator.languages` to match.
83
- - **Plain drivers over CDP** — no patched driver, no init-script signature, no
84
- `Object.defineProperty` shim to detect.
85
- - **Always the latest binary** — one license key fetches the newest checksum-verified build for
86
- your platform and reuses it thereafter.
87
-
88
- ## Options (both drivers)
89
-
90
- | Option | Default | Meaning |
91
- | --- | --- | --- |
92
- | `seed` | random | Identity seed; a stable, coherent device per seed |
93
- | `platform` | `"windows"` | Spoofed OS persona: `windows` \| `macos` \| `linux` |
94
- | `headless` | `false` | Windowed is the coherent persona default |
95
- | `proxy` | none | `"http://user:pass@host:port"`, `"socks5://host:port"`, or `{server, username, password, bypass}` |
96
- | `geoip` | off | `true` = pin tz/geo/WebRTC/language to the egress; `false` = explicit opt-out |
97
- | `timezone` / `locale` | — | Explicit overrides (IANA tz, BCP-47 locale; in-binary spoof) |
98
- | `stealthArgs` | `true` | `false` drops the default fingerprint flags |
99
- | `licenseKey` / `licenseServer` | env / `~/.capium/license` | Handed to the self-licensing binary via the environment, never argv |
100
-
101
- Remaining options are forwarded to the driver's own `launch()`.
102
-
103
- ### Framework integrations
104
-
105
- `buildLaunchOptions()` (on both subpaths) returns the ready-made options object for the
106
- driver's own `launch()`, for frameworks that must hold the launch themselves (Crawlee,
107
- custom pools):
265
+
266
+ // Full control
267
+ const browser = await launch({ seed: 200123, platform: 'windows', headless: false });
268
+
269
+ // Proxy + coherent geo (HTTP/HTTPS/SOCKS5, inline creds)
270
+ const b2 = await launch({ seed: 200123, proxy: 'socks5://user:pass@host:port', geoip: true });
271
+
272
+ // Explicit timezone/locale always win over geoip auto-detection
273
+ const b3 = await launch({ seed: 200123, proxy: 'http://host:port', geoip: true, timezone: 'Europe/London' });
274
+
275
+ // Persistent profile — stays logged in, avoids the "always fresh incognito" tell; extensions need this
276
+ const ctx = await launchPersistentContext('profiles/acct1', {
277
+ seed: 200123, platform: 'linux', extensionPaths: ['/path/to/unpacked-extension'],
278
+ });
279
+
280
+ // Bring your own flags — disable the defaults and build the command line yourself
281
+ const b4 = await launch({ stealthArgs: false, args: ['--fingerprint=200123', '--fingerprint-platform=linux'] });
282
+ ```
108
283
 
109
284
  ```js
285
+ // Framework escape hatch: you hold the launch, Capium supplies the options
110
286
  const { chromium } = require('playwright-core');
111
287
  const { buildLaunchOptions } = require('capiumbrowser/playwright');
112
- const browser = await chromium.launch(await buildLaunchOptions({ seed: 42 }));
288
+ const b5 = await chromium.launch(await buildLaunchOptions({ seed: 200123 }));
113
289
  ```
114
290
 
115
- ## License & binary
291
+ **Puppeteer specifics** — the same options, with Puppeteer-shaped defaults applied for you:
292
+ `defaultViewport: null` (the page tracks the real window), `--enable-automation` stripped from
293
+ the default args, and persistence via `launch({ userDataDir })` (Puppeteer has no separate
294
+ persistent-context API, so `launchPersistentContext(dir, opts)` is sugar for exactly that).
116
295
 
117
- The `capiumbrowser` npm package is open; the **Capium browser binary is licensed** per
118
- concurrent session (free tier: 1 concurrent session). Configure the key once:
296
+ ---
119
297
 
120
- ```bash
121
- export CAPIUM_LICENSE_KEY=cap_... # or ~/.capium/license with a KEY= line
298
+ ## Options
299
+
300
+ Unless noted, all of these work on **`launch`**, **`launchContext`**, and
301
+ **`launchPersistentContext`** (which forward everything to `launch`). Same options as the
302
+ Python SDK, in camelCase.
303
+
304
+ ### Identity & rendering
305
+
306
+ | Option | Type | Default | Description |
307
+ |---|---|---|---|
308
+ | `seed` | `number` \| `null` | `null` | Persona seed → a complete coherent device. `null` = fresh random seed each launch. The range selects the OS family (see [Personas & seeds](#personas--seeds)). |
309
+ | `platform` | `string` | `"windows"` | Spoofed OS: `"windows"` \| `"macos"` \| `"linux"`. Sets `--fingerprint-platform` and picks the seed range if you didn't. |
310
+ | `headless` | `boolean` | `false` | Headed is recommended (reads cleaner). On a server, run headed under Xvfb. |
311
+ | `stealthArgs` | `boolean` | `true` | Apply the default coherent fingerprint flags. Set `false` to build the whole command line yourself via `args`. |
312
+ | `args` | `string[]` | — | Extra raw Chrome flags appended verbatim (see [Fingerprint switches](#fingerprint-switches)). |
313
+
314
+ ### Proxy, geo & locale
315
+
316
+ | Option | Type | Default | Description |
317
+ |---|---|---|---|
318
+ | `proxy` | `string` \| `object` | — | HTTP/HTTPS/SOCKS5 URL with inline creds, or `{server, username, password, bypass}`. Credentials are URL-encoded and the **binary authenticates natively** (SOCKS5 RFC 1929; preemptive HTTP auth) — commas & special characters are safe. |
319
+ | `geoip` | `boolean` \| `null` | `null` | Geo coherence, resolved inside the binary. **`null`/omitted — OFF**: no lookup runs, even with a proxy (a proxy alone doesn't trigger it, so proxied launches aren't slowed). **`true`** — ON: pins timezone/geo/WebRTC/`navigator.languages` to the egress (proxy exit, or the host IP if proxyless). **`false`** — explicit opt-out. |
320
+ | `timezone` | `string` | — | IANA tz (e.g. `"America/New_York"`) → `--timezone`. **Overrides** `geoip`. |
321
+ | `locale` | `string` | — | BCP-47 (e.g. `"en-US"`) → `--lang` + `--accept-lang`. **Overrides** `geoip`. |
322
+
323
+ ### Profiles & extensions
324
+
325
+ | Option | Type | Default | Description |
326
+ |---|---|---|---|
327
+ | `userDataDir` | `string` | — | **`launchPersistentContext` only** (first positional arg). Directory where cookies/localStorage/cache persist across runs. |
328
+ | `extensionPaths` | `string[]` \| `string` | — | Unpacked Chrome extension directory(ies). Extensions require a **persistent context**. |
329
+
330
+ ### License
331
+
332
+ | Option | Type | Default | Description |
333
+ |---|---|---|---|
334
+ | `licenseKey` | `string` | — | `cap_…` key. Falls back to `CAPIUM_LICENSE_KEY` env / `~/.capium/license`. Passed to the binary via the environment, never argv. |
335
+ | `licenseServer` | `string` | — | Override the license server (default `https://license.capzy.ai`). |
336
+ | `licenseThroughProxy` | `boolean` | `false` | Route license/session calls through `--proxy-server` instead of direct. |
337
+ | `licensePreflight` | `boolean` | `true` | Fail fast with a typed `CapiumConfigError` when no key is configured, before spinning up a browser. Set `false` for a dev build that runs without enforcement. |
338
+
339
+ ### `launchContext` only
340
+
341
+ | Option | Type | Default | Description |
342
+ |---|---|---|---|
343
+ | `url` | `string` | — | If set, navigate the returned page to it (`domcontentloaded`, 60 s) as a driven navigation. |
344
+ | `humanize` | `boolean` | `false` | Attach `page.humanMove` / `humanClick` / `humanType` / `humanScroll` / `humanDwell` (see [Human behavior](#human-behavior)). |
345
+ | `humanPreset` | `string` | `"default"` | Pace of humanized input: `"default"` (natural) or `"careful"` (slower, more deliberate). |
346
+
347
+ ### Binary & driver passthrough
348
+
349
+ | Option | Type | Default | Description |
350
+ |---|---|---|---|
351
+ | `binary` | `string` | — | Exact path to the capium launch target — skips discovery/download (same as `CAPIUM_BINARY`). |
352
+ | *(rest)* | — | — | Every remaining option is forwarded to the driver's own `launch()` — `slowMo`, `timeout`, Playwright's `viewport`, Puppeteer's `defaultViewport`/`ignoreDefaultArgs`, etc. Persistent contexts default to `viewport: null` unless you pass one. |
353
+
354
+ > Prefer the friendly options (`proxy`, `geoip`, `timezone`, `locale`) over raw `args` — reach for
355
+ > `args` only when a convenience option doesn't cover the surface. Environment variables that affect
356
+ > every launch are in [CLI & environment](#cli--environment).
357
+
358
+ ---
359
+
360
+ ## Personas & seeds
361
+
362
+ A **persona** is a complete, self-consistent device deterministically derived from one integer **seed**.
363
+ The seed range selects the OS family (or pass `platform` and Capium picks the range for you):
364
+
365
+ | OS family | Seed range | `platform` |
366
+ |---|---|---|
367
+ | Windows | `10000–99999` | `"windows"` |
368
+ | macOS (Apple Silicon) | `100000–199999` | `"macos"` |
369
+ | Linux | `200000–299999` | `"linux"` |
370
+
371
+ ```js
372
+ await launch({ seed: 200123 }); // a specific, repeatable device
373
+ await launch({}); // random seed each launch (still fully coherent)
122
374
  ```
123
375
 
124
- Enforcement lives **in the browser binary** (activate → session → heartbeat); the SDK only
125
- passes the key along and translates the binary's fail-closed exit into typed errors:
126
- `CapiumConfigError` (no key), `CapiumSeatLimitError`, `CapiumExpiredError`,
127
- `CapiumServerDownError`.
376
+ > **Tip — pin a seed per account.** A fresh random seed every visit looks like a new device each time,
377
+ > which is suspicious when you keep hitting the same site from the same IP. A fixed seed reads as a
378
+ > returning visitor. **And match the persona to the host OS** — a macOS persona is flawless on a Mac and a
379
+ > Windows persona on Windows, because the host's real text-rasterizer and GPU back the claim.
128
380
 
129
- ## CLI
381
+ ### Launch every persona — and persist per account
130
382
 
131
- ```bash
132
- npx capiumbrowser # environment check: license + binary + drivers
133
- npx capiumbrowser status # license entitlements from the server
134
- npx capiumbrowser install # download the capium browser binary
135
- npx capiumbrowser run [URL] # demo launch (SEED/PLATFORM/PROXY/HEADLESS=1/PROFILE env)
383
+ ```js
384
+ const { launchContext, launchPersistentContext } = require('capiumbrowser');
385
+
386
+ // One coherent device per OS: pick platform + any stable seed
387
+ for (const [platform, seed] of [['windows', 200111], ['macos', 200222], ['linux', 200333]]) {
388
+ const { browser, page } = await launchContext({ seed, platform, url: 'https://browserscan.net/' });
389
+ await browser.close(); // non-persistent: close the browser
390
+ }
391
+
392
+ // Persist a logged-in account across runs — give it a profile DIRECTORY (persistent-only;
393
+ // launch()/launchContext() are always throwaway).
394
+ const ctx = await launchPersistentContext('capium-profiles/acct-a', { seed: 210001, platform: 'windows' });
395
+ const page = ctx.pages()[0] || (await ctx.newPage());
396
+ await page.goto('https://example.com'); // cookies/localStorage persist in the profile dir
397
+ await ctx.close();
398
+
399
+ // A fleet: each account its own coherent device AND its own profile
400
+ for (const [name, seed] of Object.entries({ 'acct-a': 210001, 'acct-b': 210002, 'acct-c': 210003 })) {
401
+ const c = await launchPersistentContext(`capium-profiles/${name}`, { seed, platform: 'macos' });
402
+ await c.close();
403
+ }
404
+ ```
405
+
406
+ Full runnable version (personas, persistent profiles, a fleet, proxy+geo, full control):
407
+ [`examples/profiles.js`](https://github.com/capzy-ai/capiumbrowser/tree/main/examples/profiles.js).
408
+
409
+ ---
410
+
411
+ ## Fingerprint switches
412
+
413
+ The SDK sets the essentials from `seed`/`platform`. Everything below is available for precise control —
414
+ pass any through `args: [...]` (or `stealthArgs: false` to build the whole command line yourself):
415
+
416
+ ```js
417
+ await launch({ seed: 200123, args: [
418
+ '--fingerprint-hardware-concurrency=8',
419
+ '--fingerprint-screen-width=2560', '--fingerprint-screen-height=1440',
420
+ ]});
421
+ ```
422
+
423
+ **Identity**
424
+
425
+ | Switch | What it controls |
426
+ |---|---|
427
+ | `--fingerprint=<seed>` | Master seed → the whole coherent device. |
428
+ | `--fingerprint-platform=<windows\|macos\|linux>` | Spoofed OS: `navigator.platform`, UA, UA-CH platform. |
429
+ | `--fingerprint-platform-version=<v>` | UA-CH `platformVersion`. |
430
+ | `--fingerprint-brand=<name>` / `--fingerprint-brand-version=<v>` | UA-CH brand and version entries. |
431
+ | `--fingerprint-hardware-concurrency=<n>` | `navigator.hardwareConcurrency` (CPU cores). |
432
+ | `--fingerprint-screen-width=<n>` / `--fingerprint-screen-height=<n>` | `screen.width` / `screen.height`. |
433
+ | `--fingerprint-device-scale-factor=<f>` | `devicePixelRatio`. |
434
+ | `--fingerprint-storage-quota=<GB>` | `navigator.storage.estimate().quota` in **gigabytes** (also affects incognito-from-quota checks). Auto-set per-seed by the SDK (128–576 GB) so the real host/container disk never leaks — including on Windows, where no wrapper runs. |
435
+
436
+ **Rendering & noise**
437
+
438
+ | Switch | What it controls |
439
+ |---|---|
440
+ | `--fingerprint-noise=<true\|false>` | Deterministic per-seed noise on canvas image data, `measureText`, and audio. Default **off** (per-seed noise can read as tampering when the DevTools tell is patched). |
441
+ | `--disable-spoofing=<canvas,font,…>` | Selectively turn off spoofing for named surfaces (comma-separated). |
442
+
443
+ **Fonts & voices**
444
+
445
+ | Switch | What it controls |
446
+ |---|---|
447
+ | `--fingerprint-windows-font-metrics` | Measure default text with Windows metrics (**requires real Windows fonts** — see [Fonts](#fonts)). Default on for a Windows persona. |
448
+ | `--fingerprint-sapi-voices=<true\|false>` | Present the Windows SAPI voice list for a Windows persona. |
449
+
450
+ **Location, network & content**
451
+
452
+ | Switch | What it controls |
453
+ |---|---|
454
+ | `--timezone=<IANA>` | In-browser timezone (e.g. `America/New_York`). |
455
+ | `--fingerprint-location=<lat,lon>` | Geolocation API coordinates (permission auto-granted). |
456
+ | `--fingerprint-webrtc-ip=<ip\|auto>` | The IP WebRTC reports (pin to your proxy exit — the SDK does this with `geoip`). |
457
+ | `--fingerprint-allow-3p-cookies` | Allow third-party cookies (some SSO / embedded-payment flows need them). |
458
+ | `--disable-ads` | Built-in ad/tracker blocker with a login/captcha-safe allowlist (default on). |
459
+
460
+ Most of these have friendly SDK equivalents (`timezone`, `locale`, `proxy`, `geoip`). The full
461
+ per-switch matrix lives in the [docs](https://docs.capiumbrowser.com).
462
+
463
+ ---
464
+
465
+ ## Human behavior
466
+
467
+ Behavioral anti-bot systems score *how* you move, not just what you send. Pass
468
+ **`humanize: true`** to `launchContext()` (or call `human.humanize(page)` yourself) and human
469
+ input helpers are attached to the page:
470
+
471
+ ```js
472
+ const { browser, page } = await launchContext({ seed: 200123, humanize: true, url: 'https://example.com' });
473
+ await page.humanClick('#login'); // curved cursor along a bezier path, then a human press
474
+ await page.humanType('#user', 'alice'); // per-key typing with realistic timing & think-pauses
475
+ await page.humanScroll(1200); // eased, incremental scrolling — not one jump
476
+ await page.humanDwell(); // idle a human-plausible moment
477
+ ```
478
+
479
+ - The cursor follows a **curved bezier path** through randomized way-points with variable speed.
480
+ - Keystrokes carry **per-key jitter** with occasional longer think-pauses.
481
+ - Scrolling moves in **eased increments** that decay toward the target.
482
+
483
+ Two presets tune the pace: `"default"` (natural) and `"careful"` (slower). It's pure driver
484
+ input (`page.mouse` / `page.keyboard`) — no CDP tricks — and works with both Playwright and
485
+ Puppeteer pages. Helpers are also importable directly:
486
+
487
+ ```js
488
+ const { human } = require('capiumbrowser');
489
+ await human.click(page, '#login');
490
+ await human.typeText(page, '#user', 'alice', 'careful');
491
+ ```
492
+
493
+ ---
494
+
495
+ ## Proxies & geo
496
+
497
+ **No proxy provider and no credentials ship with the package** — you supply your own.
498
+
499
+ ```js
500
+ await launch({ seed: 200123, proxy: 'http://user:pass@host:port', geoip: true });
501
+ await launch({ seed: 200123, proxy: 'socks5://user:pass@host:port' }); // RFC 1929 auth
502
+ await launch({ proxy: { server: 'http://h:8080', username: 'u', password: 'p', bypass: 'localhost,*.internal' } });
136
503
  ```
137
504
 
138
- ## Environment variables
505
+ `proxy` accepts an HTTP/HTTPS or SOCKS5 URL (inline credentials) or a
506
+ `{server, username, password, bypass}` object. Credentials are passed **inline** to the Capium
507
+ binary — which authenticates natively (SOCKS5 RFC 1929; preemptive HTTP `Proxy-Authorization`) — and are
508
+ URL-encoded so special characters (commas in `groups-X,country-Y` usernames included) can't truncate the
509
+ proxy string into a real-IP-leaking `DIRECT` fallback.
139
510
 
140
- | Variable | Meaning |
141
- | --- | --- |
142
- | `CAPIUM_LICENSE_KEY` / `CAPIUM_LICENSE_SERVER` | License credentials (or `~/.capium/license`) |
143
- | `CAPIUM_HOME` | Install/search root for the browser binary (default `~/.capium`) |
144
- | `CAPIUM_BINARY` | Exact launch target; skips discovery and download |
145
- | `CAPIUM_VERSION` | Pin a specific binary build |
146
- | `CAPIUM_DOWNLOAD_URL` | Direct `.tar.gz` URL escape hatch (may contain `{platform}`/`{version}`) |
147
- | `CAPIUM_INLINE_PROXY_AUTH=0` | Legacy CDP proxy-auth path for old binaries |
511
+ Geo coherence is resolved **inside the binary** at launch, which geolocates the egress IP
512
+ and pins timezone, geolocation, WebRTC IP, and `navigator.languages` — so the WebRTC IP equals the
513
+ site-visible IP and the clock/locale match the egress geography. There's no SDK-side network call. `geoip` is
514
+ tri-state:
148
515
 
149
- ## Fonts (cross-OS personas)
516
+ - **omitted / `null` (default) — OFF.** No geo lookup runs, **even with a proxy** — a proxy alone does not
517
+ trigger it (the lookup is a blocking egress round-trip we don't pay unless you ask). Pass `geoip: true`
518
+ to opt into proxy-exit coherence.
519
+ - **`geoip: true` — ON.** Geolocates the egress and pins timezone/geolocation/WebRTC/`navigator.languages` to
520
+ it — the **proxy exit** when a proxy is set, else the **host's own public IP**.
521
+ - **`geoip: false` — explicit opt-out.** Forwards `--geoip=false` so the in-binary resolver is unambiguously off.
150
522
 
151
- A persona reads cleanest on a **matching-OS host** (Windows persona on Windows, …) — the OS
152
- fonts back the claim and there's nothing to install. For a **Windows persona on Linux/macOS**,
153
- copy the fonts from a real Windows machine you own:
523
+ Explicit `timezone` / `locale` always win (they're set at launch, so they also cover the HTTP
524
+ `Accept-Language` header).
525
+
526
+ ---
527
+
528
+ ## Fonts
529
+
530
+ Font detection is **measurement-based** — a font only counts as "present" if it genuinely renders with the
531
+ right metrics. Capium controls what actually resolves, gating each persona to a coherent per-seed set and
532
+ hiding the host's other fonts.
533
+
534
+ - **Bundled & free (ship anywhere):** DejaVu, Liberation, and the metric-identical MS clones **Carlito**
535
+ (= Calibri) and **Caladea** (= Cambria).
536
+ - **Proprietary (you supply from a licensed source):** genuine Apple fonts for a macOS persona on a non-Mac
537
+ host, and genuine Microsoft fonts for a Windows persona on a non-Windows host.
538
+
539
+ On a **matching-OS host** the persona uses the operating system's own fonts and there's nothing to install.
540
+
541
+ **Copying Windows fonts to a Linux host** (Windows persona on Linux) — copy the whole font
542
+ folder from any real Windows machine you own; it covers the required set (Segoe UI, Segoe UI
543
+ Light, Calibri, Marlett, MS UI Gothic, Franklin Gothic, Consolas, Courier New) and more:
154
544
 
155
545
  ```bash
156
- # Linux: copy C:\Windows\Fonts\* into a font dir, then refresh
546
+ # on the Linux box:
157
547
  mkdir -p ~/.local/share/fonts/windows
158
- scp C:\Windows\Fonts\* user@linuxbox:~/.local/share/fonts/windows/ # from the Windows box
548
+ # from the Windows machine (PowerShell):
549
+ scp C:\Windows\Fonts\* user@linuxbox:~/.local/share/fonts/windows/
550
+ # back on the Linux box:
159
551
  fc-cache -f
160
- # macOS: drop the .ttf/.ttc files into ~/Library/Fonts/ (picked up immediately)
161
552
  ```
162
553
 
163
- Once Segoe UI/Calibri/Consolas & co. resolve, the wrapper auto-enables
164
- `--fingerprint-windows-font-metrics`. `CAPIUM_FONTS_DIR=/path` points at a custom dir. Copy
165
- proprietary fonts only between machines you hold licenses for. Full guide: the
166
- [product README](https://github.com/capzy-ai/capiumbrowser#fonts).
554
+ The distro also ships **`capium-install-fonts.sh`**, which installs the free baseline
555
+ (emoji/CJK + the Carlito/Caladea/Liberation substitutes) via apt and then checks for the
556
+ required Windows set. Once the fonts resolve, the `capium` wrapper **auto-enables**
557
+ `--fingerprint-windows-font-metrics` — no flag needed.
558
+
559
+ **Copying Windows fonts to a macOS host** — install the same `.ttf`/`.ttc` files via Font
560
+ Book, or drop them into `~/Library/Fonts/` (picked up immediately).
561
+
562
+ **macOS persona on a non-Mac host** — needs genuine Apple fonts (SF Pro, Helvetica Neue, …)
563
+ from a Mac you own, placed in the same font locations. This is the hardest cross-OS
564
+ direction — a macOS persona reads cleanest on a real Mac.
565
+
566
+ Copy proprietary fonts only between machines you hold licenses for. On Linux,
567
+ `CAPIUM_FONTS_DIR` adds a custom font directory; `CAPIUM_SUPPRESS_FONT_WARNING=1` silences the
568
+ "missing Windows fonts" hint once you've supplied them.
569
+
570
+ ---
571
+
572
+ ## Framework integrations
573
+
574
+ Capium is a Chromium fork, so any Chromium automation tool works — point it at the binary and add the
575
+ persona flags. Runnable examples live in
576
+ [`examples/integrations/`](https://github.com/capzy-ai/capiumbrowser/tree/main/examples/integrations/):
577
+
578
+ | Framework | Example |
579
+ |---|---|
580
+ | [Crawlee](https://github.com/apify/crawlee) (`PlaywrightCrawler`) | [`crawlee.js`](https://github.com/capzy-ai/capiumbrowser/tree/main/examples/integrations/crawlee.js) |
581
+ | [@playwright/test](https://playwright.dev/docs/intro) | [`playwright_test.spec.js`](https://github.com/capzy-ai/capiumbrowser/tree/main/examples/integrations/playwright_test.spec.js) |
582
+ | [puppeteer-cluster](https://github.com/thomasdondorf/puppeteer-cluster) | [`puppeteer_cluster.js`](https://github.com/capzy-ai/capiumbrowser/tree/main/examples/integrations/puppeteer_cluster.js) |
583
+ | any CDP tool | [`cdp_connect.js`](https://github.com/capzy-ai/capiumbrowser/tree/main/examples/integrations/cdp_connect.js) |
584
+
585
+ Two patterns cover them all:
586
+
587
+ ```js
588
+ // 1) Framework launches our binary directly (Crawlee, puppeteer-cluster, @playwright/test):
589
+ // buildLaunchOptions() returns {executablePath, args, env, ...} for the framework's launcher.
590
+ const { buildLaunchOptions } = require('capiumbrowser/playwright'); // or /puppeteer
591
+ const launchOptions = await buildLaunchOptions({ seed: 200123, platform: 'windows' });
592
+
593
+ // 2) Capium launches first, the framework connects over CDP (AI agents, remote tools):
594
+ const { launch } = require('capiumbrowser/playwright');
595
+ const browser = await launch({ seed: 200123, geoip: true, args: ['--remote-debugging-port=9242'] });
596
+ // point anything at http://127.0.0.1:9242 — all stealth flags are already set
597
+ ```
598
+
599
+ ---
600
+
601
+ ## Deployment
602
+
603
+ Capium runs identically local, in Docker, and on a VPS. Build your own image — download the
604
+ binary at build time with a BuildKit secret so the key never lands in a layer, and keep it
605
+ under `CAPIUM_HOME` so `npm ci` can never delete it:
606
+
607
+ ```dockerfile
608
+ FROM node:22-slim
609
+ ENV CAPIUM_HOME=/opt/capium
610
+ RUN npx -y playwright-core install-deps chromium
611
+ WORKDIR /app
612
+ COPY package*.json ./
613
+ RUN npm ci # capiumbrowser + playwright-core (or puppeteer-core) from your package.json
614
+ RUN --mount=type=secret,id=capium_license \
615
+ CAPIUM_LICENSE_KEY="$(cat /run/secrets/capium_license)" npx capiumbrowser install
616
+ COPY your_script.js .
617
+ CMD ["node", "your_script.js"]
618
+ ```
619
+
620
+ ```bash
621
+ DOCKER_BUILDKIT=1 docker build --secret id=capium_license,env=CAPIUM_LICENSE_KEY -t my-capium .
622
+ ```
623
+
624
+ On a headless Linux server, run the browser under a virtual display (`Xvfb :99` + `DISPLAY=:99`) so it
625
+ launches **headed**, which reads cleaner than headless.
626
+
627
+ ---
167
628
 
168
629
  ## Platforms
169
630
 
170
- `linux-x64` · `linux-arm64` · `windows-x64` · `macos-arm64` (Apple Silicon).
631
+ | Platform | Distro tag | Notes |
632
+ |---|---|---|
633
+ | Windows x86_64 | `windows-x64` | Native GPU/fonts back a Windows persona flawlessly |
634
+ | macOS arm64 (Apple Silicon) | `macos-arm64` | M1–M4 by design (covers 2020+ Macs); a Windows persona uses installed Windows fonts for fallback |
635
+ | Linux x86_64 | `linux-x64` | Defaults to a Windows persona; supply Windows fonts for the cleanest result |
636
+ | Linux arm64 | `linux-arm64` | Same as Linux x64 for aarch64 hosts |
637
+
638
+ The SDK auto-detects your host and downloads the matching tag; macOS Intel and Windows ARM are **not**
639
+ published and throw a clear error. Capium currently targets **Chromium 152**.
640
+
641
+ ---
642
+
643
+ ## CLI & environment
644
+
645
+ ```bash
646
+ npx capiumbrowser # environment check: license + binary + drivers ("what do I still need?")
647
+ npx capiumbrowser status # license entitlements (plan, seats, live sessions, renewal)
648
+ npx capiumbrowser version # SDK version + the Chromium build it targets
649
+ npx capiumbrowser install # download the capium browser binary
650
+ SEED=200123 PLATFORM=linux PROXY="http://user:pass@host:port" GEOIP=1 HUMANIZE=1 \
651
+ npx capiumbrowser run https://example.com # launch a demo browser (Ctrl-C to exit)
652
+ ```
653
+
654
+ `npx capiumbrowser` (bare, = `info`) checks the drivers, the binary (path + version), and the
655
+ license key; it prints a fix for anything missing and exits non-zero if the environment isn't ready.
656
+
657
+ | Variable | Purpose |
658
+ |---|---|
659
+ | `CAPIUM_LICENSE_KEY` / `CAPIUM_LICENSE_SERVER` | license key (`cap_…`) + server (default `https://license.capzy.ai`) |
660
+ | `CAPIUM_BINARY` | exact path to the capium launch target (skips download) |
661
+ | `CAPIUM_DOWNLOAD_URL` | direct archive URL (`{platform}`/`{version}` placeholders); unsigned escape hatch |
662
+ | `CAPIUM_HOME` / `CAPIUM_VERSION` | where distros cache (default `~/.capium`) / pin a binary version |
663
+ | `CAPIUM_INLINE_PROXY_AUTH=0` | legacy CDP proxy-auth path (only for a binary lacking the preemptive-auth patch) |
664
+ | `CAPIUM_FONTS_DIR` / `CAPIUM_SUPPRESS_FONT_WARNING` | custom font dir / silence the font hint (Linux) |
665
+
666
+ ---
667
+
668
+ ## Troubleshooting
669
+
670
+ | Symptom | Fix |
671
+ |---|---|
672
+ | `capium binary not found` | Set `CAPIUM_LICENSE_KEY` (to auto-download), or `CAPIUM_BINARY`, or run `npx capiumbrowser install`. |
673
+ | `no license configured` | Set `CAPIUM_LICENSE_KEY`, pass `licenseKey: '…'`, or create `~/.capium/license` (`KEY=cap_…`). |
674
+ | `playwright-core is not installed` | `npm install playwright-core` (or `puppeteer-core`) — the driver is a peer dependency you choose. |
675
+ | `CapiumSeatLimitError` | Free tier is 1 concurrent session — close the other Capium browser (or upgrade the tier). |
676
+ | Still blocked on aggressive sites | Run **headed** (`headless: false` under Xvfb) + a **residential** proxy + `geoip: true` + humanized input. Most blocks are IP reputation or a mismatched clock, not fingerprint. |
677
+ | Intermittent 403s on reCAPTCHA Enterprise sites | Prefer the **Playwright** front-end — Puppeteer's CDP protocol usage leaks more automation signals (a Puppeteer limitation, not a Capium one). |
678
+ | FPJS `tampering: true` | Cross-OS persona on a mismatched host, or per-seed noise unmasked — run on a matching-OS host; `--fingerprint-noise=false` is the default. |
679
+ | "Windows persona but missing fonts" | Supply real `C:\Windows\Fonts\*.ttf` (see [Fonts](#fonts)) or set `CAPIUM_SUPPRESS_FONT_WARNING=1`. |
680
+ | `os_mismatch: true` | A network/transport signal (genuine Chrome shows it too behind some proxies) — a routing concern, not the browser. |
681
+ | Headed browser won't start on a server | Run under `Xvfb` and export `DISPLAY=:99`. |
682
+
683
+ More: [docs.capiumbrowser.com](https://docs.capiumbrowser.com).
684
+
685
+ ---
686
+
687
+ ## FAQ
688
+
689
+ **Is this legal?** Capium is a browser built on open-source Chromium. Use it only where you're authorized to.
690
+ Automating systems without authorization, credential stuffing, and account-creation abuse are prohibited.
691
+
692
+ **Is it free?** The `capiumbrowser` npm package is open. The binary has a **free tier with 1 concurrent
693
+ session** using the same latest build; paid tiers raise the concurrent-session cap. See
694
+ [capiumbrowser.com](https://capiumbrowser.com/#pricing).
695
+
696
+ **Do I need a license key?** Yes — the binary is license-gated and fails closed. A free key (from the
697
+ dashboard) gives one concurrent session; a paid key raises the limit.
698
+
699
+ **Playwright or Puppeteer?** Both are first-class. Playwright is the recommended default (its native
700
+ launch path is the one measured cleanest, and it matters on reCAPTCHA-Enterprise-heavy sites);
701
+ Puppeteer works great when your stack is already built on it.
702
+
703
+ **How is this different from JS stealth plugins?** They inject JavaScript that modern ML detects. Capium
704
+ rewrites fingerprints in the Chromium source and compiles them in — there's no injected hook to catch.
705
+
706
+ **Will detection eventually catch this?** Bot detection is an arms race. Source-level patches are much harder
707
+ to detect than config-level ones, and Capium rebases onto new Chromium and ships updates as detection evolves.
708
+
709
+ **Can I use my own proxy?** Yes — HTTP/HTTPS and SOCKS5 are supported natively. Bring your own.
710
+
711
+ **Does this work with Python?** Yes — the same browser ships as a
712
+ [PyPI package](https://pypi.org/project/capiumbrowser/) with the same options (snake_case).
713
+
714
+ ---
715
+
716
+ ## Security
717
+
718
+ The SDK fetches the binary over an **authenticated** request — the license key travels in a header (over
719
+ TLS), never in the URL, and the request target is HMAC-signed. The response's checksum is
720
+ verified against the downloaded bytes before anything is extracted, so a corrupted or tampered download is
721
+ rejected. The key is handed to the browser subprocess through the **environment**, never on argv.
722
+
723
+ ---
724
+
725
+ ## License
726
+
727
+ - **`capiumbrowser` npm package** — open; see [LICENSE](https://github.com/capzy-ai/capiumbrowser/blob/main/LICENSE).
728
+ - **Capium browser binary** (compiled Chromium) — licensed per concurrent session; requires an active key
729
+ to download and run. Free tier available. See [capiumbrowser.com](https://capiumbrowser.com).
171
730
 
172
- > **Responsible use.** Capium is a stealth browser for legitimate automation, testing, QA, and
173
- > research. Capium doesn't solve CAPTCHAs, and no stealth tool can promise you'll never see
174
- > one. Respect the terms of service of the sites you automate.
731
+ <p align="center"><sub><a href="https://capiumbrowser.com">Capium Browser</a> is a product of <a href="https://capzy.ai">Capzy</a>. Use responsibly and only where you are authorized to.</sub></p>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capiumbrowser",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Drop-in stealth browser SDK on top of Playwright or Puppeteer (Capium Chromium).",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Capzy (https://capzy.ai)",