Telegram Web K speaks exclusively over MTProto v2, Telegram’s custom binary protocol. Every API call, file transfer, and server push travels through this stack. Understanding it is essential before making changes to network behavior, adding new API methods, or diagnosing connection problems. The implementation lives underDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/TelegramOrg/Telegram-web-k/llms.txt
Use this file to discover all available pages before exploring further.
src/lib/mtproto/ and is used from within the MTProto shared worker, keeping the main thread free of protocol work.
Networker — session, encryption, and scheduling
Networker — session, encryption, and scheduling
src/lib/mtproto/networker.ts is the core of the MTProto stack. Each MTPNetworker instance represents one encrypted session to one data center. The app creates separate networkers for client traffic (RPC calls), file downloads, and file uploads.Key responsibilities:- Session management — On construction,
updateSession()generates a random 8-bytesessionId. The previous session ID is kept for one round-trip to handle server responses that refer to the old session. - Message sequencing —
seqNois incremented for every content-related message. Non-content-related messages (acks, pings) use even sequence numbers. - Message scheduling —
scheduleRequest()batches pending messages. If more than 640 KB of data is pending, a container is sent immediately and the remainder is scheduled for the next tick. - Container packing — When multiple messages are pending,
generateContainerMessage()wraps them in anmsg_container(TL constructor0x73f1f8dc) to reduce round-trips. - Encryption —
getEncryptedOutput()implements MTProto v2 encryption: salt + session ID + message → AES-256-IGE with a derived key frommsg_key. Decryption inparseResponse()verifies themsg_keyafter decryption. - Connection monitoring —
sendPingDelayDisconnect()sends aping_delay_disconnectto ask the server to close the connection if no traffic arrives withindisconnectDelayseconds. This keeps NAT tables alive without a separate ping loop.
usingPfs is true, the networker uses a temporary authKey bound to the permanent key via auth.bindTempAuthKey. The binding is sent as the first API call of the session.HTTP long-polling — When the WebSocket transport is unavailable, sendLongPoll() sends http_wait with max_wait: 25000 ms, which causes the server to hold the connection open until a server-side update is ready.Authorizer — RSA and Diffie-Hellman key exchange
Authorizer — RSA and Diffie-Hellman key exchange
DC configurator — data center selection
DC configurator — data center selection
src/lib/mtproto/dcConfigurator.ts maps (dcId, connectionType, transportType) tuples to transport instances, reusing them across calls.DC addresses (production):| DC | IP address |
|---|---|
| 1 | 149.154.175.50 |
| 2 | 149.154.167.50 |
| 3 | 149.154.175.100 |
| 4 | 149.154.167.91 |
| 5 | 149.154.171.5 |
client (RPC), download, upload. Each gets its own transport instance unless reuse = false.WebSocket URLs are constructed as wss://{suffix}ws{dcId}{connectionSuffix}.web.telegram.org/apiws{testSuffix}. Client connections use no suffix; download/upload connections append -1 to the host and /apiws remains unchanged.HTTPS fallback — When WebSocket is unavailable, SSL subdomains are used: pluto, venus, aurora, vesta, flora for DC 1–5, hitting https://{subdomain}.web.telegram.org/apiw1.chosenServers[transportType][connectionType][dcId][]. Calling DcConfigurator.removeTransport() is the safe way to remove a dead connection from the pool without mutating the object while iterating.Transports — WebSocket and HTTP
Transports — WebSocket and HTTP
All transports live in
src/lib/mtproto/transports/ and implement MTTransport.WebSocket transport (tcpObfuscated.ts, websocket.ts)TcpObfuscated wraps the raw WebSocket with the TCP Obfuscation protocol. On connect it sends a 64-byte random header that tells the server which codec to use. Messages are XOR-obfuscated with a key derived from the header to prevent protocol fingerprinting by network intermediaries.Available codecs:abridged.ts— 1-byte or 4-byte length prefix, simplest format.intermediate.ts— 4-byte length prefix, no padding.padded.ts— Same as intermediate, plus random padding to defeat traffic analysis.
http.ts)Long-polling over HTTPS. Each send() call is a separate fetch() POST. The networker controls pacing via checkLongPoll() and sendLongPoll(), sending http_wait to hold the connection up to 25 seconds.Transport controller (controller.ts)transportController.pingTransports() is called once at startup (when VITE_MTPROTO_AUTO is enabled) to detect whether WebSocket is reachable. The result decides which transport the Authorizer uses for the initial key exchange.Safari proxy (socketProxied.ts)On Safari in a Web Worker, SocketProxied proxies WebSocket traffic through the main window because Safari workers cannot open WebSockets directly. The proxy uses postMessage on a dedicated MessageChannel.Time manager — clock synchronization
Time manager — clock synchronization
src/lib/mtproto/timeManager.ts keeps the client clock aligned with the Telegram server.MTProto message IDs encode the Unix timestamp in the upper 32 bits. If the client clock is more than 30 seconds off, the server rejects messages with msg_id_too_low / msg_id_too_high. The TimeManager corrects for this drift.generateId() produces a monotonically increasing message ID by combining the adjusted Unix time (in seconds) with milliseconds and a 16-bit random value packed into the low 32 bits. If two IDs would be identical, the counter is incremented by 4 instead.applyServerTime() is called during the DH exchange, when the server_DH_inner_data message contains the current server time. It is also called when the networker receives a bad_server_salt or bad_msg_notification with code 16/17.TL schema and layer version
TL schema and layer version
src/lib/mtproto/schema.ts contains the complete auto-generated TL (Type Language) schema as a single JSON object with two namespaces, MTProto and API. Each entry has a numeric id (CRC32 of the type signature), the constructor/method name, its parameters, and the return type.layer field is passed to the server as the first argument of invokeWithLayer on every new connection (networker.ts:wrapApiCall). Type-safe layer types are generated into src/layer.d.ts by the generate-mtproto-types script and are consumed throughout the codebase as import type {...} from '@layer'.Do not edit
schema.ts or layer.d.ts by hand. These files are generated. Regenerate them with the project’s generate-mtproto-types build task whenever the TL schema changes.tl_utils.ts provides TLSerialization and TLDeserialization, the read/write primitives that encode every message using the schema. gzipPacked support allows large requests to be compressed before sending.