capiumbrowser 1.2.2 → 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 +1 -1
- package/lib/channels.json +6 -6
- package/lib/config.js +32 -5
- package/package.json +1 -1
- package/playwright.js +3 -0
- package/puppeteer.js +3 -0
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
|
|
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/channels.json
CHANGED
|
@@ -7,24 +7,24 @@
|
|
|
7
7
|
"windows-x64": {
|
|
8
8
|
"version": "155.0.8059.85",
|
|
9
9
|
"engine_version": "155.0.8059.84",
|
|
10
|
-
"revision":
|
|
11
|
-
"sha256": "
|
|
10
|
+
"revision": 2,
|
|
11
|
+
"sha256": "905bb081d5234338237b6a4c3df7ef3fbb8d20d0049adde982027494b87e4ed2",
|
|
12
12
|
"published": true,
|
|
13
13
|
"license_status_protocol": 1
|
|
14
14
|
},
|
|
15
15
|
"macos-arm64": {
|
|
16
16
|
"version": "155.0.8059.84",
|
|
17
17
|
"engine_version": "155.0.8059.84",
|
|
18
|
-
"revision":
|
|
19
|
-
"sha256": "
|
|
18
|
+
"revision": 2,
|
|
19
|
+
"sha256": "5c4ab089d7925a3b86fd891cfbe9de95777c46fc7616990a94b15b891c89775f",
|
|
20
20
|
"published": true,
|
|
21
21
|
"license_status_protocol": 1
|
|
22
22
|
},
|
|
23
23
|
"linux-x64": {
|
|
24
24
|
"version": "155.0.8059.84",
|
|
25
25
|
"engine_version": "155.0.8059.84",
|
|
26
|
-
"revision":
|
|
27
|
-
"sha256": "
|
|
26
|
+
"revision": 2,
|
|
27
|
+
"sha256": "e9e18dd9f23baa500e1be0a7075096f6e6c8fb3a37150c96bd96fd4e58518880",
|
|
28
28
|
"published": true,
|
|
29
29
|
"license_status_protocol": 1
|
|
30
30
|
},
|
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
|
-
|
|
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
|
-
//
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
|
|
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
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.
|