capiumbrowser 1.2.3 → 1.2.4

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.
package/README.md CHANGED
@@ -753,7 +753,7 @@ license key; it prints a fix for anything missing and exits non-zero if the envi
753
753
  | `CapiumSeatLimitError` | Free tier is 1 concurrent session — close the other Capium browser (or upgrade the tier). |
754
754
  | Still blocked on aggressive sites | Compare a matching persona with stock Chrome through assigned proxies. Check route, timezone, graphics availability and detector fields separately; headed mode under Xvfb also needs a working graphics backend. |
755
755
  | 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). |
756
- | FPJS `tampering: true` | Prefer a matching-OS host and keep the default `--fingerprint-noise=false`. The current Linux audit remains flagged even with hardware Vulkan; ML zero alone does not clear tampering or anomaly. See the [audit](../../docs/SDK-GPU-AUDIT.md). |
756
+ | FPJS `tampering: true` | Prefer a matching-OS host. Per-profile render noise is **on** by default (deterministic per profile; opt out with `--fingerprint-noise=false`). The current Linux audit remains flagged even with hardware Vulkan; ML zero alone does not clear tampering or anomaly. See the [audit](../../docs/SDK-GPU-AUDIT.md). |
757
757
  | "Windows persona but missing fonts" | Supply real `C:\Windows\Fonts\*.ttf` (see [Fonts](#fonts)) or set `CAPIUM_SUPPRESS_FONT_WARNING=1`. |
758
758
  | `os_mismatch: true` | A network/transport signal (genuine Chrome shows it too behind some proxies) — a routing concern, not the browser. |
759
759
  | Headed browser won't start on a server | Run under `Xvfb` and export `DISPLAY=:99`. |
package/lib/config.js CHANGED
@@ -73,7 +73,9 @@ function getDefaultStealthArgs(seed = null, platform = 'windows', screen = null,
73
73
  'primaryPointerType=2,availablePointerTypes=2,maxTouchPoints=5,' +
74
74
  'viewportEnabled=true,viewportMetaEnabled=true,shrinksViewportContentToFit=true',
75
75
  '--touch-events=enabled', '--enable-viewport',
76
- '--no-first-run', '--no-default-browser-check', '--fingerprint-noise=false',
76
+ // Per-profile render noise ON (engine default), same as desktop: mobile canvas/WebGL/audio
77
+ // are unique + stable per seed instead of identical across profiles on one host.
78
+ '--no-first-run', '--no-default-browser-check',
77
79
  `--window-size=${sw},${sh}`,
78
80
  ...(platform === 'ios' ? [`--user-agent=${p.user_agent}`, '--capium-preserve-user-agent'] : []),
79
81
  ...(screen ? [`--fingerprint-screen-width=${sw}`, `--fingerprint-screen-height=${sh}`] : []),
@@ -110,10 +112,11 @@ function getDefaultStealthArgs(seed = null, platform = 'windows', screen = null,
110
112
  // requests that legacy mode on 155. See docs/SDK-GPU-AUDIT.md for measured
111
113
  // page-global, object-handle and binding compatibility.
112
114
  );
113
- // Keep injected canvas/audio/rectangle noise opt-in. Device fonts and the
114
- // actual renderer can still affect pixels; noise=false does not guarantee
115
- // identical canvases across personas or a particular detector classification.
116
- args.push('--fingerprint-noise=false');
115
+ // Per-profile render farbling is ON (engine default) so canvas/WebGL/audio are unique AND
116
+ // stable per seed; without it every profile on a host renders identically (a cross-instance
117
+ // correlation surface a detector clusters over time). The engine farbles deterministically per
118
+ // (seed,x,y), skipping low-entropy images. Combined with the per-profile seed, each profile gets
119
+ // a distinct render fingerprint. Opt out via args: ['--fingerprint-noise=false'].
117
120
  // A Windows persona's font metrics must match real Windows (needs Windows fonts
118
121
  // present on the host); harmless elsewhere, so gate it to the windows persona.
119
122
  if (platform === 'windows') args.push('--fingerprint-windows-font-metrics');
@@ -138,6 +141,28 @@ function newSeed() {
138
141
  return 1 + Math.floor(Math.random() * (2 ** 31 - 2));
139
142
  }
140
143
 
144
+ /** Stable, unique-per-machine seed, persisted in CAPIUM_HOME/machine-seed (random on first use,
145
+ * never derived from hardware so it leaks nothing). Keeps a machine's no-seed identity
146
+ * consistent across launches instead of colliding on the engine's built-in default. */
147
+ function machineSeed() {
148
+ const os = require('os'), fs = require('fs'), path = require('path');
149
+ const home = process.env.CAPIUM_HOME || path.join(os.homedir(), '.capium');
150
+ const p = path.join(home, 'machine-seed');
151
+ try { const v = parseInt(fs.readFileSync(p, 'utf8').trim(), 10); if (v > 0) return v; } catch (e) { /* first use */ }
152
+ const s = 1 + Math.floor(Math.random() * (2 ** 31 - 2));
153
+ try { fs.mkdirSync(home, { recursive: true }); fs.writeFileSync(p, String(s)); } catch (e) { /* ephemeral ok */ }
154
+ return s;
155
+ }
156
+
157
+ /** Stable seed unique to this (machine, profile) pair -- a hash of the machine seed and the
158
+ * profile directory. Each persistent profile gets a distinct, consistent fingerprint so no two
159
+ * profiles collide (not the same path on different machines, nor different profiles on one host). */
160
+ function profileSeed(userDataDir) {
161
+ const crypto = require('crypto'), path = require('path');
162
+ const base = `${machineSeed()}:${path.resolve(userDataDir)}`;
163
+ return (crypto.createHash('sha256').update(base).digest().readUInt32BE(0) % (2 ** 31 - 1)) + 1;
164
+ }
165
+
141
166
  // ---- binary / wrapper discovery -------------------------------------------------------------
142
167
  // The launch target (handed to the driver as executablePath) differs by OS:
143
168
  // * POSIX (Linux/macOS): the `capium` bash wrapper -- it adds the GL/geoip/font flags and
@@ -338,6 +363,8 @@ module.exports = {
338
363
  getHeadlessDefaultArgs,
339
364
  hasScreenOverride,
340
365
  newSeed,
366
+ machineSeed,
367
+ profileSeed,
341
368
  findBinary,
342
369
  searchBases,
343
370
  _ensureExecutable: ensureExecutable,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capiumbrowser",
3
- "version": "1.2.3",
3
+ "version": "1.2.4",
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)",
package/playwright.js CHANGED
@@ -236,6 +236,9 @@ async function requireMobileEngine(context, mobileDevice = null, seed = 0, platf
236
236
  * Same options as launch(); returns a BrowserContext.
237
237
  */
238
238
  async function launchPersistentContext(userDataDir, opts = {}) {
239
+ // Stable per-profile seed from the persistent profile dir so each profile gets a distinct,
240
+ // consistent fingerprint and no two profiles collide. An explicit opts.seed still wins.
241
+ if (opts.seed === null || opts.seed === undefined) opts = { ...opts, seed: config.profileSeed(userDataDir) };
239
242
  const {
240
243
  seed, platform, mobileDevice, browserBrand, proxy, geoip, args, stealthArgs, timezone, locale, extensionPaths,
241
244
  binary, licenseKey, licenseServer, licenseThroughProxy, licensePreflight,
package/puppeteer.js CHANGED
@@ -246,6 +246,9 @@ async function launch(opts = {}) {
246
246
  * Returns the Browser.
247
247
  */
248
248
  async function launchPersistentContext(userDataDir, opts = {}) {
249
+ // Stable per-profile seed from the persistent profile dir so each profile gets a distinct,
250
+ // consistent fingerprint and no two profiles collide. An explicit opts.seed still wins.
251
+ if (opts.seed === null || opts.seed === undefined) opts = { ...opts, seed: config.profileSeed(userDataDir) };
249
252
  const browser = await launch({ ...opts, userDataDir });
250
253
  // Desktop personas: fit the window to the seed's screen in HEADLESS too (coherent per-seed
251
254
  // viewport, not the tiny startup window). Mobile keeps its device viewport.