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 launchfrom 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()pip install chromix playwrightThe distribution and import package are both named chromix. To install the
SDK directly from a repository checkout instead, run:
pip install ./sdk/python playwrightOn 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.
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.
| 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.
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.
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.
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.
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"])CLOAKBROWSER_BINARY_PATH— use a local chrome binary instead of downloadingCLOAKBROWSER_VERSION/CLOAKBROWSER_RELEASE_CHANNEL— pin a version/channelCLOAKBROWSER_GEOIP_TIMEOUT_SECONDS— geoip lookup timeoutCLOAKBROWSER_WIDEVINE_CDM— explicit Widevine CDM dir (DRM);CLOAKBROWSER_WIDEVINE=0disables DRMCHROMIX_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.
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.
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-cachelicense_keyis accepted and ignored (one open tier).geoipqueries ip-api.com over HTTP instead of a local GeoLite2 database; explicittimezone=/locale=always win.- Python uses Playwright; the Node SDK also provides a native
/puppeteeradapter. - Widevine is enabled automatically when a CDM is present (installed Chrome,
CLOAKBROWSER_WIDEVINE_CDM, orpython -m chromix widevine).
The Python SDK is available under the BSD 3-Clause License. See
LICENSE.