Skip to Content
ConceptsSessions

Sessions

A session is what a client library needs to resume a logged-in account: a DC, its address and the auth key. opentele2 builds every format from a tdata account, and builds tdata back from each of them.

Warning:

A session string or file is a logged-in account, exactly like the tdata folder it came from. Never paste one into an issue, a chat or a log.

The formats

FormatWhat it holdsPythonNodeRust
Telethon string session (version 1)DC id, IPv4 or IPv6 address, port, auth keytelethon_string_sessiontelethonStringSessionsession::telethon::StringSession
Telethon .session file (SQLite, version 8) + .jsonthe same row, plus the API profile and account fieldsSaveSessionJson, FromSessionJsonopentele2/telethonsession::telethon_file (feature telethon-sqlite)
mtcute string session (version 3)primary DC and address, self user id, test mode, auth keymtcute_string_sessiontoStringSession (opentele2/mtcute)session::mtcute::StringSession
grammers 0.11 SessionDatahome DC, every production DC, the main DC key, the self user——opentele2_grammers::session_data

Which endpoint. Every conversion takes the first TCP endpoint of the account’s main DC from its stored MTP config when the account has one, and from the built-in production table otherwise. Telethon sessions take the IPv6 endpoint when you ask for it (ipv6 / use_ipv6) and the DC has one. A main DC without a usable endpoint fails with a bad-config error; an account without a key for its main DC fails with auth-key-not-found.

String sessions

strings.py
from opentele2._native import TData, mtcute_string_session, telethon_string_session folder = TData.load("tdata") # TData.load("tdata", "passcode") for a locked folder account = folder.main_account print(telethon_string_session(account)) # telethon_string_session(account, True) for IPv6 print(mtcute_string_session(account))

opentele2._native is the extension module the package is built on, typed by its _native.pyi stub. With a Telethon client at hand, Telethon’s own StringSession.save(client.session) gives the same string for a client from ToTelethon(..., UseCurrentSession).

Telethon .session + .json

The pair is how many tools store a Telethon account: a Telethon SQLiteSession file (database version 8, the layout Telethon 1.45 writes and reads) and a .json companion with the API profile and account fields. opentele2 writes both byte for byte the same in every ecosystem, over the SQLite bundled in the core.

  • telethon.session
  • telethon.json

The companion starts with the profile keys app_id, app_hash, device, sdk, app_version, system_lang_pack, system_lang_code, lang_pack and lang_code, followed by the account keys (twoFA, role, id, phone, username, is_premium, first_name, last_name, proxy, ipv6 and the rest) and session_file, the base name of the pair. Loading a pair reads the profile back from it, so a session keeps announcing the device it was saved with.

pair.py
import asyncio from opentele2.td import TDesktop from opentele2.tl import TelegramClient async def main(): session_file, json_file = await TDesktop("tdata").SaveSessionJson("telethon.session") client = await TelegramClient.FromSessionJson("telethon.session") # profile from the .json await client.connect() asyncio.run(main())

SaveSessionJson(path, api=None, fetch_user_info=False) on a TelegramClient saves a connected client the same way; with fetch_user_info=True it fills id, phone, username, the names and is_premium from get_me().

grammers SessionData

opentele2_grammers::session_data(account) gives a grammers 0.11 SessionData: the main DC as home DC, every production DC with its first IPv4 and IPv6 endpoints (the stored config’s when there is one), the account’s key on the main DC only, and the self user in peer_infos. The updates state is empty, so grammers fetches it on first use.

src/main.rs
use grammers_session::storages::MemorySession; use opentele2_core::tdata::TData; fn main() -> opentele2_core::Result<()> { let tdata = TData::load("tdata", b"", None)?; let account = tdata.main_account().expect("folder has an account"); let _session = MemorySession::from(opentele2_grammers::session_data(account)); Ok(()) }
Tip:

grammers’ SessionData and its DcOption print the raw auth key with Debug; do not log them.

Back to tdata

Every format goes back to a tdata folder. Two flags decide which session ends up in it:

  • Use the current session: the folder gets the client’s own auth key. Offline, and the same device keeps using it.
  • Create a new session: the existing client logs a new session in by QR code (with the 2FA password when the account has one) and the folder gets the new key, on the device of the API profile you pass. Needs the network.
back.py
import asyncio from opentele2.api import API, CreateNewSession, UseCurrentSession from opentele2.td import TDesktop from opentele2.tl import TelegramClient async def main(): # From a .session + .json pair; the folder gets the pair's own key. tdesk = await TDesktop.FromSessionJson("telethon.session") tdesk.SaveTData("tdata_from_pair") # From a client: a new session on a generated device. client = TelegramClient("telethon.session") tdesk = await client.ToTDesktop( CreateNewSession, api=API.TelegramDesktop.Generate("windows", "my-id"), password=None ) tdesk.SaveTData("tdata_new") asyncio.run(main())

TDesktop.FromTelethon(client, flag, api, password) is the same as client.ToTDesktop(...); UseCurrentSession stores the client’s own session.

See the guides for full conversion and QR login recipes.

Last updated on