Skip to main content
Each release publishes browser archives for Linux x64, Linux arm64, macOS arm64 and Windows x64 on GitHub Releases. Every release so far is built on Chromium 152.0.7977.83. The Python package (apostate on PyPI) and the Node package (@heretic-tech/apostate on npm) are released with the same version number when their code changes.

Unreleased

Changes on main since v0.4.3. The Python and Node packages will ship them as 0.4.4. No browser patch changed.
  • Node 22. The Node package needs Node 22 or later, and its engines field says so. It calls Promise.withResolvers, which Node 20 lacks, so on Node 20 every GeoIP lookup of 0.4.3 failed.
  • Dark themes. Both packages turn off Playwright’s prefers-color-scheme: light emulation, so a page reads the persona’s own theme. On 0.4.3, pass color_scheme="null" in Python or call page.emulateMedia({ colorScheme: null }) in Node. See prefers-color-scheme in the 0.4.3 packages.
  • Timezones. Both packages refuse a timezone that is not an IANA zone name, before launch. Python raises ConfigurationError and Node throws RangeError. In 0.4.3 an unknown name went into TZ, and a page’s Intl timezone read undefined.
  • GeoIP warning. The warning for a failed lookup says the persona uses en-US and the host’s timezone. In 0.4.3 it said the launch keeps the host’s own locale, which was wrong. The reason and the advice are joined without a double period.
  • Python diagnostics. Python launches carry apostate_diagnostics, as Node launches carry apostateDiagnostics. GeoIP warnings are in its ["warnings"] list.
  • Python sync API. Several browsers can be open at once in one thread. They share the thread’s driver, which stops when the last of them closes. In 0.4.3 a second launch() while one is open fails with Sync API inside the asyncio loop.
  • Launch errors. A launch error no longer carries the --apostate-profile value, which holds a proxy credential base64-encoded. The value reads --apostate-profile=<redacted>. In Python, a proxy URL in the error text has its credential replaced with <redacted>, and the rest of the text is kept. In 0.4.3 the text was cut at the first proxy URL, which dropped the browser’s own apostate: refusal line.
  • Sandbox. Both packages keep Chromium’s sandbox on where it can start: macOS, Windows, and Linux as a regular user outside a container, with no seccomp filter and with user namespaces allowed. Playwright otherwise passes --no-sandbox, and a headed window then shows Chromium’s unsupported-flag bar on its first tab, which took 56 pixels from innerHeight. An explicit chromium_sandbox or chromiumSandbox is kept. See A bar on the first tab.
  • Proxy credentials. Both packages count the 4096 limit for a username or password in bytes of UTF-8, as the browser does, and both refuse a malformed escape such as %zz.
  • Timezone case. The Node package refuses a timezone that differs from a zone name only in letter case, such as europe/berlin, as the Python package does. On Windows the Python package depends on tzdata, so it can check names on a host with no tz database.
  • Node first run. Every Node launch passes --no-first-run and --no-default-browser-check. launchProcess() did not, so a headed first launch of a new user data directory could stop at a first-run dialog.
  • Python CLI. apostate run forwards every argument after run to the browser, so apostate run --fingerprint=42 works without a -- separator, as it already did in the Node CLI.
  • Fonts. apostate fonts install windows also installs the Windows 11 Marlett, which the font repository it clones lacks. It reads only that file out of the liblaf/fonts Win11 release zip with HTTP range requests, and installs it only when its SHA-256 matches.
  • Catalogue. The catalogue the packages ship describes the seed as keyed on the version values v0.4.2 used, and names apostate/identity as the file a persistent profile stores its seed in. The browser’s own catalogue is unchanged.
  • MCP server. A new package in mcp/, @heretic-tech/apostate-mcp 0.1.0, gives an AI agent an Apostate browser with Playwright MCP’s tools. It needs Node 22 or later. MCP server describes it.
  • Test suite. tests/ checks what a page reads from the browser, offline against a local probe page and live against public detector pages, and writes each run to a dated results file. The offline tier and the MCP server’s test run in CI on Linux x64 with the released browser. Test suite describes it, and Results has the published runs from macOS arm64 and Linux arm64.
  • Examples. examples/ holds runnable Python, Node, use-case, agent and Docker examples. Examples lists them.
  • Documentation. This site replaces the Markdown pages in docs/. docs/KNOWN_GAPS.md stays as a pointer, because the 0.4.3 browser’s --fingerprint-explain names it. The repository README and the PyPI and npm READMEs link to the site.

v0.4.3

Released 26 September 2026. Python and Node packages 0.4.3.
  • URLs. A Windows persona parses file paths in URLs as Windows Chrome does. new URL("c:/foo").protocol is file:, where other personas and stock Chromium on Linux and macOS give c:.
  • Seeds. A seed keeps its machine across Chrome updates and catalogue version changes. The machine is keyed on fixed version values, the ones v0.4.2 used, so a v0.4.2 seed presents the same machine in v0.4.3. An edit to a catalogue table still re-draws the choices that table decides.
  • CPU performance. navigator.cpuPerformance follows the persona’s core count and ignores the host’s CPU model, except for a macOS persona on a Mac.
  • Python. viewport=None means no viewport. Playwright had dropped the None and emulated a 1280x720 viewport.

v0.4.2

Released 25 September 2026. Browser archives only. No package was released at this version.
  • Fonts under a Windows persona. Ascent, descent and line gap come from the fonts’ Windows metrics as DirectWrite reads them, including the typo metrics a font asks for. Windows alias and legacy family names resolve, such as Courier, Times, Helvetica, MS Sans Serif and Franklin Gothic. Emoji and symbols fall back to Segoe UI Emoji, Segoe UI Symbol and Cambria Math.
  • Font install. apostate fonts install windows installs only the families of the Windows core font pack, lists the ones still missing, and takes --from DIR to install from a Windows Fonts folder.
  • Locale. --fingerprint-locale with one tag sets only the UI locale, and the language list is Chrome’s own default for that locale. A comma list sets the list exactly. The packages pass the GeoIP locale as one tag.
  • Voices. A persona lists its voices on a host with no speech engine. The Windows sets include the Google network voices desktop Chrome lists, and the en-US Windows set matches two real machines’ 22 voices.
  • WebGPU. GPUAdapterInfo.subgroupMinSize and subgroupMaxSize come from the GPU family instead of the host.
  • Window. A new window fills the persona’s work area, and a Windows persona opens maximized. The packages’ Xvfb display is 3840x2160, so any claimed screen fits.
  • Windows machines. Screen sizes and core counts follow a public corpus of Windows sessions. The taskbar is at the bottom, 40 pixels on Windows 10 and 48 on Windows 11. The 1920x1200 and 2048x1280 screens are gone, and the network is always 4g. These table changes give many seeds a different machine than v0.4.0 gave them.
  • Linux personas on ARM hosts keep navigator.platform as Linux x86_64, as Chrome does on every Linux CPU. The ARM host shows only in the Client Hints architecture.

v0.4.0

Released 23 September 2026. Python and Node packages 0.4.0.
  • Normal profile. launch() opens pages in a normal profile instead of an off-the-record context, on a temporary profile the driver deletes on close. new_context() stays off-the-record, as in Playwright. This needs Patchright 1.55 or Playwright 1.53 or later.
  • Windows system values. A Windows persona serves Windows system colours, Segoe UI for the CSS system fonts, Windows’ system-ui and default fonts, no BarcodeDetector, a 48 kHz AudioContext, the claimed speakers on a host with no sound card, the claimed GPU’s power-efficient codecs and the US Windows keyboard map.
  • CPU architecture. Windows and Linux personas claim the host’s CPU architecture, arm on an ARM host.
  • WebGPU. A host with no GPU serves the claimed adapter instead of none, and every GPU model has a WebGPU adapter. On Linux, requestAdapter() still returns null in headless mode and in a headed launch as root. See WebGPU in headless mode on Linux.
  • Widevine. The packages give the browser a Widevine CDM on first launch, copied from a local Google Chrome or downloaded from Google and checked by SHA-256. The Python CLI adds apostate provision-drm.
  • Linux displays. A headed launch on a Linux host with no display starts its own Xvfb, sized to the persona’s screen, and stops it on close.
  • Fonts. Each persona shows only its platform’s font families. The CLI adds apostate fonts install windows, fonts install macos and fonts export-macos.
  • Removed. The font metric and text raster emulation added in earlier releases, which measured as changing nothing detectors score.
  • Fixes. A Windows persona no longer crashes the browser in enumerateDevices() on a host with no sound card. WebGPU on a host with no GPU keeps the float32-filterable and float32-blendable features. The Python package extracts .tar.zst on Python before 3.14, and the Node package decompresses zstd itself on Node 22.15 and later.

v0.3.0

Released 22 September 2026. Python and Node packages 0.3.0.
  • Windows fonts and voices. The Windows core font pack is the Windows 11 English set, and every persona lists its own platform’s voices, spoken by a real speech provider.
  • Refused switches. Both packages refuse a misspelt --fingerprint* switch, such as --fingeprint-platform, and --fingerprint-noise=false, which turns noise on.
  • Persistent profiles. Both packages refuse a persistent profile on launch() and name launch_persistent_context() instead. The Node package also refuses --user-data-dir and --proxy-server in args, which it had dropped without a word.
  • GeoIP through SOCKS5. The lookup hands the endpoint’s name to the proxy instead of resolving it on the host.
  • Node package. It downloads from its own release, and an extraction failure names the tool that is missing.

v0.2.1

Released 22 September 2026. Python and Node packages 0.2.1.
  • Text. A persona derives sub-pixel text positioning by its own platform’s rule, so a Linux persona on a Mac measures text advances as Linux Chrome does.

v0.2.0

Released 21 September 2026. Node package 0.2.0.
  • Signed macOS build. The macOS bundle is Developer ID signed and notarized.
  • GPUs. A Windows persona can present many more NVIDIA and Intel models, registered on the measured GPU families by PCI device id, including the GeForce RTX 40 series.
  • WebGL. The GPU family’s WebGL limits reach pages on every host backend, Metal included.
  • WebRTC. Behind a SOCKS5 proxy, WebRTC offers only the address families the proxy can relay.
  • Readback noise. --fingerprint-noise, off by default, changes canvas and WebGL readback by one step per channel, seeded by the profile.
  • Extensions. The profile decides whether pages see chrome.runtime from an installed extension.
  • Install. Patchright is a dependency of both packages, so one install is enough. The packages find a browser already on disk before downloading one.

v0.1.0

Released 20 September 2026. Python and Node packages 0.1.0, and 0.1.1. The first public release. It is Chromium 152.0.7977.83 with a composer that builds a whole Windows, macOS or Linux machine from a seed before any other browser process starts.
  • Switches. --fingerprint, --fingerprint-platform, --fingerprint-anchor and --fingerprint-explain, the per-field switches, --fingerprint=host and --apostate-profile.
  • Persistent identity. A launch with --user-data-dir stores its seed in the directory and presents the same machine on every later launch.
  • Locale and timezone. They come from the launch or the host, never from the seed. A composed persona ignores the shell’s locale.
  • Proxies. --proxy-server accepts a credential in the URL. WebRTC relays UDP through a SOCKS5 proxy or opens no UDP socket.
  • Packages. The Python and Node packages download and verify the browser, look up the exit’s locale and timezone, and launch it through Patchright or Playwright. The Node package also drives Puppeteer.
The 0.1.1 packages install the v0.1.0 browser. They fetch the release’s manifest when the package carries none, ship the GeoIP lookup inside the Python package with SOCKS5 support, map every country to a locale, and send a SOCKS proxy credential to the browser instead of the driver.