GLOSSARY

What is a Session String?

A session string is a portable, serialized MTProto authorization: the data centre it belongs to plus the 256-byte auth key that Telegram issued when the account logged in. Anyone holding it is logged into that Telegram account, with no phone number, no SMS code, and no two-factor password required.

Free forever plan · No credit card required · Cancel anytime

Quick definition

A session string is a portable, serialized MTProto authorization: the data centre it belongs to plus the 256-byte auth key that Telegram issued when the account logged in. Anyone holding it is logged into that Telegram account, with no phone number, no SMS code, and no two-factor password required.

In a single sentence: it is not a password hint, it is the logged-in device itself, in text form.

What it means

When a Telegram client logs in over MTProto, it does not receive a token in the way an OAuth client would. It performs a Diffie-Hellman key exchange with the server and both sides end up holding the same 2048-bit shared secret, 256 bytes, called the auth key. Every request from then on is encrypted with a key derived from it, and the server identifies the client by the auth_key_id, which is the low 64 bits of the SHA-1 of that key.

A session string is that auth key plus enough routing information to reconnect, packed into a single base64 blob you can copy and paste. It exists so a client can be stopped, moved, containerised or redeployed without going through the SMS login flow every time.

The exact packing is library-specific. Telethon's StringSession is a version byte, the data centre ID, the server IP and port, and the 256-byte auth key, base64-encoded, which lands at roughly 350 characters. Pyrogram packs a little more: the API ID, a test-mode flag, the user ID and a bot flag. WTelegramClient, the MTProto library behind Pinlyx, skips strings altogether and persists an encrypted session file. All three are the same idea with different envelopes.

The security model, stated plainly

A session string is a bearer credential of the strongest kind available on Telegram. Whoever holds it can:

  • Read every private chat, group and channel on that account.
  • Send messages as that person, including to their contacts.
  • Export the account's contact list and dialog history.
  • Terminate other sessions on the account.

And the point that surprises people: two-factor authentication does not help. The 2FA password guards the login flow. Once an auth key exists, no subsequent request consults the password again. Adding 2FA to an account whose session has already leaked changes nothing at all.

The only real control is revocation. Settings, Devices, terminate the session, and the server drops the auth key. Programmatically that is account.getAuthorizations to enumerate and account.resetAuthorization(hash) to kill one.

This is why a session string should never be pasted into a chat, a support ticket, a bug report, an environment file committed to git, or a log line. Any "free Telegram tool" that asks you to paste a session string is asking for permanent, unrevoked access to the account, and the request is almost never necessary: legitimate tools run the login flow themselves.

AUTH_KEY_DUPLICATED: the deployment trap

The single most common way to destroy a working session in production has nothing to do with attackers.

Telegram treats one auth key being used from two different places simultaneously as evidence of key theft, and it responds by invalidating the key. The error is AUTH_KEY_DUPLICATED, status 406, and it is permanent. There is no back-off that recovers from it; the account has to log in again from scratch, which for a phone-number account means another SMS code.

The realistic causes are all ordinary operations mistakes:

  • A rolling deploy where the new container connects before the old one has finished shutting down.
  • Two replicas of the same worker scheduled onto different nodes, both reading the same session from shared storage.
  • A developer running the same session locally to debug while it is live on the server.
  • A cron job and a long-running daemon both instantiating a client from the same file.

The structural fix is to make the session single-owner: one process holds it, and everything else talks to that process. If you must share, take a lock. Draining the old process fully before starting the new one is not optional with MTProto sessions in the way it can be with stateless HTTP workers.

Sessions carry state, not just keys

A session is often described as "just the auth key", and that description costs teams a lot of unnecessary traffic.

A complete session also holds the update state: the pts, qts, date and seq counters that mark how far the client has consumed Telegram's event stream. Restore only the key and the client has to call updates.getState and refill from a cold start, which produces a burst of catch-up requests on every restart.

Most session implementations also hold a peer cache, the mapping of IDs to access hashes that the account has resolved. Throwing that away means re-resolving every contact, and mass re-resolution is one of the reliable ways to earn a flood wait. In other words, an aggressive "just regenerate the session" habit is not neutral: it costs rate limit budget every time.

Data centres and exported authorizations

An auth key is bound to one Telegram data centre. Telegram runs several, and an account is homed to whichever one it registered against.

That matters when a file lives elsewhere. Media in a chat may be stored in a different data centre from the one your session is authorised against, and downloading it requires a separate authorization for that data centre, obtained with auth.exportAuthorization on the home data centre and auth.importAuthorization on the target. Libraries usually handle this transparently, which is why it only becomes visible when you write your own transport and downloads mysteriously fail with AUTH_KEY_UNREGISTERED against a data centre you never logged into.

Why it matters

For anything running Telegram at scale, the session store is the crown jewels. A CRM with 40 connected accounts is holding 40 credentials, each of which grants total access to a real person's Telegram, including their private conversations that have nothing to do with work.

That places concrete obligations on the software: encryption at rest with a key held outside the database, no session material in logs or error reports, no session material in API responses, and a revocation path the account owner can trigger themselves without asking support. It also places an obligation on the operator to treat "the session died" as an event worth investigating rather than an error to auto-retry, because the difference between a rolling deploy bug and an actual compromise is visible in exactly one place: the error code.

Common mistakes

  • Storing session strings in environment variables. They end up in process listings, crash dumps, and CI logs. Use an encrypted field in the database or a secrets manager.
  • Retrying AUTH_KEY_UNREGISTERED. The key is gone. Retrying just adds failed handshakes to the account's record.
  • Running one session in two processes. This is not a race condition to be managed, it is a session-destroying event.
  • Regenerating sessions casually. Every fresh session throws away the update state and the peer cache and pays for both again.
  • Assuming 2FA protects an existing session. It does not. Only revocation does.
  • Backing up session files to unencrypted object storage. A backup bucket with a session file in it is a backup bucket with a logged-in Telegram account in it.

Related concepts

  • MTProto: the protocol whose handshake produces the auth key in the first place.
  • Userbot: the pattern that makes session strings necessary, and risky.
  • Access hash: the per-account peer authorizations that live alongside the session.
  • Telegram Bot API: the alternative where the credential is a revocable bot token instead.
  • TDLib: keeps the same material in a local encrypted database directory rather than a string.
  • Flood wait: what unnecessary session churn costs you in rate limit budget.

How Pinlyx handles it

Pinlyx never asks a customer to paste a session string. Accounts are connected through the normal Telegram login flow inside the panel, the resulting session is persisted encrypted at rest, and the encryption key lives outside the database. Each session has exactly one owning worker process, so a rolling deploy drains before it starts and AUTH_KEY_DUPLICATED stays theoretical. Session errors are classified rather than retried: a 406 pages the operator, a 401 marks the account disconnected and prompts the owner to re-link it, and a ban stops every queued send for that number immediately.

Decision table · session errors

Five session errors, and what each one actually requires.

None of these are retryable. Every one of them needs a different response, and treating them uniformly is how accounts get lost.

AUTH_KEY_UNREGISTERED401

The server does not recognise this auth key. The session was terminated from another device, or the string was truncated in storage.

Do this: Do not retry. Mark the account as logged out and require a fresh login.

AUTH_KEY_DUPLICATED406

The same auth key was used from two places at once. Telegram invalidates the key on the spot as an anti-theft measure.

Do this: The session is dead permanently. Re-authenticate, then fix whatever ran two clients on one session.

SESSION_REVOKED401

A human terminated this session from Settings, Devices, or the account password was reset.

Do this: Re-authenticate. If it was not you, treat the session string as leaked and rotate everything it touched.

SESSION_PASSWORD_NEEDED401

Login reached the two-factor step. This appears during authentication, not on an established session.

Do this: Complete the SRP check with account.checkPassword before continuing.

USER_DEACTIVATED_BAN401

The account itself was banned. The session is irrelevant now.

Do this: Stop all sends from this number and review what the account was doing before the ban.

Cheat sheet · what is inside

Anatomy of a string session.

The Telethon layout, which is the most minimal of the common formats. Never print a real one.

"1" + base64url( struct.pack(">B4sH256s", dc_id, ip, port, auth_key) )
 |            |     |    |    |     |
 |            |     |    |    |     +-- 256 bytes: the shared secret
 |            |     |    |    +-------- 2 bytes:   port
 |            |     |    +------------- 4 bytes:   server IPv4
 |            |     +------------------ 1 byte:    data centre id
 |            +------------------------ 263 bytes total, ~350 chars base64
 +------------------------------------- format version

// NOT in the string: phone number, 2FA password, username.
// ALSO NOT in the string, but part of a complete session:
//   pts / qts / date / seq   update-stream cursors
//   peer cache              id -> access_hash, per account

// The failure that ends a session permanently
{
  "_": "rpc_error",
  "error_code": 406,
  "error_message": "AUTH_KEY_DUPLICATED"
}
// Cause: two processes, one auth key, at the same moment.
// Recovery: none. Log in again.

256 bytes of secret

The auth key is 2048 bits from a Diffie-Hellman exchange. The server indexes it by the low 64 bits of its SHA-1.

File or string, same risk

A session file holds the identical key. Only encryption at rest changes the exposure.

No expiry, no scope

Sessions do not time out and cannot be made read-only. Revocation is the only control.

Handling checklist

Six rules for storing Telegram sessions in production.

  • Encrypt at rest, with the key held somewhere other than the database that holds the ciphertext.
  • One process owns one session. Drain before deploy, never overlap.
  • Persist the update state and peer cache with the session, not separately.
  • Never log, never return over an API, never place in an environment variable.
  • Classify session errors instead of retrying them. 406 is permanent, 401 needs a re-login.
  • Give the account owner a self-service disconnect that also terminates the session on Telegram.
Watch out for

"Paste your session string here" is the Telegram phishing pattern.

A legitimate tool runs the login flow: it asks for the phone number, sends you to Telegram for the code, and builds its own session. A tool that asks you to paste an existing session string is asking for something it does not need, and receiving something it can never be made to give back. There is no read-only session, no scoped session, and no expiry.

If you have already pasted one somewhere you regret: open Telegram, go to Settings then Devices, and terminate every session you do not recognise. That is the only action that actually revokes access.

Session strings: FAQ

The questions that matter before you put a Telegram session anywhere near production.

No, and this is the most dangerous misunderstanding about session strings. Two-factor authentication is a gate on the login flow. Once a login has completed and an auth key exists, the password is no longer consulted on any subsequent request. A stolen session string walks straight past 2FA. The only defence is revocation: terminate the session from Settings, Devices, which invalidates the auth key server-side.
The essentials are the data centre ID, the server address and port for that data centre, and the 256-byte auth key that the Diffie-Hellman handshake produced at login. Different libraries add a little more: Pyrogram packs the API ID, a test-mode flag, the user ID and a bot flag alongside it. Telethon keeps it minimal, which is why a Telethon string session is roughly 350 characters of base64. What is never inside is the phone number or the 2FA password.
You can try, and Telegram will kill the session. Using one auth key from two places at once triggers AUTH_KEY_DUPLICATED with status 406, and the key is invalidated permanently rather than temporarily. This bites during deployments: an old container that has not shut down yet plus a new one starting up is exactly two clients on one key. Drain the old process before starting the new one, or key your session storage per replica.
Because a session holds more than the auth key. It also holds the update state: the pts, qts, date and seq counters that tell Telegram how far along the event stream your client already is. Restoring only the auth key and dropping the state means the client calls updates.getState and starts from scratch, which produces a burst of catch-up traffic and, at scale, flood waits. Persist the update state with the session, not separately.
From any Telegram client: Settings, then Devices, then terminate the session you do not recognise. Programmatically it is account.getAuthorizations to list them and account.resetAuthorization with the returned hash to kill one. Revocation is immediate and irreversible. Terminating the current session logs that client out too, which is the correct behaviour when you suspect a leak.
Only in the sense that it is harder to paste into a chat window by accident. A session file contains the same auth key, so the security question is identical: is it encrypted at rest, is the key held somewhere other than next to the file, and is it excluded from backups, logs and version control. WTelegramClient, which is what Pinlyx runs on, persists to an encrypted session file with the encryption key supplied through configuration rather than stored beside it.
Ready to ship

Connect Telegram accounts without handing over the keys.

Pinlyx runs the real login flow, encrypts every session at rest, and gives account owners a one-click disconnect.

Free forever plan · GDPR-ready · No credit card required

We value your privacy

We use cookies to improve our site, analyze traffic, and personalize ads. You can accept all, reject non-essential, or customize your choices. Read our Cookie Policy.