· via dev.to (home feed)
Telegram's username field returns an empty string when a chat holds multiple handles
A dev.to post shows Telegram returning an empty username string for chats that hold several public handles, which breaks naive t.me link building; the fix is to use the active, editable handle.

A post on dev.to documents a Telegram API pitfall that can silently break handle-based linking: the username field can come back as an empty string, even on the account of the person who founded the platform.
The post's central example, captured as live output on 16 September 2026, is the durov account. The response carries a numeric id (1006503122) and username: "" — not null, not missing. Code that builds a link from whatever it finds, via something like chat.username or chat.id, produces t.me/1006503122, a URL that renders fine and resolves to nothing useful for a human reader.
Two shapes from one endpoint
According to the post, this is not a bug. Telegram allows a chat to hold several public handles at once, and when it does, the primary username field empties out and the handles move into a separate usernames array, where each entry carries its own flags.
For durov, that array holds six handles: durov, rove, paul, snow, feed and lean. All six are marked active, and exactly one — durov — is also marked editable. A single-handle chat shows the mirror-image shape: a lookup for the telegram channel returns username: "telegram" with usernames: null. Both responses come from the same route, and the post's blunt conclusion is that code handling only one of the two shapes is wrong half the time.
Choosing the canonical handle
The intuitive rule — grab the first active entry — is the wrong one, the post argues. Editable is the distinguishing bit: it marks the handle the owner controls, while the other entries are aliases that resolve but are not the channel's name. The numeric flags value encodes the same information (2 for active alone, 3 for active plus editable), but the booleans already expose it, so there is nothing to decode.
The recommended resolution order is: the active and editable entry first, then any active entry, then the plain username field, then give up:
python def best_handle(chat): names = chat.get("usernames") or [] for entry in names: if entry.get("active") and entry.get("editable"): return entry["username"] for entry in names: if entry.get("active"): return entry["username"] return chat.get("username") or None
Two details in that shape matter. The or [] guard exists because usernames is null rather than empty for single-handle chats, so iterating it directly raises an exception in the majority case. And the two passes must stay in that order — collapsing them into one loop returns an alias whenever an alias happens to come first.
The final None matters too. Falling back to the numeric id produces a link that looks valid and goes nowhere, which the post considers worse than no link at all.
Where it breaks in practice
The failure surfaces wherever stored data is turned back into a link: digest emails listing channels, dashboard rows, CSV exports opened weeks later. The trigger is a channel that renames itself while keeping its old handles alive — exactly the situation where username empties out and nobody notices until the links ship.
The suggested defence is cheap: for every chat you store, assert that the saved handle is non-empty and is not the id in string form. One line in a test, and a class of dead links never reaches anyone.
One caveat worth noting: the live examples in the post were produced through a third-party Telegram data API hosted on RapidAPI, a service the post's author appears to run, and the piece ends by pitching it. That does not change the response shapes it documents, but it explains the framing.
Why it matters
The empty-string-versus-null distinction is a classic integration trap, and Telegram's contract here is unusually sneaky: a populated concept — the channel's handle — is expressed through one of two shapes, and only one of them is the shape developers naively code against. Any product that stores Telegram handles for later linking, from newsletters to analytics tools, needs the three-step fallback or it will ship dead links in precisely the cases where nothing throws an error. The failure is silent by design: a renamed channel keeps working for its audience while the stored link quietly rots. The fix is a few lines, but only if you know the second shape exists.
- #telegram
- #api
- #edge-cases
- #rest-api