DEV Community

tgscope
tgscope

Posted on

How we date Telegram channels from their numeric IDs

Telegram does not show when a channel was created. It does show a numeric ID, and that number turns out to carry a date, as long as you know how Telegram hands IDs out. We mapped 15 ID blocks used between 2015 and 2025 and built a lookup from them. Here is how the dating works, where it breaks, and what the May 2024 jump past 2³¹ means for your code.

If you only want the result, the Telegram channel creation date checker takes a username, a t.me link or a numeric ID and returns the period the channel was born in. The rest of this post is the method.

IDs were sequential, then they were not

Until late 2017 Telegram issued channel IDs in order, so a bigger ID meant a younger channel. Since November 2017 each new channel gets a random number from a block of 100 to 250 million IDs, and every few months Telegram moves on to a fresh block.

That changes what an ID can tell you. Inside a block the order is random, so the ID cannot give you a day. It can give you the block, and a block has an opening and a closing date.

Finding block edges without a creation date

Telegram does not expose creation dates, so we needed a proxy. The one we used: a channel cannot post before it exists. Take tens of thousands of channels with neighbouring IDs and look at their last posts. Many channels are abandoned within days of being created, so the earliest last posts in a group of neighbouring IDs sit close to the moment those IDs were first issued.

Plot ID against last-post date and you get a staircase. Each step is a block opening, and the area below it is empty. We used 247,850 channels whose posts we could date, and only 140 of them (0.06%) fall below the steps.

The procedure, in short:

  1. Split the ID range into 2-million bins.
  2. Look for places where the share of channels that went silent before a given date drops to zero from one bin to the next.
  3. Refine the edges at 0.5-million resolution.
  4. Define a block's opening date as the start of the first dense run of last posts, meaning at least three channels in a 30-day window for old blocks, or 0.15% of the block's dated channels for newer ones.

Dates are accurate to days for blocks opened since 2021 and rough before that.

how to read a channel's age from its ID

Checking that the order really is random

A correlation test shows the switch. Among channels that went silent while their block was still being filled, we compared the order of IDs with the order of last posts (Spearman rank correlation):

  • first block (Sep 2015 to Jan 2017): 0.78
  • 2017: 0.23
  • every block since Nov 2017: between -0.06 and 0.10

Near 1 means IDs were issued in order, near 0 means the ID order says nothing about age.

Another check: are blocks used one at a time, or several in parallel? If one block is active, the rate at which its channels go silent should drop when the next block opens, because the supply of short-lived new channels stops. It does. In the block that opened in May 2024, 24 of every 1,000 dated channels went silent in August 2024, 12 in September and 8 in October. One exception: from October 2018 to June 2021 Telegram drew from two blocks together, so an ID between 1.15B and 1.40B only tells you "somewhere between November 2017 and June 2021".

Sanity checks against known channels also land where they should. The Telegram News channel and the founder's personal channel are both in the first block, which opened on the day Telegram launched channels, September 22, 2015.

The 2³¹ problem

One block starts at exactly 2,147,483,648, which is 2³¹, one more than a signed 32-bit integer can hold. It opened on or shortly before May 16, 2024. Of 430 dated channels with IDs in the 3 million just below that number, 22 went silent before May 2024. Of the 353 just above, 1 did.

What breaks:

import ctypes

raw_id = 2_200_000_000
print(ctypes.c_int32(raw_id).value)
Enter fullscreen mode Exit fullscreen mode

That prints -2094967296. Code that reads raw channel IDs from the client API and stores them in a signed 32-bit column or variable overflows on every channel and supergroup created since May 2024. Typical places are a Postgres integer column, a Java int, or an old SQLite schema.

What does not break: the Bot API. It never exposed the raw value. It shows channels as -100 followed by the ID, a number that has always needed 64 bits, so most bots were unaffected. Both forms work as input to a lookup like ours; just keep the type bigint end to end.

Blocks are being used up faster

Blocks do not last a fixed time. The 200-million block that opened in October 2021 lasted 355 days. The 200-million blocks of 2025 lasted 89, 79 and 52 days. If Telegram retires a block when a fixed share of its numbers is taken, channels and supergroups were being created about seven times faster in August 2025 than in 2022. We cannot check that assumption from outside: a block could also be retired early or filled more thinly.

Here are a few of the blocks:

Block Opened Days in use
1.00B to 1.10B Sep 22, 2015 495
1.60B to 1.80B Oct 7, 2021 355
2^31 to 2.25B May 16, 2024 100
2.50B to 2.70B Feb 16, 2025 89
2.90B to 3.10B Aug 4, 2025 52

The full table with all 15 blocks is in our write-up, the Telegram channel ID clock.

What the date is and is not

The result is a period, not a day. It is the season a channel was born in, and it is only as good as the block table. Renamed channels are where this helps most: a channel's name and picture can be copied in a minute, an ID cannot. For example, 23 of 79 channels carrying a tap-to-earn game's name had IDs from blocks older than the game's own channel, so they were created earlier and renamed later.

A minimal lookup is a sorted list of block start IDs and a binary search:

import bisect

starts = [1_000_000_000, 1_100_000_000, 1_150_000_000, 1_500_000_000]
labels = ["Sep 2015", "Jan 2017", "Nov 2017", "Jun 2021"]

def block_of(channel_id: int) -> str:
    i = bisect.bisect_right(starts, channel_id) - 1
    return labels[max(i, 0)]
Enter fullscreen mode Exit fullscreen mode

Bear in mind the overlap between 1.15B-1.40B and 1.40B-1.50B, and strip the -100 prefix from Bot API IDs before looking anything up.

The method and the full block table are described in the ID clock research.

Top comments (0)