[1.76.2] - 2026-08-12
- FIXED: Photos, videos and stickers stopped loading in 1.76.0 and 1.76.1 - data center 203, the one Telegram serves media from, was addressed as
kws2on the shared Cloudflare pool and on a custom WebSocket domain. Those names are separate records with separate origins:kws2is data center 2 at149.154.167.51,kws203is91.105.192.100. Every media session therefore established, in about 150 ms, against a data center that could not serve it, and because the connection succeeded the direct route behind it was never tried.kws203was said to be a name that exists nowhere, which is true only of Telegram's own edge, and data center 203 was already kept away from that edge on other grounds. - FIXED: Two of Telegram's addresses were relayed to the wrong data center -
149.154.167.43and149.154.167.92answer as data center 4, but they sit inside the block b4 reads as data center 2 and neither is named in Telegram's own address list, so both were addressed askws2and Cloudflare carried the session to data center 2. Same shape as the data center 203 fault, and it was already shipping. - FIXED: Most of Telegram's addresses had no data center at all, so those connections gave up the whole route list - b4 knew five address blocks, and Telegram answers from far more: nearly half the intercepted connections in a capture from a censored network could not be placed, and an unplaced connection gets a Cloudflare Worker or a direct attempt and nothing else - no Telegram edge, no shared pool. Data center 5 (
91.108.56.0/24,149.154.170.0/24,149.154.171.0/24) and data center 1 (149.154.175.48/28) are recognised now.149.154.175.0/24deliberately is not: data centers 1 and 3 share it, and half those sessions would be carried to the wrong one. - CHANGED: The block b4 reads as data center 4 was four times wider than anything Telegram answers on -
91.108.4.0/22covered 768 addresses that reply to nothing; narrowed to91.108.4.0/24. - CHANGED: A Cloudflare Worker of your own is now the last WebSocket route tried, not the first - Cloudflare reclaims a stateless worker part-way through a session, and it does so long after the handshake, so every connection test passed it and every video failed. Measured from a censored network against data center 1: a worker answered 8 rounds and went mute at 8.7 seconds, a domain from the shared pool answered 100 rounds over two minutes on the same machine. Ahead of the pool the worker won the dial and took the session with it, because the route list only moves on when a dial fails, and this one succeeds.
- FIXED: A route that answered nothing at all was handed the next connection anyway - a relay was only ranked down when it went quiet mid-session with a request outstanding. A worker reclaimed by Cloudflare does not go quiet, it stops existing: the client gives up first, and the whole session shows as a dial that worked and carried nothing. A route that took a request and returned zero bytes is now ranked down like a mute one.
- CHANGED: The Cloudflare Worker script in the documentation keeps its relay alive longer - the loop carrying data back from Telegram was a promise nobody awaited, which Cloudflare may cancel the moment the handler returns, and this handler returns as soon as the WebSocket is accepted. It is handed to
ctx.waitUntil()now, and the three socket promises that nobody watches get a no-op handler so a reclaimed session stops filling the worker log with unhandled rejections. Set the worker's compatibility date to2026-04-07or later as well. This is not a full remedy -waitUntilis documented to extend a request by about thirty seconds - which is why the worker now sits behind the shared pool. - FIXED:
tgprobenever tested the shared Cloudflare pool - it built its configuration from an empty struct and then applied defaults, and applying defaults deliberately leaves booleans alone, so every on/off setting read as off. It builds its configuration the way b4 itself does now. - CHANGED: The Cloudflare Worker is asked for a data center address only, never a port - a Worker that opens 443 whatever it was asked for is the right one: Telegram serves the same endpoint on 80, 443 and 5222, 443 is the port every data center listens on, and data center 203 does not answer on 5222 at all, so passing the port on turned a working media connection into a dead one. The script in the Telegram documentation is again the tg-ws-proxy script unchanged, and a Worker deployed from either page needs nothing done to it.
What's Changed
- feat: implement self-dial mark and relay stall reporting by @DanielLavrushin in #300
Full Changelog: v1.76.0...v1.76.2rc3