Skip to content

Latest commit

 

History

History
272 lines (224 loc) · 13.3 KB

File metadata and controls

272 lines (224 loc) · 13.3 KB

chromix (Python)

Drive the Chromix stealth Chromium engine with a CloakBrowser-compatible API — function names, keyword arguments, return types (Playwright Browser / BrowserContext) and CLOAKBROWSER_* env-var names all match the cloakbrowser wrapper, so existing CloakBrowser scripts run on Chromix by changing only the import:

- from cloakbrowser import launch
+ from chromix import launch
from chromix import launch

browser = launch(proxy="http://user:pass@proxy:8080", geoip=True, humanize=True)
page = browser.new_page()
page.goto("https://example.com")
browser.close()

Install

pip install chromix playwright

The distribution and import package are both named chromix. To install the SDK directly from a repository checkout instead, run:

pip install ./sdk/python playwright

On first launch the stealth Chromium binary is downloaded from this repo's GitHub Release, SHA256-verified, and cached under ~/.cache/chromix. Point CLOAKBROWSER_BINARY_PATH at a local build (e.g. your own chrome.exe) to skip the download.

Binary platforms

The SDK resolves Linux x64/ARM64, Windows x64/ARM64, and macOS x64/ARM64. On Windows, platform.machine() values ARM64/aarch64 (case-insensitive) select win-arm64 and chromix-win-arm64.zip; AMD64/x86_64 keep selecting win-x64 and chromix-win-x64.zip. Use native ARM64 Python on Windows ARM64. The SDK follows the reported architecture and does not fall back to an x64 bundle when the ARM64 asset is missing.

Both Windows ZIPs contain chromix/chromix.cmd and chromix/chrome.exe. ensure_binary() returns chrome.exe for Playwright; the cache is isolated by release tag and platform (~/.cache/chromix/<tag>/win-arm64/). Downloads require the matching asset in the selected release or CHROMIX_DOWNLOAD_HOST; SDK support alone does not publish an ARM64 browser. Windows ARM64 Widevine CDM discovery is not supported; an x64 CDM is not reused for ARM64.

API

Function Description
launch(**opts) Returns a Playwright Browser
launch_async(**opts) Async variant
launch_context(**opts) Returns a BrowserContext (native viewport by default)
launch_context_async(**opts) Async variant
launch_persistent_context(user_data_dir, **opts) Persistent profile
launch_persistent_context_async(user_data_dir, **opts) Async variant
build_args / get_default_stealth_args Arg assembly (32-bit random seed + native platform claim)
maybe_resolve_geoip(geoip, proxy, tz, locale, args) Egress IP → (tz, locale, exit_ip)
ensure_binary / clear_cache / binary_info / check_for_update Binary management
HumanConfig / resolve_human_config Behavioral-layer config (default / careful presets)
ProxySettings Playwright-shaped proxy TypedDict
export_cookies / import_cookies Explicit encrypted migration between live Chromium contexts
export_cookies_async / import_cookies_async Async Cookie migration variants
encrypt_cookies / decrypt_cookies Node-compatible authenticated Cookie envelope

Options (headless, proxy, args, stealth_args, timezone, locale, geoip, humanize, human_preset, human_config, extension_paths, license_key, browser_version, release_channel, user_agent, viewport, color_scheme) match CloakBrowser name-for-name; **kwargs passes through to playwright.chromium.launch() / browser.new_context().

Persistent contexts create .chromix-fingerprint-seed inside user_data_dir on first stealth launch and reuse it thereafter. The file is one decimal 32-bit seed followed by a newline, uses the same format as the Node SDK, and is published atomically for concurrent first launches. An explicit --fingerprint=... in args wins without creating or rewriting the file; stealth_args=False also skips seed I/O. Defaults claim the native persona: linux, windows, or macos. Default viewport geometry is native. The browser's public fingerprint mode supplies CPU/RAM 8/8, platform-specific screen/taskbar defaults and a 102400 MiB quota. The older seeded synthetic viewport/hardware pools require args=["--uxr-synthetic-device-tests=true"]; that separate test mode retains deterministic cross-SDK templates. Explicit viewport options still win outside measured mode.

Explicit synthetic seeds accept nonzero decimal uint64 values, including values above 2**32; Python and Node derive identical geometry. Malformed seeds, conflicting screen/taskbar aliases, invalid work areas and incomplete viewport pairs fail instead of silently choosing another template. --uxr-viewport-width/--uxr-viewport-height override the UI-strip template. Screen dimensions and DPR (including 1) are sent together with a configured viewport; viewport=None keeps native context geometry. The launch display backend requires a browser rebuilt from the current patch stack.

Public fingerprint flags

All listed public flags are passed through args: GPU vendor/renderer, hardware concurrency, device memory, screen/taskbar, brand/version/platform version, timezone/locale, storage quota, Windows font metrics, WebRTC IP/auto, noise/off, third-party cookies and FakeShadowRoot. Backend policy flags add GPU mode, restricted fonts, graph audio isolation, clock resolution, codec restrictions and effective CSS/input preferences. Voice tables are synthetic fixtures. See the complete flag contract for defaults and native-versus-SDK boundaries. These source changes require a rebuilt browser; updating this Python package alone does not upgrade an older executable.

browser = launch(args=[
    "--fingerprint=42",
    "--fingerprint-brand=Edge",
    "--fingerprint-brand-version=152.0.0.0",
    "--fingerprint-noise=false",
    "--fingerprint-allow-3p-cookies",
    "--enable-blink-features=FakeShadowRoot",
])

--fingerprint=off also accepts false/0/disable/disabled and strips the injected platform. Explicit timezone/locale and geoip=True still apply their regional settings; omit them for a native-persona comparison. noise=false keeps identity seeds and disables existing perturbation paths, not four new Canvas/WebGL/audio/client-rect noise implementations.

Ordinary launches now default to --fingerprint-gpu-backend=native; explicit WebGL name hints require compatibility. The SDK no longer injects --ignore-gpu-blocklist. Optional --fingerprint-audio-render=isolated uses the fingerprint seed (or an explicit audio seed), and --fingerprint-timer-resolution=7 means 7 milliseconds. See backend policy for limits and native acceptance status.

Encrypted Cookie migration

Install the optional cryptography extra: pip install 'chromix[cookies]'.

import os
from chromix import export_cookies, import_cookies

passphrase = os.environ['COOKIE_PASSPHRASE']
export_cookies(source_context, 'cookies.enc', passphrase=passphrase)
import_cookies(empty_destination_context, 'cookies.enc', passphrase=passphrase)

The AES-GCM/scrypt format interoperates with Node. Passphrases contain 12–1024 UTF-8 bytes; exports never replace an existing file. Imports require an empty context, skip expired entries, preserve host-only/domain, CHIPS and security attributes, and compare browser readback. No existing Cookies are cleared. CDP writes are not transactional: failure may leave partial contents. This is live-context migration, not OSCrypt or portable profile-database encryption. See the format and evidence boundaries.

Measured device launch

launch_context(device_pool={"host": "record.json", "records": ["record.json"], "seed": "42"}) validates whole evidence bundles and native host capabilities, then checks five live contexts before returning. Async and persistent context variants support the same option; the async persistent directory is keyword-only. Point CLOAKBROWSER_BINARY_PATH at the collected executable. Evidence defaults to a 24-hour maximum age, and extra launch/context overrides are rejected. Persistent profiles bind record and seed rather than rotating identities. Browser-returning launch does not support this option. See device pool documentation for collection, configuration, native fallback and remaining acceptance limits.

Custom font directory

fonts_dir="path/to/fonts" parses .ttf / .otf / .ttc family names and, on Linux, configures the actual Fontconfig directory. It does not install fonts into the Windows/macOS font backend or prove the file used for each glyph. Normal launches keep native font selection. Add --fingerprint-font-policy=restricted to enforce the parsed family pool on resolved native fonts and fallback; an explicit whitelist overrides generated names. Legacy substitutions and persona fallback still require synthetic-test opt-in. Measured device mode rejects fonts_dir and other per-field overrides.

browser = launch(fonts_dir="/path/to/fonts", args=["--fingerprint-font-policy=restricted"])

Env vars

  • CLOAKBROWSER_BINARY_PATH — use a local chrome binary instead of downloading
  • CLOAKBROWSER_VERSION / CLOAKBROWSER_RELEASE_CHANNEL — pin a version/channel
  • CLOAKBROWSER_GEOIP_TIMEOUT_SECONDS — geoip lookup timeout
  • CLOAKBROWSER_WIDEVINE_CDM — explicit Widevine CDM dir (DRM); CLOAKBROWSER_WIDEVINE=0 disables DRM
  • CHROMIX_CACHE_DIR / CHROMIX_DOWNLOAD_HOST — cache location / release host override

High-risk engine ports are available only through explicit browser args:

browser = launch(args=[
    "--fingerprint-devtools-runtime-suppression",
    "--fingerprint-canvas-bridge=127.0.0.1:9228",
    "--fingerprint-canvas-bridge-unsafe",
])

Runtime suppression can break console/binding-based automation. Canvas Bridge removes the sandbox from bridge renderer processes and forwards canvas/WebGL operations to the configured endpoint.

Proxy and GeoIP behavior

GeoIP is metadata, not a routing mechanism. The lookup uses the effective HTTP/HTTPS/SOCKS proxy and does not inherit environment proxies or NO_PROXY bypasses. Failed lookups do not fall back to the host connection. Metadata transport supports SOCKS4/4a/5/5h, including SOCKS5 credentials; that transport alone does not extend Chromium's proxy backend. A browser rebuilt with patches 0154–0157 also supports native SOCKS5 TCP authentication through the SDK's high-level proxy option. Endpoint-bound credentials travel in its launch environment, not argv or origin HTTP auth. Unrelated launches scrub inherited auth, including Windows case aliases; font environment merging cannot restore it. UDP ASSOCIATE and matching-native-build acceptance remain open. SOCKS5/4a metadata lookups resolve destination names at the proxy; SOCKS4 uses local IPv4 DNS. Single raw --proxy-server routes are supported for lookup; PAC/auto-detect, route lists, empty raw proxies, raw proxy credentials and conflicting --no-proxy-server are rejected. If raw --proxy-server and a high-level proxy are both supplied, their endpoints must match (default ports and equivalent IPv6 spellings are normalized); use the high-level option for credentials.

With a proxy, the SDK defaults to the native --force-webrtc-ip-handling-policy=disable_non_proxied_udp unless an explicit native policy was supplied. This does not guarantee the routing of all DNS, HTTP, QUIC or operating-system traffic.

--fingerprint-webrtc-ip=<IPv4|IPv6|auto> is supported. Auto resolves before launch through the same effective proxy; geoip=True reuses its one lookup to append the exit IP unless an explicit IP wins. Off mode skips IP injection. The browser changes local candidate/SDP/stats presentation, not sockets or STUN success; remote addresses, zero placeholders and relay allocations remain native. webrtc-fake-srflx and webrtc-fake-srflx-allow-udp (including uxr equivalents) remain rejected. The SDK's HTTP metadata service is unauthenticated and is not proof of an exit route. Bare-browser auto uses its own bounded HTTPS startup resolver; see the full resolution contract.

GeoIP lookup failures now raise ValueError. The timeout defaults to 10 seconds and accepts values greater than zero and at most 60. Python's synchronous DNS/connection setup cannot always be interrupted at that deadline; a late connection is rejected before sending the GeoIP request. IANA timezone data must be installed for timezone validation. Creating a later context with another proxy does not recompute browser-level locale or timezone/IP.

CLI

python -m chromix install      # pre-download the binary
python -m chromix info         # binary / cache info
python -m chromix widevine     # fetch the Widevine CDM (Linux x64)
python -m chromix clear-cache

Intentional differences from CloakBrowser

  1. license_key is accepted and ignored (one open tier).
  2. geoip queries ip-api.com over HTTP instead of a local GeoLite2 database; explicit timezone= / locale= always win.
  3. Python uses Playwright; the Node SDK also provides a native /puppeteer adapter.
  4. Widevine is enabled automatically when a CDM is present (installed Chrome, CLOAKBROWSER_WIDEVINE_CDM, or python -m chromix widevine).

License

The Python SDK is available under the BSD 3-Clause License. See LICENSE.