Skip to main content

Hexium Browser

Hexium Browser — Launch like Chrome. Stay undetected.

Latest Version 0.1.0 Chromium 151.0.7922.174.1 Python 3.9+ Playwright AGPL-3.0

Launch like Chrome. Stay undetected.

Playwright in. Chrome 151 out. Built by HeadlessX Labs.

Sites see Google Chrome 151. You see Hexium Browser — a C++ persona compiled into Chromium, persistent disk profiles, humanize, and GeoIP locale. No JS injectors.


Headless Google search, new profile — examples/google_search_human_headless_new_profile.py

Features

  • Playwright launch() — headed and --headless=new
  • Linux x86_64 binary in this alpha (Windows and macOS not supported yet)
  • Persistent disk profiles (real tabs, not Incognito)
  • C++ persona presets — Linux default linux-native; see Personas
  • Seeded fingerprint sample (fingerprint= or auto --hexium-seed=) — not a new GPU every page
  • Humanized mouse, keys, and scroll (humanize=True)
  • GeoIP timezone, locale, and WebRTC IP from the egress IP (on by default)
  • Chrome 151 web identity (User-Agent and related surface)

Depth lives in docs/. This README is the quickstart.

Launch

from hexium_browser import launch

browser = launch(headless=True)  # new ~/.hexium/profiles/hexium-session-* + new fingerprint
browser = launch(
    profile="Work",
    headless=True,
    proxy="http://user:pass@host:port",
    humanize=True,
    fingerprint="account-1",
)  # sticky ~/.hexium/profiles/Work

browser.new_page() opens a tab. Bare launch() is a new visitor each time; use profile="Work" or HEXIUM_USER_DATA_DIR to return to the same identity.

python examples/linux_chrome_persona.py
python examples/windows_chrome_persona.py --headed
python examples/stealth_test.py
python examples/open_google.py

Install

The Python package is not on PyPI. Install from source:

pip install -e '.[geoip]'

Requires Python 3.9+ and the Playwright driver (ships with the playwright package). Do not install Playwright’s Chromium as the browser — Hexium launches its own Chrome 151 binary.

Optional GeoIP extra: geoip2 + socksio. GeoIP is on by default; without the extra, launch continues and timezone stays the sampled UTC.

Profiles

Hexium is a real Chrome user-data-dir, not Incognito. Bare launch() creates a new ~/.hexium/profiles/hexium-session-* and a new fingerprint. Named profiles stick:

hexium-browser profiles
hexium-browser profiles new Work
hexium-browser profiles use Work
hexium-browser profiles last
from hexium_browser import launch
launch()  # new identity
launch(profile="Work")  # returning visitor

The sampled persona sticks on a named profile until you pass a new fingerprint= or use another profile=.

Migrating from Playwright? One-line change:

- from playwright.sync_api import sync_playwright
- pw = sync_playwright().start()
- browser = pw.chromium.launch()
+ from hexium_browser import launch
+ browser = launch()

page = browser.new_page()
page.goto("https://example.com")
# ... rest of your code works unchanged

page.goto(), click(), fill(), locator(), and browser.close() are the same Playwright objects. Do not pass executable_path or channel. browser.new_page() is a tab on a persistent disk profile (not Incognito). If you used browser.new_context(), switch to launch(profile="Work") or keep calling new_page().

Why Hexium Browser?

  • JS stealth injectors break — they patch navigator in page JS. Detection sites look for the patch. Hexium does not inject stealth scripts.
  • Persona is compiled in — GPU, screen, UA, and hardware reporting follow a sampled Chrome persona at the C++ layer, plus a persistent profile on disk.
  • Same Playwright APIlaunch(), new_page(), click(), fill(). Swap the import.
  • Humanize is a flag — Bézier mouse, per-character typing, realistic scroll. A virtual mouse pointer is on whenever humanize is on; pass show_cursor=False for stealth oracles.

Hexium does not solve CAPTCHAs. Bring your own proxy. Use the Playwright API you already know.

Test results

Captured 12 Sep 2026 against live oracles with Chrome 151 (examples/stealth_test.py, examples/recaptcha_score.py, examples/fingerprint_scan_test.py). These are screenshots, not a guarantee that every site will score the same.

Oracle What the capture shows
reCAPTCHA v3 demo score 0.9
BrowserScan bot detection Normal
deviceandbrowserinfo.com You are human! (isBot: false)
bot.sannysoft.com WebDriver missing, window.chrome present, plugins 5, UA Chrome/151
Rebrowser bot detector no webdriver / no __pwInitScripts (some checks need a click to fire)
reCAPTCHA v3 demo — score 0.9 BrowserScan — Normal
reCAPTCHA v3 demo — score 0.9 BrowserScan bot detection — Normal
deviceandbrowserinfo.com — You are human! bot.sannysoft.com — WebDriver passed
deviceandbrowserinfo.com — “You are human!” bot.sannysoft.com — WebDriver missing, Chrome present, plugins 5
Rebrowser bot detector bot.incolumitas.com
Rebrowser bot detector — no webdriver, no Playwright init scripts bot.incolumitas.com — examples/stealth_test.py
CreepJS
CreepJS lies, noise=false CreepJS
CreepJS (noise=false) — examples/stealth_test.py CreepJS — examples/fingerprint_scan_test.py
fingerprint-scan.com

fingerprint-scan.com
fingerprint-scan.com — examples/fingerprint_scan_test.py

Stealth/oracle examples pass humanize=True and show_cursor=False. The virtual pointer is a DOM tell. launch() turns it on whenever humanize is on; pass False to hide it.

Humanize

launch() defaults to humanize=True, and show_cursor follows that. Playwright never moves the OS cursor — a standard mouse arrow is the virtual pointer.

from hexium_browser import launch

browser = launch(headless=False, humanize=True)
page = browser.new_page()
page.goto("https://example.com")
page.locator("#email").fill("user@example.com")
page.locator("button[type=submit]").click()
Interaction Playwright default humanize=True
Mouse Instant teleport Bézier curve, easing, slight overshoot
Clicks Instant Aim point + hold
Keyboard Instant fill Per-character timing
Scroll Jump Accelerate → cruise → decelerate
Humanize click demo Still
Humanize click demo Same demo — virtual highlighter mid-path
Headed Google search Still
Google search results after humanize After the headed search — “Nextjs Latest version”
DABI interaction oracle Still
DABI interaction oracle Same interaction run — still frame
Headless, reused profile Headless, fresh profile
Headless Google search still Headless Google search, new profile

Personas

launch(persona=…) or HEXIUM_PERSONA. Linux default is linux-native. Windows default is windows-native. macOS default is macos-native (alias mac-native). Pass windows-chrome or linux-chrome to sample. A *-native name that does not match this OS remaps to the host native. The engine binary alone uses the same host defaults.

Preset What sites see GPU / fonts When
linux-native This machine Host GPU, fonts, screen, CPU Linux default.
windows-native This Windows machine Host GPU, fonts, screen, CPU Windows default.
macos-native This macOS machine Host GPU/fonts macOS default. Alias mac-native. No macos-chrome.
linux-chrome Linux Chrome 151 Host GPU and fonts; screen/CPU/RAM still sampled persona="linux-chrome"
windows-chrome Win32 + Chrome 151 Sampled D3D11 WebGL + Segoe pack. On Linux: known WebGL −5% pixel-vs-name tell (not claimed fixed). persona="windows-chrome" (alias windows-1080p)
from hexium_browser import launch

launch()                              # Linux: linux-native + GeoIP tz/lang
launch(persona="linux-chrome")        # Linux UA, real GPU, sampled screen
launch(persona="windows-chrome")      # Win32 UA + D3D + Segoe pack
launch(fingerprint="off")             # fingerprint patches off
launch(persona="windows-chrome", fingerprint="account-1")  # same machine next time

Windows-on-Linux needs a Segoe pack (HEXIUM_FONTS_DIR, or the engine Windows font bundle). Desktop UA-CH model is empty (stock Chrome 151). Do not cartesian OS×GPU — one OS + one joint sample.

python examples/linux_chrome_persona.py
python examples/windows_chrome_persona.py --headed

What is random vs sticky

A fingerprint seed picks one coherent device. Same seed → same machine. Bare launch() mints a new seed (and a new hexium-session-*). profile="Work" or fingerprint="account-1" reuses persona.json.

Surface Source Sticky with seed?
Screen (width/height/avail/DPR) Joint Chrome desktop sample Yes
hardwareConcurrency, deviceMemory Same sample (Windows desktop min 4 GB) Yes
WebGL vendor/renderer, WebGPU vendor/arch Same sample (windows-chrome only) Yes
UA-CH platformVersion (Win10 vs Win11) Same sample; clamped to 10.0.0 / 15.0.0 (never 19.0.0); UA rewritten to 151.0.7922.174 Yes
Fonts Fixed Windows pack on windows-chrome; host on linux-* Yes (not shuffled per page)
Timezone, locale, navigator.languages, WebRTC IP GeoIP from egress IP (default on) Follows the proxy/IP, not the seed
Canvas LSB noise Off unless args=["--hexium-noise=on"] Seed-stable if you turn it on
Mouse / keys / scroll humanize=True (default) No — new path each action (human_preset="default" or "careful")

GeoIP does not re-roll the GPU. Explicit timezone= / locale= always win over GeoIP.

linux-chrome persona on example.com
linux-chrome persona on example.com (examples/linux_chrome_persona.py)

Binary

Linux x86_64 only for this alpha. Windows and macOS are not supported yet — we are actively working on them. Thanks for your patience.

Archives are named Hexium + engine version + OS + arch:

Hexium-{VERSION}-{os}-{arch}.tar.gz

This ship:

Hexium-151.0.7922.174.1-linux-x64.tar.gz

Unpack it and you get hexium-v151.0.7922.174.1/chrome (same layout as ~/.hexium/hexium-v{VERSION}/). Point HEXIUM_BINARY_PATH at that chrome, or let hexium-browser fetch unpack into the cache when downloads are published.

We are not cutting GitHub Releases until the Python package is on PyPI. Until then, use a local build or a tarball you were given — not a release asset.

Resolution order:

  1. HEXIUM_BINARY_PATH (alias HEXIUM_BINARY)
  2. $HEXIUM_OUT/hexium-v{VERSION}/chrome if it exists
  3. Cache under ~/.hexium/hexium-v{VERSION}/
  4. hexium-browser fetch from https://headlessx.dev/api/download (when that tarball exists)

Pin the engine with HEXIUM_VERSION.

Env Job
HEXIUM_DOWNLOAD_URL Download prefix (default https://headlessx.dev/api/download)
HEXIUM_VERSION Engine version (151.0.7922.174.1)
HEXIUM_BINARY_PATH Exact chrome path
HEXIUM_OUT Local out root
HEXIUM_CACHE_DIR Cache root (~/.hexium)
hexium-browser info
hexium-browser fetch

GeoIP

GeoIP is on by default. With hexium-browser[geoip], Hexium maps the egress IP (proxy exit, or the machine public IP when there is no proxy) to timezone, locale, languages, and --hexium-webrtc-ip=. Pass geoip=False to opt out. Explicit timezone= / locale= always win. Without the extra, launch continues and timezone stays the sampled UTC. Missing GeoLite2 still returns the exit IP so WebRTC does not leak LAN.

Docs

Doc What
Changelog 0.1.0 alpha and later
Usage launch(), personas, GeoIP, humanize, profiles
Personas linux-native, linux-chrome, windows-native, windows-chrome, macos-native
Contributing Install, pytest, bug reports
Support How to file issues
Security Vulnerability reports
CLAUDE.md Agent / contributor product rules

Persona notes: linux-native · linux-chrome · windows-native · windows-chrome · macos-native

Troubleshooting

Still getting blocked on aggressive sites (DataDome, Turnstile)?

Some sites detect --headless=new even with the C++ persona. Run headed on a virtual display when you have no monitor:

# Install Xvfb (virtual framebuffer)
sudo apt install xvfb

# Start virtual display
Xvfb :99 -screen 0 1920x1080x24 &
export DISPLAY=:99
from hexium_browser import launch

# Headed Chrome + residential proxy
browser = launch(headless=False, proxy="http://your-residential-proxy:port")
page = browser.new_page()
page.goto("https://example.com")
browser.close()

That is a real headed window on Xvfb — no physical monitor. Combine with the config below. Pass show_cursor=False on stealth oracles (the highlighter is a DOM tell). Hexium does not solve CAPTCHAs.

Recommended config for anti-bot sites

Most blocks come from missing one of these three things, not from browser fingerprint detection:

from hexium_browser import launch

browser = launch(
    proxy="http://your-residential-proxy:port",  # residential IP — datacenter IPs get blocked by reputation alone
    geoip=True,      # default; timezone + locale follow the proxy exit IP
    headless=False,  # headed — some sites still detect --headless=new
    humanize=True,   # default; mouse, keys, scroll
)

geoip=True needs pip install -e '.[geoip]'. Without the extra, launch still works and timezone stays the sampled UTC.

If the proxy supports SOCKS5, prefer it — SOCKS5 tunnels raw TCP and avoids HTTP CONNECT issues some proxies have with HTTP/2:

browser = launch(
    proxy="socks5://user:pass@proxy:1080",
    geoip=True,
    headless=False,
    humanize=True,
)

Linux default persona is linux-native. Windows default is windows-native. macOS default is macos-native. windows-chrome needs a Segoe pack (HEXIUM_FONTS_DIR, or the engine Windows font bundle). Named profile= keeps the same fingerprint; a bare launch() is a new visitor each time.

Sites challenge fresh sessions but work after first visit

Some sites challenge first-time visitors with no cookies over HTTP/2. That is a Chromium / site behavior, not a Hexium-only tell. Warm cookies once on a named profile, then reuse it:

from hexium_browser import launch

# First run: warm up with --disable-http2
browser = launch(profile="Shop", args=["--disable-http2"])
page = browser.new_page()
page.goto("https://example.com")  # writes cookies into ~/.hexium/profiles/Shop
browser.close()

# Later runs — same profile, no --disable-http2
browser = launch(profile="Shop")
page = browser.new_page()
page.goto("https://example.com")  # returning visitor
browser.close()

A bare launch() is a new hexium-session-* every time, so cookies never come back. Pin profile= (or user_data_dir=) when you need a returning visitor.

For a one-shot session, launch(args=["--disable-http2"]) forces HTTP/1.1. Only use that flag on sites that need it — most are fine on HTTP/2. SOCKS5 (proxy="socks5://user:pass@host:port") avoids HTTP CONNECT entirely.

What's next

Python hexium_browser already ships in this repo. First-party packages still to land (thin bindings over the same launch() contract — not a new fingerprint stack):

License

Last reviewed: 13 Sep 2026

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hexium_browser-0.1.0.tar.gz (1.8 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hexium_browser-0.1.0-py3-none-any.whl (1.8 MB view details)

Uploaded Python 3

File details

Details for the file hexium_browser-0.1.0.tar.gz.

File metadata

  • Download URL: hexium_browser-0.1.0.tar.gz
  • Upload date:
  • Size: 1.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.2

File hashes

Hashes for hexium_browser-0.1.0.tar.gz
Algorithm Hash digest
SHA256 90dd020ee5fcc25abcf45ae0293cc40243ccda8636be22d7652e4f668c830abb
MD5 e760fc2bf74ec4c80392e2cecf3f9a7d
BLAKE2b-256 99578f4c1bee8f12adecb49ace4c0a32d6d0eaa2edc1bed4512aff5f29db52ca

See more details on using hashes here.

File details

Details for the file hexium_browser-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: hexium_browser-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 1.8 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.2

File hashes

Hashes for hexium_browser-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 58c878b9ab72bb6b8b56841f1a1b9a50b20cf71ae10e9318fb8e432bc1afdd1d
MD5 9328c77fce4094d66414f5f578a83c0e
BLAKE2b-256 e3c36195e33eff78ac86ca0ab796cf2413a36391481511e6090c558e155673d1

See more details on using hashes here.

Release history Release notifications | RSS feed

0.1.1

2 files

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page