Skip to Content
ConceptsClient versions

Client versions

Every API profile carries an app version, and the web profiles a browser user agent. A version that lags far behind the official app is a tell, so opentele2 keeps a built-in set of versions and can fetch the current ones from the clients’ public release sources.

The versions

One record, PlatformVersions (api::Versions in Rust), holds them all:

FieldWhat it is
android_app_version, android_app_version_codeTelegram Android, for example 13.0.3 and 7183
android_sdk_range, android_latest_sdkthe Android SDK levels generated devices run
android_x_app_versionTelegram X
ios_app_version, ios_build_number, ios_version_range, ios_system_versionTelegram iOS and the iOS versions
macos_app_version, macos_build_number, macos_system_versionTelegram for macOS
desktop_app_version, desktop_app_version_suffixTelegram Desktop, 7.3.1; bound to the tdata version
web_a_version, web_k_versionTelegram Web A and Web K
chrome_version, user_agentstable Chrome and the user agent of the default web profiles
firefox_versionstable Firefox, whose major bounds the Firefox web devices

Node spells the same fields in camelCase (androidAppVersion, chromeVersion, …).

Offline defaults

The built-in set ships inside the core: Versions::offline() in Rust, platformVersions() in Node, _native.platform_versions() in Python. Every function that takes versions (profiles, Generate, validation, consistency expectations) uses it when you pass none.

Live versions

opentele2-versions queries nine sources in parallel: Telegram Desktop, Android, Telegram X, iOS, macOS, Web K, Web A, Chrome and Firefox, from their public release feeds (GitHub releases, the stores’ lookup APIs, the Telegram stable channel, the web clients’ version files, Chrome for Testing and Mozilla’s product details). Each HTTP request has a timeout, 10 seconds by default. A source that fails or times out only leaves its fields unset; fetching never fails for the network, and with no network the result is empty.

The result is a patch: only the fields some source answered.

Importing opentele2 fetches the live versions once per process and applies them to opentele2.fingerprint.PLATFORM_VERSIONS; the API classes take their app versions from it. Fetching is best effort: on any failure the built-in versions stay.

versions.py
from opentele2.fingerprint import get_platform_versions versions = get_platform_versions() # PLATFORM_VERSIONS, fetched at import print(versions.android_app_version, versions.chrome_version, versions.firefox_version)

Set OPENTELE_NO_FETCH before the import to skip the fetch and stay on the built-in set, for tests, CI and offline machines:

terminal
OPENTELE_NO_FETCH=1 python main.py

Applying a patch

A patch is written onto a versions record field by field, with two rules:

  • desktop_app_version is reported but never applied. The Telegram Desktop version stays bound to the version written into tdata, 7.3.1, so a profile never claims a desktop build newer than the folder it came with.
  • chrome_version rebuilds user_agent of the default web profiles to match.

The Chrome and Firefox majors also decide the web device pool, so a web device generated for a unique id changes when either browser moves to a new major.

patch.py
from opentele2 import _native patch = {"chrome_version": "156.0.0.0", "android_app_version": "13.1.0"} versions = _native.apply_versions_patch(_native.platform_versions(), patch) print(versions["user_agent"]) # ... Chrome/156.0.0.0 Safari/537.36 print(_native.profile("TelegramAndroid", versions)["app_version"]) # 13.1.0 (7183)

_native.fetch_versions(timeout) returns the same patch the import applies.

Note:

Strict validation and the consistency expectations compare a profile’s app version with a versions record. Validate a profile against the same versions it was built with.

Last updated on