Skip to Content
GuidesBrowser fingerprints

Browser fingerprints

A web client runs in a browser, and the browser is part of its identity. 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 output is data: opentele2 does not drive a browser or inject anything, so you hand the values to the automation tool you already use.

Note:

One identity, one seed. Seed the generator with an id you store with the account, and the same browser comes back on every run, in every language. Two accounts that share a seed share a browser.

Generate headers

headers.py
from opentele2.browser import HeaderGenerator headers = HeaderGenerator(browser="chrome", os="windows").generate(seed="my-id") print(headers["User-Agent"]) # Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36

The class takes browserforge’s argument names and defaults, so browserforge code keeps working.

The headers come in sending order, from sec-ch-ua to Accept-Language, identical in all three languages for one seed and options.

Narrow the options

PythonNodeRust (HeaderOptions)Default
browserbrowsersbrowserschrome, firefox, safari, edge
osososwindows, macos, linux, android, ios
devicedevicesdevicesdesktop, mobile
localelocaleslocalesen-US; at most ten, most preferred first
http_versionhttpVersionhttp_version2
strictstrictstrictoff: relax the options when nothing fits

A browser can carry bounds on its major version: Browser(name, min_version, max_version, http_version) in Python, { name, minVersion, maxVersion } in Node, opentele2_browser::Browser in Rust.

options.py
from opentele2.browser import Browser, HeaderGenerator generator = HeaderGenerator( browser=[Browser("firefox", min_version=120)], os="linux", locale=["de-DE", "en-US"] ) headers = generator.generate(seed=7, request_dependent_headers={"Referer": "https://web.telegram.org/"}) print(headers["User-Agent"]) # ... Firefox/150.0 print(headers["Accept-Language"]) # de-DE;q=1.0, en-US;q=0.9

generate(...) takes the same options again to override the generator’s for one call, plus user_agent and request_dependent_headers.

Generate a full fingerprint with screen constraints

A fingerprint is drawn for a set of headers and carries them. Screen bounds are inclusive, in CSS pixels; without strict, a bound nothing meets is dropped instead of failing.

fingerprint.py
from opentele2.browser import FingerprintGenerator, Screen generator = FingerprintGenerator(screen=Screen(min_width=1280, max_width=1920), os="windows") fingerprint = generator.generate(seed=42) print(fingerprint.screen.width, fingerprint.screen.height) # 1366 768 print(fingerprint.navigator.platform, fingerprint.navigator.language) # Win32 en-US print(fingerprint.headers["User-Agent"] == fingerprint.navigator.userAgent) # True

FingerprintGenerator(screen, strict, mock_webrtc, slim, **header_kwargs): the keyword arguments of HeaderGenerator choose the headers. strict=True raises ValueError when no screen fits.

Reproduce it with a seed

The same seed and options give byte-identical output on any platform, in Rust, Python and Node. A seed is a string or an integer; an integer counts as its decimal text, so 42 and "42" are the same seed. Without a seed every call draws from the operating system’s entropy.

seed.py
from opentele2.browser import FingerprintGenerator generator = FingerprintGenerator() print(generator.generate(seed=42).dumps() == generator.generate(seed="42").dumps()) # True print(generator.generate().dumps() == generator.generate().dumps()) # False: no seed

Hand it to a browser automation tool

Take the values your tool sets (user agent, window and screen size, locale, extra headers) from the fingerprint, and keep the whole fingerprint as JSON for a script that patches navigator and screen in the page. mock_webrtc and slim are only carried in the output, as mockWebRTC and slim, for such a script.

automation.py
import json from opentele2.browser import FingerprintGenerator, Screen fingerprint = FingerprintGenerator(screen=Screen(max_width=1920), os="windows").generate(seed="my-id") # Plain data: map these keys onto your tool's own launch or context options. browser_settings = { "user_agent": fingerprint.navigator.userAgent, "screen": {"width": fingerprint.screen.width, "height": fingerprint.screen.height}, "locale": fingerprint.navigator.language, "headers": {k: v for k, v in fingerprint.headers.items() if k.lower() != "user-agent"}, } print(json.dumps(browser_settings, indent=2)) full = fingerprint.dumps() # browserforge's JSON, for an in-page script
Warning:

A Web A or Web K session announces a browser user agent as its device. A fingerprint drawn with the same seed is a separate draw, not that browser: when one account uses both, check that the browser you run agrees with the profile it announces. See web devices.

Next

Last updated on