Telegram publishes every public channel twice: once inside the app, and once as a plain web page that any anonymous visitor can request. The second one is what makes a scraper possible without an account, and it is the whole basis of this Actor.
Why there is no login step
A public channel is served at t.me/s/<handle> to anyone who asks, with no cookie, no token and no phone number. That is not a loophole; it is how a channel gets shared outside Telegram at all. Everything below reads that page.
The practical consequence is reliability rather than principle. There is no session to expire halfway through a backfill and no account to be restricted, which is the failure mode of every scraper built on a signed-in client. The three routes into Telegram data compares this with the Bot API and MTProto.
Step 1 — pick the mode that matches what you know
| Mode | You already know | What it returns |
|---|---|---|
messages | the channels | Every post, newest or oldest first, up to your cap. |
search | the channels and a keyword | Only posts matching the keyword, filtered on Telegram's side. |
discover | a keyword and a niche | Matching posts across a curated catalogue of verified channels. |
channel-info | the channels | Metadata and the exact subscriber count, one row per channel. |
The choice is a cost decision more than a feature one. Reading a channel to find twenty posts about one topic cost 25 requests and 712 KB in testing; asking Telegram to filter cost 1 request and 24 KB for the same twenty — the measurement.
Step 2 — name the channels, four ways that all work
durov, @durov, t.me/durov and https://t.me/s/durov all mean the same channel and all resolve to the same internal id. Paste whichever form you happen to have.
In discover mode you name no channels at all: you pick a niche and the Actor searches the largest verified channels in it — what that catalogue reaches and what it does not.
Step 3 — set the caps before the run, not after
maxMessagesPerChannel is a hard cap and it defaults to 200, so a channel with 40,000 posts cannot quietly run up a bill. In discover mode the default drops to 20, because that mode opens many channels at once.
sinceDate is the other brake worth setting. Walking newest-first stops as soon as it passes the date, so posts older than your window are never fetched and never charged.
Step 4 — run it
{
"mode": "search",
"channels": ["durov", "https://t.me/s/tgbeta"],
"searchTerms": ["react", "typescript"],
"exactMatch": true,
"sinceDate": "2026-06-01",
"maxMessagesPerChannel": 500
}exactMatch is on by default and removes the posts Telegram matched by word stem rather than by your term — a search for hiring otherwise returns a post about hiring a cab. Discarded candidates are never charged.
Reading the output
Identity fields are at 100%: datetime, message id, url, channel username and telegram_channel_id. Post text is at 99.6% and never truncated. View counts arrive on 99.2% of rows, as a typed number and as the string Telegram displayed. The full field reference gives the rate for all of them, measured over 893 posts across 9 channels.
What a run costs
$0.001 per post, $0.001 per search result, $0.002 per channel record, $0.00001 to start. Five hundred posts is fifty cents. Three things are never charged: error and diagnostic rows, candidates discarded by exact match, and rows you already received if a run is interrupted and resumed.
Charging happens immediately after each row is delivered rather than in a batch at the end, so a run that dies halfway bills exactly what it delivered.
Four mistakes that waste a run
Reading a history when you wanted a topic. If you know the keyword, search mode does the filtering on Telegram's side and you stop paying for the posts you walk past.
Expecting attachments. Across 893 posts in 29 channels the anonymous preview rendered no documents, voice notes, audio, stickers, locations or round videos — the finding. Photo and video flags do ship.
Passing a group or an invite link. Only public channels with the web preview enabled can be read. Anything else returns a free diagnostic row naming which case it was, which is more useful than an empty result and costs nothing.
Planning around the average email rate. 3.0% overall spans 0% in news channels and 9.0% in job channels. Plan against your channel type.


