A Telegram channel's @username is editable by its owner, and changing it silently splits any dataset keyed on the handle into two unrelated histories — the old rows under the old name, the new rows under the new one, with nothing joining them. `telegram_channel_id` is Telegram's internal identifier, it does not change when the handle does, and this Actor puts it on 100% of rows. Key on the id and store the handle as an attribute, which is the same reason a database keys on a surrogate id rather than on an email address.
Key points
The @username is owner-editable, so it is an attribute rather than an identifier.
`telegram_channel_id` is Telegram's internal id and is on 100% of rows in both post and channel records.
A rename does not produce an error anywhere: the old rows keep resolving and the new rows arrive under a new key, so the split is silent.
The handle should still be stored, because it is what a human recognises and what a URL contains.
The same rule applies to the four accepted input forms — `durov`, `@durov`, `t.me/durov` and the full preview URL all resolve to one channel and one id.
This is a short article about one column, because that column is the difference between a dataset that survives a year and one that quietly becomes two.
How a rename breaks a dataset
A channel owner can change the @username. Nothing announces it. The old handle stops resolving, the channel carries on under the new one, and your next run writes rows under a key that has never appeared before.
Nothing fails. No error is raised, because from the scraper's point of view a new channel was read successfully. The history simply splits in two, and it is usually discovered months later by somebody wondering why a series has a cliff in it.
The identifier that does not move
telegram_channel_id is Telegram's internal identifier for the channel. It does not change when the handle does, and it is on 100% of rows in both post and channel records. Key on it.
Store the handle anyway
The handle is what appears in a URL, what a person recognises, and what somebody will paste into your tool next week. Store it as an attribute of the channel rather than as its key. This is the ordinary rule — key on the identifier, display the label — and Telegram is simply a case where the label is unusually easy to change.
Four input forms, one channel
durov, @durov, t.me/durov and https://t.me/s/durov all resolve to the same channel and the same id, so it does not matter which form your source data happens to use. The normalisation happens before the request, which is also why passing a mixed list does not produce duplicate rows.
Frequently asked questions
▸Can a Telegram channel change its @username?
Yes — it is set by the channel owner and can be changed. The old handle stops resolving and the channel continues under the new one, which is why a dataset keyed on the handle ends up with two disconnected histories and no error to warn you.
▸Is the channel id stable?
It is Telegram's internal identifier for the channel and it survives a rename, which is exactly the property a key needs. It is present on 100% of rows.
▸Do I still need the handle?
Yes, as an attribute. It is what appears in URLs and what a person recognises. The rule is the ordinary one: key on the identifier, display the label.
Sources
Every URL below was requested and returned a page on the date shown.
The Bot API cannot read a channel it is not in. MTProto needs a phone number and an api_id. The public web preview needs neither, and it is what a channel publishes to the open web.
A walkthrough of reading public Telegram channels anonymously: the four modes, when search beats reading a history, and what the anonymous preview does and does not render.
Documents, voice notes, audio, stickers, locations and round videos never appeared once in the anonymous preview. Fields that would always be false were cut rather than shipped.