Skip to Content
ConceptsBrowser fingerprints

Browser fingerprints

A web client’s identity includes the browser it runs in. opentele2-browser generates consistent browser HTTP headers and full browser fingerprints (screen, navigator, codecs, plugins, WebGL card, fonts and more), sampled from Bayesian networks the way browserforge samples them. The same crate draws the web devices of the web API profiles.

PythonNodeRust
Headersopentele2.browser.HeaderGeneratorgenerateHeaders(options, seed)opentele2_browser::generate_headers(seed, &options)
Fingerprintsopentele2.browser.FingerprintGeneratorgenerateFingerprint(options, seed)opentele2_browser::generate_fingerprint(seed, &options)

The Python classes take browserforge’s argument names and defaults, so code written for browserforge’s HeaderGenerator and FingerprintGenerator keeps working.

Determinism

Every random draw comes from a seedable generator (xoshiro256**), and every set operation keeps first-seen order. The same seed and options give byte-identical output on any platform, in Rust, Python and Node. Without a seed every call draws from the operating system’s entropy. A seed is a string or an integer; an integer counts as its decimal text, so 42 and "42" are the same seed.

Headers, reproducible by seed
headers.py
from opentele2.browser import HeaderGenerator headers = HeaderGenerator(browser="chrome", os="windows").generate(seed="my-id") print(headers["User-Agent"])

All three give the same headers in the same order, starting with sec-ch-ua and ending with Accept-Language.

A full fingerprint
fingerprint.py
from opentele2.browser import FingerprintGenerator, Screen fingerprint = FingerprintGenerator(screen=Screen(max_width=1920)).generate(seed=42) print(fingerprint.navigator.userAgent, fingerprint.screen.width) print(fingerprint.dumps()[:80]) # JSON, as browserforge's dumps

Header options

browserforge / PythonNodeRust (HeaderOptions)Default
browserbrowsersbrowsers: Vec<Browser>chrome, firefox, safari, edge
osososwindows, macos, linux, android, ios
devicedevicesdevicesdesktop, mobile
localelocaleslocalesen-US; at most ten, most preferred first
http_versionhttpVersionhttp_version2; HTTP/1 falls back to HTTP/2 when no HTTP/1 sample fits
strictstrictstrictoff: relax the options when nothing fits them
user_agent (on generate)userAgentHeaderOverrides::user_agentthe User-Agent is one of these
request_dependent_headers (on generate)requestDependentHeadersHeaderOverrides::request_dependent_headersreplace a generated header in place, or append it

In Rust, the overrides go to HeaderGenerator::new(options)?.generate(&mut rng, &overrides), with Rng::from_seed(seed) as the generator.

A browser can carry bounds on its major version and its own HTTP version: Browser(name, min_version, max_version, http_version) in Python, { name, minVersion, maxVersion, httpVersion } in Node, opentele2_browser::Browser in Rust. In Python, HeaderGenerator.generate(...) takes the same options again to override the generator’s for one call.

Fingerprint options

Python (FingerprintGenerator)NodeRust (FingerprintOptions)Meaning
screen=Screen(...)screen: { minWidth, maxWidth, minHeight, maxHeight }screen: Option<Screen>inclusive bounds on the screen size, in CSS pixels
strictstrictstrictfail instead of dropping a screen constraint nothing meets
mock_webrtcmockWebRtcmock_webrtccarried to the output as mockWebRTC for an injector
slimslimslimcarried to the output for an injector
header keyword argumentsheader: { ... }header: HeaderOptionsthe headers the fingerprint is drawn for

Options nothing can satisfy raise ValueError in Python, reject with OT_INVALID_INPUT in Node (ERR_INVALID_ARG_VALUE for invalid ones) and return an opentele2_browser::Error in Rust.

Behaviour and data

The crate samples the networks as browserforge does, with seven browserforge defects fixed: Sec-Fetch values, OS relaxation, the HTTP/1 fallback, Edge detection, the user-agent constraint, the locale cap and request-dependent headers. In Node the first call parses the embedded networks, so both functions are async.

Important:

opentele2-browser is licensed Apache-2.0. It is a Rust port of browserforge  (Apache-2.0) and embeds the three Bayesian networks of the Python package apify_fingerprint_datapoints 0.15.0, part of Apify fingerprint-suite  (Apache-2.0). Its NOTICE  credits both. The rest of opentele2 is MIT.

Last updated on