botonomus.fingerprint¶
Seeded personas and the Botonomus Chromium switches that apply them.
botonomus.fingerprint
¶
Seeded personas and the Botonomus Chromium switches that apply them.
A seed (by default derived from the profile name and a per-installation key)
becomes a Persona whose values are realistic for Windows desktops and
never exceed the host's hardware; Persona.to_switches renders it as
--bn-* command-line switches for Botonomus Chromium.
GPU_TABLE
module-attribute
¶
GPU_TABLE: Final[Mapping[GpuFamily, tuple[GpuOverride, ...]]] = MappingProxyType({'nvidia': (_angle('NVIDIA', 'NVIDIA GeForce GTX 1060 6GB', 7171), _angle('NVIDIA', 'NVIDIA GeForce GTX 1650', 8066), _angle('NVIDIA', 'NVIDIA GeForce GTX 1660 SUPER', 8644), _angle('NVIDIA', 'NVIDIA GeForce RTX 2060', 7944), _angle('NVIDIA', 'NVIDIA GeForce RTX 3050', 9479), _angle('NVIDIA', 'NVIDIA GeForce RTX 3060', 9476), _angle('NVIDIA', 'NVIDIA GeForce RTX 3070', 9348), _angle('NVIDIA', 'NVIDIA GeForce RTX 4060', 10370), _angle('NVIDIA', 'NVIDIA GeForce RTX 4070', 10118)), 'amd': (_angle('AMD', 'Radeon RX 580 Series', 26591), _angle('AMD', 'AMD Radeon RX 6600', 29695), _angle('AMD', 'AMD Radeon RX 6700 XT', 29663), _angle('AMD', 'AMD Radeon RX 7600', 29824), _angle('AMD', 'AMD Radeon(TM) Graphics', 5688)), 'intel': (_angle('Intel', 'Intel(R) UHD Graphics 620', 22807), _angle('Intel', 'Intel(R) UHD Graphics 630', 16018), _angle('Intel', 'Intel(R) UHD Graphics 770', 18048), _angle('Intel', 'Intel(R) Iris(R) Xe Graphics', 39497))})
Real Windows Chrome WebGL strings (ANGLE on Direct3D 11) grouped by vendor family.
The format matches what stock Chrome reports on Windows; device IDs are the PCI IDs of the listed parts. Every value is a plausible desktop or laptop GPU, but only values from the host's own family are safe to claim.
DEVICE_MEMORY_WEIGHTS
module-attribute
¶
(navigator.deviceMemory GB, relative weight) for Windows desktop Chrome.
An estimate shaped by the Steam Hardware & Software Survey's RAM shares (16 GB the plurality, 32 GB second and growing, 8 GB declining, 4 GB rare), expressed as the power-of-two values Chromium reports.
HARDWARE_CONCURRENCY_WEIGHTS
module-attribute
¶
HARDWARE_CONCURRENCY_WEIGHTS: Final[tuple[tuple[int, int], ...]] = ((4, 12), (6, 8), (8, 20), (12, 18), (16, 22), (20, 8), (24, 12))
(logical processors, relative weight) for Windows desktop Chrome.
An estimate, not a measurement: shaped by the Steam Hardware & Software Survey's physical-core shares (6 and 8 cores most common) mapped to logical counts with SMT / Hyper-Threading, plus Intel 12th-14th gen hybrid parts at 16, 20 and 24 threads. Replace with BrowserForge / apify fingerprint-suite data (Apache-2.0) when a measured distribution is imported.
PersonaSpec
¶
PersonaSpec = Literal['auto', 'off'] | int | Persona
"auto" (seed from the profile), "off", an explicit seed, or a persona.
GpuOverride
dataclass
¶
Unmasked WebGL vendor and renderer strings to report.
Rules (enforced on construction): each string is 1-256 printable ASCII
characters (0x20-0x7E) with no leading or trailing whitespace and no
", \ or =.
Attributes:
| Name | Type | Description |
|---|---|---|
vendor |
str
|
|
renderer |
str
|
|
Raises:
| Type | Description |
|---|---|
ConfigurationError
|
If either string breaks the rules above. |
HostInfo
dataclass
¶
HostInfo(logical_cpus: int, memory_gb: float, platform: str, screen: tuple[int, int] | None = None, scale: float = 1.0, windows_server: bool = False)
Hardware of the host that will run the browser.
A persona never claims more than the host can back up: detectors measure parallel speed-up and proof-of-work timing, so extra cores or memory show.
Attributes:
| Name | Type | Description |
|---|---|---|
logical_cpus |
int
|
Logical processor count (what stock Chrome reports as
|
memory_gb |
float
|
Total physical memory in GiB. |
platform |
str
|
|
screen |
tuple[int, int] | None
|
Primary display resolution in physical pixels, or |
scale |
float
|
Display scale factor ( |
windows_server |
bool
|
Whether the host runs Windows Server, whose UA-CH
|
Raises:
| Type | Description |
|---|---|
ConfigurationError
|
If |
device_memory
property
¶
The navigator.deviceMemory value stock Chrome reports on this host.
Mirrors Chromium's ApproximatedDeviceMemory: physical memory in MB
is rounded to the nearest power of two (ties round down), converted to
GB and clamped to the desktop range 2-32. A "16 GB" machine with 15.8 GiB
usable therefore reports 16, not 8.
Persona
dataclass
¶
Persona(seed: int, hardware_concurrency: int, device_memory: int, timezone: str | None = None, gpu: GpuOverride | None = None, noise: bool = True, screen: tuple[int, int] | None = None, taskbar: int = 48, platform_version: str | None = None)
The hardware and locale identity a Botonomus Chromium profile presents.
Build one with from_seed (or resolve_persona) so its values
are realistic and within the host's capabilities; direct construction is for
explicit overrides and is validated but not capped.
Attributes:
| Name | Type | Description |
|---|---|---|
seed |
int
|
64-bit key for canvas, WebGL and audio noise. C++ derives per-site keys from it and the top-level eTLD+1, so one profile is stable per site and unlinkable across profiles. |
hardware_concurrency |
int
|
|
device_memory |
int
|
|
timezone |
str | None
|
IANA time zone, or |
gpu |
GpuOverride | None
|
WebGL vendor/renderer override, or |
noise |
bool
|
Whether readback noise is on; |
screen |
tuple[int, int] | None
|
Screen size in CSS pixels, or |
taskbar |
int
|
Taskbar height in CSS pixels ( |
platform_version |
str | None
|
UA-CH |
Raises:
| Type | Description |
|---|---|
ConfigurationError
|
If any field is out of range or malformed. The time
zone is checked against the IANA database when one is installed
( |
from_seed
classmethod
¶
from_seed(seed: int, host: HostInfo, *, timezone: str | None = None, gpu: GpuOverride | None = None, noise: bool = False) -> Persona
Derive a realistic persona deterministically from a seed.
Each value is drawn from its weighted distribution after removing candidates above the host's capability, using BLAKE2b of the seed as the random source so the result is identical on every Python version and platform. A host below the smallest candidate reports its own value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seed
|
int
|
64-bit seed, in |
required |
host
|
HostInfo
|
Host capabilities that cap the claimed hardware. |
required |
timezone
|
str | None
|
IANA zone to present, or |
None
|
gpu
|
GpuOverride | None
|
Explicit GPU override; see the GPU table in
|
None
|
noise
|
bool
|
Canvas, WebGL and audio readback noise. Off by default: measured on 2026-10-05, fingerprint.com's tampering model scored noisy personas 0.76-0.92 (flagged above about 0.8) and noiseless ones 0.24, against 0.48 for no persona. Without noise, personas on one machine share their canvas, WebGL and audio hashes. |
False
|
Returns:
| Type | Description |
|---|---|
Persona
|
The persona. |
Raises:
| Type | Description |
|---|---|
ConfigurationError
|
For an invalid seed, host, time zone or GPU. |
to_switches
¶
Render the Botonomus Chromium command-line switches for this persona.
Returns:
| Type | Description |
|---|---|
str
|
Sorted |
...
|
override, |
tuple[str, ...]
|
only when noise is disabled. |
gpu_family
¶
gpu_family(vendor: str) -> GpuFamily | None
Classify a vendor or renderer string into a GPU family.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vendor
|
str
|
Any vendor-identifying string, for example |
required |
Returns:
| Type | Description |
|---|---|
GpuFamily | None
|
The family, or |
GpuFamily | None
|
software renderers such as SwiftShader or Microsoft Basic Render Driver). |
same_family_gpus
¶
same_family_gpus(host_vendor: str) -> tuple[GpuOverride, ...]
Overrides that stay within the host GPU's vendor family.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
host_vendor
|
str
|
The host's real vendor or renderer string (see
|
required |
Returns:
| Type | Description |
|---|---|
GpuOverride
|
The curated overrides for that family; empty when the family is unknown, |
...
|
because no override can be backed by the rendered output. |
resolve_persona
¶
resolve_persona(spec: PersonaSpec, profile_root: Path, profile: str, host: HostInfo, *, timezone: str | None = None) -> Persona | None
Turn a configuration value into the persona for one session.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
PersonaSpec
|
|
required |
profile_root
|
Path
|
Profile root directory holding the persona key. |
required |
profile
|
str
|
Profile name. |
required |
host
|
HostInfo
|
Host capabilities. |
required |
timezone
|
str | None
|
Time zone to present (for example from a geo lookup). It fills in an explicit persona's missing time zone but never replaces one. |
None
|
Returns:
| Type | Description |
|---|---|
Persona | None
|
The persona, or |
Raises:
| Type | Description |
|---|---|
ConfigurationError
|
For an unknown spec, invalid seed, profile or time zone, or an explicit persona that claims more cores or memory than the host has. |
persona_seed
¶
Return the stable 64-bit persona seed of a profile.
The seed is a keyed BLAKE2b of the normalized (lowercase) profile name, keyed
with 32 random bytes stored in profile_root/.botonomus/persona.key. The
same profile therefore keeps one identity across restarts, while the same
profile name on another installation gets an unrelated identity.
The key is created on first use and is never logged. Deleting it changes the
identity of every profile under profile_root. Blocking file I/O; it is a
single small read after the first call.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
profile_root
|
Path
|
Profile root directory (the one passed to the manager). |
required |
profile
|
str
|
Profile name, validated like |
required |
Returns:
| Type | Description |
|---|---|
int
|
The seed, in |
Raises:
| Type | Description |
|---|---|
ConfigurationError
|
If the profile name is invalid, or the key file exists but is not exactly 32 bytes. |
OSError
|
If the key cannot be read or created. |