capiumbrowser 1.2.3__tar.gz → 1.3.0__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.3.0}/PKG-INFO +2 -2
  2. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/README.md +1 -1
  3. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/_version.py +1 -1
  4. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/browser.py +4 -1
  5. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/browser_async.py +3 -1
  6. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/channels.json +16 -16
  7. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/config.py +53 -11
  8. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0/capiumbrowser.egg-info}/PKG-INFO +2 -2
  9. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/pyproject.toml +1 -1
  10. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/tests/test_config_args.py +4 -2
  11. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/LICENSE +0 -0
  12. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/MANIFEST.in +0 -0
  13. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/__init__.py +0 -0
  14. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/__main__.py +0 -0
  15. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/_driver.py +0 -0
  16. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/android-phones.json +0 -0
  17. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/browser-brands.json +0 -0
  18. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/desktop.py +0 -0
  19. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/errors.py +0 -0
  20. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/human/__init__.py +0 -0
  21. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/human/behavior.py +0 -0
  22. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/ios-phones.json +0 -0
  23. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/licensing/__init__.py +0 -0
  24. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/licensing/client.py +0 -0
  25. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/licensing/download.py +0 -0
  26. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/licensing/readiness.py +0 -0
  27. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/mobile.py +0 -0
  28. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/network/__init__.py +0 -0
  29. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser/network/proxy.py +0 -0
  30. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser.egg-info/SOURCES.txt +0 -0
  31. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser.egg-info/dependency_links.txt +0 -0
  32. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser.egg-info/entry_points.txt +0 -0
  33. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser.egg-info/requires.txt +0 -0
  34. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/capiumbrowser.egg-info/top_level.txt +0 -0
  35. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/setup.cfg +0 -0
  36. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/tests/test_channels_manifest.py +0 -0
  37. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/tests/test_desktop_brands.py +0 -0
  38. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/tests/test_download_contract.py +0 -0
  39. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/tests/test_geoip_flags.py +0 -0
  40. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/tests/test_ios_profiles.py +0 -0
  41. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/tests/test_launch_viewport.py +0 -0
  42. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/tests/test_license_readiness.py +0 -0
  43. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/tests/test_mobile_profiles.py +0 -0
  44. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/tests/test_proxy.py +0 -0
  45. {capiumbrowser-1.2.3 → capiumbrowser-1.3.0}/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.3.0
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.3.0"
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(
@@ -1,36 +1,36 @@
1
1
  {
2
- "_comment": "SINGLE SOURCE OF TRUTH for the current stable Capium browser build per OS/arch. Each OS reaches stable independently -- edit one entry without touching the others. This file ships inside the wheel (the SDK reads it to pick each host's stable build) AND is published to the download server by the release pipeline. `version` is the reported Chromium version (what the browser reports to the customer, names the R2 folder); `engine_version` is the actual built Chromium engine (box_package verifies the binary against it) -- it differs from `version` when a platform reports a spoofed patch (Windows reports .85 on the .84 engine). `revision` is our packaging counter -- the served R2 folder is chromium-v<version>.<revision>/, ALWAYS dotted-suffixed starting at 1. A Chromium version bump resets revision to 1. `published: false` means the tag is declared but no artifact exists yet.",
2
+ "_comment": "SINGLE SOURCE OF TRUTH for the current stable Capium browser build per OS/arch. Each OS reaches stable independently -- edit one entry without touching the others. This file ships inside the wheel (the SDK reads it to pick each host's stable build) AND is published to the download server by the release pipeline. `version` is the reported Chromium version (what the browser reports to the customer, names the R2 folder); `engine_version` is the actual built Chromium engine (box_package verifies the binary against it) -- it differs from `version` when a platform reports a spoofed patch (Windows/macOS report .48 on the .47 engine). `revision` is our packaging counter -- the served R2 folder is chromium-v<version>.<revision>/, ALWAYS dotted-suffixed starting at 1. A Chromium version bump resets revision to 1. `published: false` means the tag is declared but no artifact exists yet.",
3
3
  "schema": 1,
4
- "updated": "2026-10-21",
4
+ "updated": "2026-10-24",
5
5
  "channels": {
6
6
  "stable": {
7
7
  "windows-x64": {
8
- "version": "155.0.8059.85",
9
- "engine_version": "155.0.8059.84",
10
- "revision": 2,
11
- "sha256": "905bb081d5234338237b6a4c3df7ef3fbb8d20d0049adde982027494b87e4ed2",
8
+ "version": "156.0.8078.48",
9
+ "engine_version": "156.0.8078.47",
10
+ "revision": 1,
11
+ "sha256": "1c4dff0da8a61036b1e14a2bbe91c79a8a083cf91879399ab5cf57d68f0e865b",
12
12
  "published": true,
13
13
  "license_status_protocol": 1
14
14
  },
15
15
  "macos-arm64": {
16
- "version": "155.0.8059.84",
17
- "engine_version": "155.0.8059.84",
18
- "revision": 2,
19
- "sha256": "5c4ab089d7925a3b86fd891cfbe9de95777c46fc7616990a94b15b891c89775f",
16
+ "version": "156.0.8078.48",
17
+ "engine_version": "156.0.8078.47",
18
+ "revision": 1,
19
+ "sha256": "d545647a102c851394edbb3d6281917e5feabf1909bb128091b3eb9ed4326ee7",
20
20
  "published": true,
21
21
  "license_status_protocol": 1
22
22
  },
23
23
  "linux-x64": {
24
- "version": "155.0.8059.84",
25
- "engine_version": "155.0.8059.84",
26
- "revision": 2,
27
- "sha256": "e9e18dd9f23baa500e1be0a7075096f6e6c8fb3a37150c96bd96fd4e58518880",
24
+ "version": "156.0.8078.47",
25
+ "engine_version": "156.0.8078.47",
26
+ "revision": 1,
27
+ "sha256": "ff7019affcba442ea0fd1e3049d772cc26140a61615dadb8d383960b1f68a47f",
28
28
  "published": true,
29
29
  "license_status_protocol": 1
30
30
  },
31
31
  "linux-arm64": {
32
- "version": "155.0.8059.84",
33
- "engine_version": "155.0.8059.84",
32
+ "version": "156.0.8078.47",
33
+ "engine_version": "156.0.8078.47",
34
34
  "revision": 1,
35
35
  "sha256": null,
36
36
  "published": false
@@ -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 [])
@@ -103,17 +141,21 @@ def get_default_stealth_args(seed=None, platform="windows", screen=None, mobile_
103
141
  "primaryPointerType=4,availablePointerTypes=4",
104
142
  "--no-first-run",
105
143
  "--no-default-browser-check",
106
- # Engine 153 redirects main-world evaluations by default. Development
107
- # 155 honors the requested context and keeps console masking independent:
108
- # --capium-isolate-cdp-eval opts into legacy isolation;
109
- # --capium-disable-console-mask restores page/worker console delivery;
110
- # --capium-disable-cdp-stealth disables both policies on either engine.
111
- # Published 1.2.0 selects engine 155.
144
+ # CDP stealth defaults (engine 156): inspector-frame scrub ON (hides the
145
+ # UtilityScript/eval source-URL leak from Error.stack -- Patchright-equivalent,
146
+ # does not trip anti-detect ML); console mask OFF (ON makes developer_tools=false
147
+ # -> FPJS anti_detect/tampering) -- opt in with --capium-enable-console-mask; main-
148
+ # world evaluate isolation OFF (ON breaks page-global access for solvers) -- opt in
149
+ # with --capium-isolate-cdp-eval. --capium-disable-cdp-stealth turns everything off.
150
+ # See docs/STEALTH-FLAGS.md.
112
151
  ]
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")
152
+ # Per-profile render farbling is ON (the engine default) so canvas/WebGL/audio are unique AND
153
+ # stable per seed. Without it, every profile on a host renders identically -- a cross-instance
154
+ # correlation surface a detector clusters over time. The engine farbles deterministically per
155
+ # (seed,x,y) and skips low-entropy images (so trivial hashes aren't perturbed). Combined with
156
+ # the per-machine seed above, each machine gets a distinct, consistent render fingerprint.
157
+ # Opt out with CAPIUM_EXTRA_ARGS=--fingerprint-noise=false (e.g. when byte-exact canvas is
158
+ # required). Previously this forced =false, collapsing all profiles onto the host's raw render.
117
159
  # A Windows persona's font metrics must match real Windows (needs Windows fonts
118
160
  # present on the host); harmless elsewhere, so gate it to the windows persona.
119
161
  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.3.0
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.3.0"
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