capiumbrowser 1.2.3__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.
Files changed (45) hide show
  1. {capiumbrowser-1.2.3/capiumbrowser.egg-info → capiumbrowser-1.2.4}/PKG-INFO +2 -2
  2. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/README.md +1 -1
  3. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/_version.py +1 -1
  4. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/browser.py +4 -1
  5. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/browser_async.py +3 -1
  6. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/config.py +46 -5
  7. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4/capiumbrowser.egg-info}/PKG-INFO +2 -2
  8. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/pyproject.toml +1 -1
  9. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/tests/test_config_args.py +4 -2
  10. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/LICENSE +0 -0
  11. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/MANIFEST.in +0 -0
  12. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/__init__.py +0 -0
  13. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/__main__.py +0 -0
  14. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/_driver.py +0 -0
  15. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/android-phones.json +0 -0
  16. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/browser-brands.json +0 -0
  17. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/channels.json +0 -0
  18. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/desktop.py +0 -0
  19. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/errors.py +0 -0
  20. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/human/__init__.py +0 -0
  21. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/human/behavior.py +0 -0
  22. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/ios-phones.json +0 -0
  23. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/licensing/__init__.py +0 -0
  24. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/licensing/client.py +0 -0
  25. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/licensing/download.py +0 -0
  26. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/licensing/readiness.py +0 -0
  27. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/mobile.py +0 -0
  28. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/network/__init__.py +0 -0
  29. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser/network/proxy.py +0 -0
  30. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser.egg-info/SOURCES.txt +0 -0
  31. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser.egg-info/dependency_links.txt +0 -0
  32. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser.egg-info/entry_points.txt +0 -0
  33. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser.egg-info/requires.txt +0 -0
  34. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/capiumbrowser.egg-info/top_level.txt +0 -0
  35. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/setup.cfg +0 -0
  36. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/tests/test_channels_manifest.py +0 -0
  37. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/tests/test_desktop_brands.py +0 -0
  38. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/tests/test_download_contract.py +0 -0
  39. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/tests/test_geoip_flags.py +0 -0
  40. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/tests/test_ios_profiles.py +0 -0
  41. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/tests/test_launch_viewport.py +0 -0
  42. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/tests/test_license_readiness.py +0 -0
  43. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/tests/test_mobile_profiles.py +0 -0
  44. {capiumbrowser-1.2.3 → capiumbrowser-1.2.4}/tests/test_proxy.py +0 -0
  45. {capiumbrowser-1.2.3 → 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
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 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). |
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 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). |
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.3"
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 = config.new_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 = config.new_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(
@@ -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
- "--no-first-run", "--no-default-browser-check", "--fingerprint-noise=false",
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
- # 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.append("--fingerprint-noise=false")
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
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 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). |
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`. |
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "capiumbrowser"
7
- version = "1.2.3"
7
+ version = "1.2.4"
8
8
  description = "Drop-in stealth browser SDK on top of Playwright (Capium Chromium)."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -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 test_noise_off_by_default():
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