capiumbrowser 1.2.2__tar.gz → 1.2.4__tar.gz
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.
- {capiumbrowser-1.2.2/capiumbrowser.egg-info → capiumbrowser-1.2.4}/PKG-INFO +2 -2
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/README.md +1 -1
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/_version.py +1 -1
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/browser.py +4 -1
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/browser_async.py +3 -1
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/channels.json +6 -6
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/config.py +46 -5
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4/capiumbrowser.egg-info}/PKG-INFO +2 -2
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/pyproject.toml +1 -1
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/tests/test_config_args.py +4 -2
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/LICENSE +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/MANIFEST.in +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/__init__.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/__main__.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/_driver.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/android-phones.json +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/browser-brands.json +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/desktop.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/errors.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/human/__init__.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/human/behavior.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/ios-phones.json +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/licensing/__init__.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/licensing/client.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/licensing/download.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/licensing/readiness.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/mobile.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/network/__init__.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser/network/proxy.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser.egg-info/SOURCES.txt +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser.egg-info/dependency_links.txt +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser.egg-info/entry_points.txt +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser.egg-info/requires.txt +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/capiumbrowser.egg-info/top_level.txt +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/setup.cfg +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/tests/test_channels_manifest.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/tests/test_desktop_brands.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/tests/test_download_contract.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/tests/test_geoip_flags.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/tests/test_ios_profiles.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/tests/test_launch_viewport.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/tests/test_license_readiness.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/tests/test_mobile_profiles.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/tests/test_proxy.py +0 -0
- {capiumbrowser-1.2.2 → capiumbrowser-1.2.4}/tests/test_version_tables_consistent.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: capiumbrowser
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.4
|
|
4
4
|
Summary: Drop-in stealth browser SDK on top of Playwright (Capium Chromium).
|
|
5
5
|
Author: Capzy
|
|
6
6
|
License: Capzy capiumbrowser SDK License
|
|
@@ -807,7 +807,7 @@ non-zero if the environment isn't ready. A bare `python -m capiumbrowser` runs `
|
|
|
807
807
|
| `no license configured` | Set `CAPIUM_LICENSE_KEY`, pass `license_key=…`, or create `~/.capium/license` (`KEY=cap_…`). |
|
|
808
808
|
| `CapiumSeatLimitError` | Free tier is 1 concurrent session — close the other Capium browser (or upgrade the tier). |
|
|
809
809
|
| 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. |
|
|
810
|
-
| FPJS `tampering: true` | Prefer a matching-OS host
|
|
810
|
+
| 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). |
|
|
811
811
|
| "Windows persona but missing fonts" | Supply real `C:\Windows\Fonts\*.ttf` (see [fonts](#fonts)) or set `CAPIUM_SUPPRESS_FONT_WARNING=1`. |
|
|
812
812
|
| `os_mismatch: true` | A network/transport signal (genuine Chrome shows it too behind some proxies) — a routing concern, not the browser. |
|
|
813
813
|
| Headed browser won't start on a server | Run under `Xvfb` and export `DISPLAY=:99`. |
|
|
@@ -744,7 +744,7 @@ non-zero if the environment isn't ready. A bare `python -m capiumbrowser` runs `
|
|
|
744
744
|
| `no license configured` | Set `CAPIUM_LICENSE_KEY`, pass `license_key=…`, or create `~/.capium/license` (`KEY=cap_…`). |
|
|
745
745
|
| `CapiumSeatLimitError` | Free tier is 1 concurrent session — close the other Capium browser (or upgrade the tier). |
|
|
746
746
|
| 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. |
|
|
747
|
-
| FPJS `tampering: true` | Prefer a matching-OS host
|
|
747
|
+
| 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). |
|
|
748
748
|
| "Windows persona but missing fonts" | Supply real `C:\Windows\Fonts\*.ttf` (see [fonts](#fonts)) or set `CAPIUM_SUPPRESS_FONT_WARNING=1`. |
|
|
749
749
|
| `os_mismatch: true` | A network/transport signal (genuine Chrome shows it too behind some proxies) — a routing concern, not the browser. |
|
|
750
750
|
| Headed browser won't start on a server | Run under `Xvfb` and export `DISPLAY=:99`. |
|
|
@@ -17,7 +17,7 @@ import json
|
|
|
17
17
|
import os
|
|
18
18
|
import platform as _platform
|
|
19
19
|
|
|
20
|
-
__version__ = "1.2.
|
|
20
|
+
__version__ = "1.2.4"
|
|
21
21
|
|
|
22
22
|
# Used only if channels.json can't be read (corrupt/removed install). ensure_binary() raises a
|
|
23
23
|
# clear error long before the "unsupported platform" case matters; this keeps lookups total.
|
|
@@ -379,7 +379,10 @@ def launch_persistent_context(user_data_dir, seed=None, platform="windows", head
|
|
|
379
379
|
key, _ = _license.effective(license_key, license_server)
|
|
380
380
|
binpath = _resolve_binary(binary, key)
|
|
381
381
|
if seed is None:
|
|
382
|
-
seed
|
|
382
|
+
# No explicit identity: derive a STABLE per-profile seed from this persistent profile
|
|
383
|
+
# dir so each profile gets a distinct, consistent fingerprint (no two profiles collide,
|
|
384
|
+
# and a profile keeps its identity across launches) -- see config._profile_seed.
|
|
385
|
+
seed = config._profile_seed(user_data_dir)
|
|
383
386
|
display = os.environ.get("DISPLAY")
|
|
384
387
|
proxy_kwargs, proxy_args = _proxy_and_geo_args(proxy, binpath, geoip, display)
|
|
385
388
|
launch_args = proxy_args + _build_args(
|
|
@@ -202,7 +202,9 @@ async def launch_persistent_context_async(user_data_dir, seed=None, platform="wi
|
|
|
202
202
|
key, _ = _license.effective(license_key, license_server)
|
|
203
203
|
binpath = _resolve_binary(binary, key)
|
|
204
204
|
if seed is None:
|
|
205
|
-
seed
|
|
205
|
+
# Stable per-profile seed from the persistent profile dir -- distinct, consistent
|
|
206
|
+
# fingerprint per profile so no two profiles collide (see config._profile_seed).
|
|
207
|
+
seed = config._profile_seed(user_data_dir)
|
|
206
208
|
display = os.environ.get("DISPLAY")
|
|
207
209
|
proxy_kwargs, proxy_args = await _proxy_and_geo_args_async(proxy, binpath, geoip, display)
|
|
208
210
|
launch_args = proxy_args + _build_args(
|
|
@@ -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
|
},
|
|
@@ -46,6 +46,42 @@ def get_headless_default_args():
|
|
|
46
46
|
|
|
47
47
|
# Chrome flags that make an automated launch look like a normal user session. These are
|
|
48
48
|
# fingerprint-level; the bash wrapper adds the platform/GL/geoip/font/bluetooth/storage flags.
|
|
49
|
+
def _machine_seed():
|
|
50
|
+
"""A stable, unique-per-machine fingerprint seed.
|
|
51
|
+
|
|
52
|
+
Persisted as a random 32-bit value in CAPIUM_HOME/machine-seed on first use -- it is NOT
|
|
53
|
+
derived from hardware (so it leaks nothing about the host) but is fixed thereafter, so a
|
|
54
|
+
machine keeps one consistent identity across launches instead of every no-seed instance
|
|
55
|
+
collapsing onto the engine's built-in default seed (identical renders). Used only when the
|
|
56
|
+
caller passes no seed; callers that want a specific identity still pass seed=."""
|
|
57
|
+
import random
|
|
58
|
+
home = os.environ.get("CAPIUM_HOME") or os.path.join(os.path.expanduser("~"), ".capium")
|
|
59
|
+
path = os.path.join(home, "machine-seed")
|
|
60
|
+
try:
|
|
61
|
+
with open(path) as f:
|
|
62
|
+
return int(f.read().strip())
|
|
63
|
+
except (OSError, ValueError):
|
|
64
|
+
pass
|
|
65
|
+
s = random.SystemRandom().randrange(1, 2**31)
|
|
66
|
+
try:
|
|
67
|
+
os.makedirs(home, exist_ok=True)
|
|
68
|
+
with open(path, "w") as f:
|
|
69
|
+
f.write(str(s))
|
|
70
|
+
except OSError:
|
|
71
|
+
pass
|
|
72
|
+
return s
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _profile_seed(user_data_dir):
|
|
76
|
+
"""Stable seed unique to this (machine, profile) pair -- a hash of the per-machine seed and the
|
|
77
|
+
profile directory. Each persistent profile (user_data_dir) on each machine gets a distinct,
|
|
78
|
+
consistent fingerprint, so no two profiles collide (not the same path on different machines,
|
|
79
|
+
nor different profiles on one host) and a profile keeps one identity across launches."""
|
|
80
|
+
import hashlib
|
|
81
|
+
base = "%d:%s" % (_machine_seed(), os.path.abspath(user_data_dir))
|
|
82
|
+
return int.from_bytes(hashlib.sha256(base.encode()).digest()[:4], "big") % (2**31 - 1) + 1
|
|
83
|
+
|
|
84
|
+
|
|
49
85
|
def get_default_stealth_args(seed=None, platform="windows", screen=None, mobile_device=None, browser_brand=None):
|
|
50
86
|
"""Return the default per-launch fingerprint flags.
|
|
51
87
|
|
|
@@ -75,7 +111,9 @@ def get_default_stealth_args(seed=None, platform="windows", screen=None, mobile_
|
|
|
75
111
|
"primaryPointerType=2,availablePointerTypes=2,maxTouchPoints=5,"
|
|
76
112
|
"viewportEnabled=true,viewportMetaEnabled=true,shrinksViewportContentToFit=true",
|
|
77
113
|
"--touch-events=enabled", "--enable-viewport",
|
|
78
|
-
|
|
114
|
+
# Per-profile render noise ON (engine default), same as desktop: mobile canvas/WebGL/
|
|
115
|
+
# audio are unique + stable per seed instead of identical across profiles on one host.
|
|
116
|
+
"--no-first-run", "--no-default-browser-check",
|
|
79
117
|
"--window-size=%d,%d" % (sw, sh),
|
|
80
118
|
*(["--user-agent=" + profile["user_agent"], "--capium-preserve-user-agent"] if platform == "ios" else []),
|
|
81
119
|
] + (["--fingerprint-screen-width=%d" % sw, "--fingerprint-screen-height=%d" % sh] if screen else [])
|
|
@@ -110,10 +148,13 @@ def get_default_stealth_args(seed=None, platform="windows", screen=None, mobile_
|
|
|
110
148
|
# --capium-disable-cdp-stealth disables both policies on either engine.
|
|
111
149
|
# Published 1.2.0 selects engine 155.
|
|
112
150
|
]
|
|
113
|
-
#
|
|
114
|
-
#
|
|
115
|
-
#
|
|
116
|
-
|
|
151
|
+
# Per-profile render farbling is ON (the engine default) so canvas/WebGL/audio are unique AND
|
|
152
|
+
# stable per seed. Without it, every profile on a host renders identically -- a cross-instance
|
|
153
|
+
# correlation surface a detector clusters over time. The engine farbles deterministically per
|
|
154
|
+
# (seed,x,y) and skips low-entropy images (so trivial hashes aren't perturbed). Combined with
|
|
155
|
+
# the per-machine seed above, each machine gets a distinct, consistent render fingerprint.
|
|
156
|
+
# Opt out with CAPIUM_EXTRA_ARGS=--fingerprint-noise=false (e.g. when byte-exact canvas is
|
|
157
|
+
# required). Previously this forced =false, collapsing all profiles onto the host's raw render.
|
|
117
158
|
# A Windows persona's font metrics must match real Windows (needs Windows fonts
|
|
118
159
|
# present on the host); harmless elsewhere, so gate it to the windows persona.
|
|
119
160
|
if platform == "windows":
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: capiumbrowser
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.4
|
|
4
4
|
Summary: Drop-in stealth browser SDK on top of Playwright (Capium Chromium).
|
|
5
5
|
Author: Capzy
|
|
6
6
|
License: Capzy capiumbrowser SDK License
|
|
@@ -807,7 +807,7 @@ non-zero if the environment isn't ready. A bare `python -m capiumbrowser` runs `
|
|
|
807
807
|
| `no license configured` | Set `CAPIUM_LICENSE_KEY`, pass `license_key=…`, or create `~/.capium/license` (`KEY=cap_…`). |
|
|
808
808
|
| `CapiumSeatLimitError` | Free tier is 1 concurrent session — close the other Capium browser (or upgrade the tier). |
|
|
809
809
|
| 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. |
|
|
810
|
-
| FPJS `tampering: true` | Prefer a matching-OS host
|
|
810
|
+
| 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). |
|
|
811
811
|
| "Windows persona but missing fonts" | Supply real `C:\Windows\Fonts\*.ttf` (see [fonts](#fonts)) or set `CAPIUM_SUPPRESS_FONT_WARNING=1`. |
|
|
812
812
|
| `os_mismatch: true` | A network/transport signal (genuine Chrome shows it too behind some proxies) — a routing concern, not the browser. |
|
|
813
813
|
| Headed browser won't start on a server | Run under `Xvfb` and export `DISPLAY=:99`. |
|
|
@@ -30,9 +30,11 @@ def test_windows_gets_font_metrics_others_do_not():
|
|
|
30
30
|
assert "--fingerprint-windows-font-metrics" not in a
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
def
|
|
33
|
+
def test_noise_on_by_default():
|
|
34
|
+
# Per-profile render farbling is the engine default now; the SDK no longer forces it off,
|
|
35
|
+
# so canvas/WebGL/audio are unique + stable per seed instead of identical across profiles.
|
|
34
36
|
args = config.get_default_stealth_args(seed=1, platform="linux", screen=None)
|
|
35
|
-
assert "--fingerprint-noise=false" in args
|
|
37
|
+
assert "--fingerprint-noise=false" not in args
|
|
36
38
|
|
|
37
39
|
|
|
38
40
|
def test_screen_coherence_flags():
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|