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 onmain 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
enginesfield says so. It callsPromise.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: lightemulation, so a page reads the persona’s own theme. On 0.4.3, passcolor_scheme="null"in Python or callpage.emulateMedia({ colorScheme: null })in Node. See prefers-color-scheme in the 0.4.3 packages. - Timezones. Both packages refuse a
timezonethat is not an IANA zone name, before launch. Python raisesConfigurationErrorand Node throwsRangeError. In 0.4.3 an unknown name went intoTZ, and a page’sIntltimezone readundefined. - GeoIP warning. The warning for a failed lookup says the persona uses
en-USand 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 carryapostateDiagnostics. 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 withSync API inside the asyncio loop. - Launch errors. A launch error no longer carries the
--apostate-profilevalue, 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 ownapostate: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 frominnerHeight. An explicitchromium_sandboxorchromiumSandboxis 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 ontzdata, so it can check names on a host with no tz database. - Node first run. Every Node launch passes
--no-first-runand--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 runforwards every argument afterrunto the browser, soapostate run --fingerprint=42works without a--separator, as it already did in the Node CLI. - Fonts.
apostate fonts install windowsalso installs the Windows 11 Marlett, which the font repository it clones lacks. It reads only that file out of theliblaf/fontsWin11 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/identityas 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-mcp0.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.mdstays as a pointer, because the 0.4.3 browser’s--fingerprint-explainnames 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").protocolisfile:, where other personas and stock Chromium on Linux and macOS givec:. - 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.cpuPerformancefollows the persona’s core count and ignores the host’s CPU model, except for a macOS persona on a Mac. - Python.
viewport=Nonemeans no viewport. Playwright had dropped theNoneand 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 windowsinstalls only the families of the Windows core font pack, lists the ones still missing, and takes--from DIRto install from a WindowsFontsfolder. - Locale.
--fingerprint-localewith 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.subgroupMinSizeandsubgroupMaxSizecome 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.platformasLinux 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-uiand default fonts, noBarcodeDetector, a 48 kHzAudioContext, 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,
armon 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 macosandfonts 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 thefloat32-filterableandfloat32-blendablefeatures. The Python package extracts.tar.zston 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 namelaunch_persistent_context()instead. The Node package also refuses--user-data-dirand--proxy-serverinargs, 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.runtimefrom 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-anchorand--fingerprint-explain, the per-field switches,--fingerprint=hostand--apostate-profile. - Persistent identity. A launch with
--user-data-dirstores 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-serveraccepts 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.