Changelog¶
All notable changes to this project are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased¶
0.4.1 - 2026-10-05¶
Changed¶
Clientkeeps its browser profile between runs (client-browsers/client-Nnext to the profile root, the first free slot for concurrent clients). Components the browser downloads once now stay installed, most importantly the Widevine CDM that streaming sites such as Spotify need: about 90 seconds after the very first start, then available immediately on every later run. Requests still run in separate contexts, so the profile keeps no site data. Copying a CDM into a fresh profile was measured again and is still flagged by fingerprint.com, while a CDM the browser downloaded itself is not.
0.4.0 - 2026-10-05¶
Changed¶
- Derived personas have readback noise off by default. On fingerprint.com's playground, the tampering model scored noisy personas 0.76-0.92 (most flagged) and noiseless ones about 0.24 (official build, rotating proxies, 2026-10-05).
Persona.from_seed(..., noise=True)turns it back on. Personas on one machine then share canvas, WebGL and audio hashes.
Added¶
consistencychecks for server and VM tells:gpu-real,audio-device,visibility,touchandnotification.- Botonomus Chromium launches pass
--bn-always-active(windows stay active, sodocument.hasFocus()is true under automation), and Windows Server hosts present the UA-CHplatformVersionof Windows 11 24H2 (19.0.0). Both need the new Botonomus Chromium build.
Not changed¶
- Widevine on fresh Botonomus Chromium profiles stays absent until the component updater installs it. Copying the CDM from a local Google Chrome was tried and rejected: fingerprint.com then flagged the browser as tampered (2 of 2 visits, against 0 of 2 without it, same proxy).
0.3.2 - 2026-10-05¶
Security¶
- WebRTC could reveal the real IP address behind a proxy. Chrome ignores
--force-webrtc-ip-handling-policy(only content_shell and headless shells read it) and takes the policy from the profile preferencewebrtc.ip_handling_policy. Sessions with a proxy, and everyClientbrowser, now writedisable_non_proxied_udpinto the profile's preferences before launch, so WebRTC never sends UDP outside the proxy. Verified in Chrome: no ICE candidates are gathered. Upgrade if you use proxies.
0.3.1 - 2026-10-04¶
Added¶
- Persona screen.
Persona.screenandPersona.taskbar(--bn-screen=WxH,--bn-taskbar=H, CSS pixels): a weighted real monitor resolution no larger than the host's, divided by the host's scale soscreen x devicePixelRatiois a real monitor size.HostInfogainsscreen(physical pixels) andscale, detected on Windows. With a persona screen the window opens at the origin and fills the persona's work area. Needs Botonomus Chromium with patch 0012. -
consistencyscreencheck: CSSdevice-width/device-heightmust matchscreen.width/height, and a persona screen must be what JavaScript reports, withavailHeight= height - taskbar and the window inside the work area. -
botonomus consistencycheckaccept-header: the loopback server records theAcceptheaders of the page and of an image, and fails when they advertiseimage/jxlwhile UA-CH claims Google Chrome (Chrome stable does not; the current Botonomus Chromium dev build does).
Changed¶
Client: the shared browser's throwaway profile now lives in the system temp directory instead ofprofile_root, so a killed process leaves nothing among your named profiles.Client: restoring an identity'slocalStorageopens its tab inside a tab slot, so it never exceedsmax_tabs.- Identity state on Windows: the identity directory's inherited permissions are replaced with full control for the current user (POSIX modes have no effect there).
0.3.0 - 2026-10-04¶
Added¶
botonomus.Client, an httpx-like layer over one shared Chrome.await botonomus.get(url)andClient.get/post/put/patch/delete/headload each request in a tab of an in-memory browser context: isolated cookies and storage, no profile on disk, and the browser, GPU and network processes shared.Responsehasstatus,headers,content,text,json(),html(rendered DOM),cookies,elapsed,viaandraise_for_status(). Non-GET methods, headers and bodies are applied to the navigation request itself. Options: per-client proxy (credentials through the loopback forwarder),max_tabs="auto"sized from free memory and CPUs,blockfor images, fonts, media or stylesheets,fresh_context,wait,timeout. The existingBotonomusAPI is unchanged.- HTTP fast path (
pip install "botonomus[http]"). After a tab has loaded a host without a challenge, later requests to it go throughcurl_cffiwith Chrome's TLS and HTTP/2 fingerprints, the headers the browser sent and the context's cookies (written back both ways). Challenge responses fall back to a tab; a host challenged twice stays on tabs. - Identities.
client.identity(name, proxy=...)keeps cookies,localStorageand the proxy in an owner-only state file and restores them into a fresh context (without contacting the site).backend="profile"opens the full Chrome profile for sites that need IndexedDB or service workers. One live use per identity across processes. - Recovery. If the shared browser dies, the client relaunches it, recreates every context from its last known state and retries the interrupted request once.
client.page(url)andidentity.page(url): a tab in the same context for full interaction (aHumanPagewithhumanize).botonomus.cdp.IsolatedContext(in-memory browser contexts with an optional proxy),Context.connectionandPage.main_frame_id.botonomus benchmark --mode contextsmeasures one browser with a context per tab; reports now includeper_instance_bytes. On the development machine, 6 held-open tabs used about 133 MiB each as contexts and about 224 MiB each as separate browsers.botonomus.HTTPStatusError.
Fixed¶
- Native driver: an event wait (for example
gotowaiting forload) now fails withTargetClosedErroras soon as its tab detaches or the connection closes, instead of hanging until the timeout. -
Native driver: a closed or detached page unregisters its event handlers, so a long-lived connection does not accumulate them.
-
Seven more detection sites:
apivoid,donutbrowser,cleantalk,pixelscan-bot,recaptcha-google,recaptcha-2captchaandturnstile-capskip, each with an extractor tested against a captured page. DetectionSite(click_button=...): the runner clicks a named button after loading, for pages that compute their result on demand.
0.2.0 - 2026-10-04¶
First public release on PyPI. It includes the measurement toolkit and Linux support below, and the restructure and features listed under "Included from the 1.0 development line".
Added¶
botonomus experiment. Interleaved A/B comparison of browser configurations ("arms") from a TOML file: rounds shuffled so arms share network conditions, a fresh profile and the next proxy per visit, per-(arm, site) pass rates with Wilson 95 % intervals,report.jsonandreport.md. Python:botonomus.diagnostics.load_spec,run_experiment.botonomus traceandtrace-diff. A diagnostic tracer that records which fingerprinting APIs a page reads (about 80 getters and methods) and the values returned, in the page, same-process frames and OOPIFs, and a diff of two traces. The hooks are visible to the page; workers are not traced.botonomus consistency. Local checks with no third-party traffic: canvas, WebGL and audio readback stability, exact solid-colour readback, identity agreement across page, iframe and dedicated, shared and service workers, media, voices, headless markers and window geometry.- Linux servers.
BrowserConfig(virtual_display=None)runs headed browsers on one shared Xvfb screen per manager when noDISPLAYis set (Trueforces it,Falsedisables it). In containers,--disable-dev-shm-usageis added when/dev/shmis under 512 MB and--no-sandboxonly when running as root. Newbotonomus.browser.VirtualDisplay,needs_virtual_display,container_flags. - Detection catalogue. Five new sites (
fingerprint-playground,pixelscan,fingerprint-scan,rebrowser,turnstile);browserscan,fingerprintandcreepjsnow decide verdicts. The catalogue lives inbotonomus.diagnostics.catalogue.
Changed¶
blockedverdict. Pages that say they are rate-limiting ("too many requests", "error 429", a 429 title) and challenge interstitials are reported asblockedinstead ofpassorunknown, counted separately inSiteSummary.blocked/blocked_rate, and excluded from pass rates.incolumitasignores its spec-levelWEBDRIVERrow, which stock Chrome fails too.CATALOGUEandSITESmoved frombotonomus.diagnostics.detectiontobotonomus.diagnostics.catalogue; import them frombotonomus.diagnostics.
Fixed¶
botonomus proxy-checkprinted?://?and no exit details for every proxy when the shared checker was used.- Unit tests pass on Linux (socket linger layout, real-clock warm-up timing).
Included from the 1.0 development line¶
The 0.1 lifecycle guarantees (bounded admission, cancellation-safe cleanup, cross-process profile locks, typed errors, credential-free logs) are unchanged.
Changed¶
- Package restructure. The code is split into single-responsibility packages:
config,core,browser,drivers,cdp,fingerprint,network,human,profiles,diagnosticsandcli. Every public module, class and function has a Google-style docstring.botonomusre-exports the main API. - The default driver is now
native, Botonomus' own stdlib CDP driver.patchrightandplaywrightremain available as optional extras. HumanProfileis renamedHumanConfig;HumanProfileandHuman(profile=...)remain as deprecated aliases.
Added¶
- Native driver mouse realism. Mouse events match a real Windows mouse: pressure 0.5 while a button is held, the
buttonsbitmask on every event, drag moves naming the held button, and click counts tracked with the Windows double-click time and rectangle. NewMouse.dblclick,Mouse.positionandMouse.buttons. Keyboard events carryKeyboardEvent.locationfor left/right modifiers. Runtime.enableregression tests. Integration tests check that console-preview CDP probes (ProxyownKeys,Error.stackgetter, error-name counter) do not fire under the native driver, with a positive control that enablesRuntimeto prove the page can detect it.- Personas (
botonomus.fingerprint). Seeded, internally consistentPersonavalues (hardware concurrency, device memory, time zone, optional GPU override, noise seed) drawn from weighted distributions, capped at the host's hardware and rendered as--bn-*switches for Botonomus Chromium.BrowserConfig(persona=...)accepts"auto"(stable per-profile seed from a per-installation key),"off", an int seed or aPersona. No JavaScript spoofing fallback: an explicit persona on stock Chrome raisesPersonaUnsupportedError. - Geo consistency (
botonomus.network.geoip). Exit lookup through the proxy with ip-api.com and an ipinfo.io TLS fallback, a provider protocol for custom services, and a per-proxyExitCachewith TTL and shared in-flight lookups.BrowserConfig(geoip=True)aligns locale and time zone with the exit;timezoneandallow_timezone_mismatchcontrol the time zone. NewGeoLookupErrorandGeoMismatchError. - Humanize v2.
HumanConfigpresets (default,careful,fast), mistype-and-correct with keyboard layouts (US QWERTY, DE QWERTZ, FR AZERTY, custom), per-session typing tempo and drift, digraph speed-up, idle micro-movements, overshoot on long moves, and an actionability wait (visible, enabled, stable box) before acting.HumanPageandBrowserConfig(humanize=...)humanizesession.pageautomatically;page.rawbypasses it. Opt-in profile warm-up withbotonomus.profiles.warm_up. - Botonomus Chromium installer.
botonomus.browser.install()fetches a release manifest, verifies its Ed25519 signature against a key embedded in the SDK (pure-Python RFC 8032 verification), checks archive size and SHA-256, extracts safely and installs atomically underBOTONOMUS_HOME.installed_binaries,find_installedanduninstallmanage installs.BrowserConfig(browser=...)chooses between Botonomus Chromium and Chrome. NewBinaryNotInstalledError,BinaryVerificationErrorandBinaryDownloadError. The release host and signing key are placeholders until the first binary release. - CLI and detection runner. The
botonomuscommand withinfo,install,uninstall,binaries,open,probe,detect,proxy-check,profiles list|remove|warmupandbenchmark, built onargparse. Browser commands accept--browser,--persona,--geoip,--timezone,--allow-timezone-mismatchand--humanize.botonomus.core.resolve_executableexposes which executable a launch uses;infoand detection reports use it and say whether it is a Botonomus build.botonomus detectruns eight public detection pages repeatedly and writes screenshots, page text and an aggregatedreport.jsonwith environment metadata.botonomus.diagnostics.run_detectionandDetectionSitesupport custom sites. - Proxy list loading and bulk checks:
botonomus.network.load_proxiesandcheck_proxies.
Fixed¶
- Proxy forwarder close hang on Windows. On the proactor event loop (CPython 3.12), a client connection reset could make
asyncio.Server.wait_closed()never return and leak the socket, and a reset during accept closed the listener for good. The forwarder now runs its own accept loop, registers every connection synchronously, closes each accepted socket itself and aborts transports on close.
[0.1.0] - 2026-10-03¶
Added¶
Botonomussession manager with a boundedmax_instancespool, cancellation-safe launch and cleanup, and typed errors.- Native Chrome launch with an explicit loopback debugging port and dedicated, cross-process locked profiles that persist cookies and storage.
- Patchright and Playwright drivers attached over CDP, and a first native CDP driver that never sends
Runtime.enableand works in an isolated world. - Locale flags, authenticated proxies through a loopback SOCKS5 forwarder, WebRTC non-proxied UDP blocking, and per-session launch arguments.
Humaninput: Bezier pointer paths with Fitts's-law timing, lognormal keystroke gaps and eased wheel scrolling.- Local probe page with ordinary-launch comparison, and a held-open concurrency benchmark.