Telegram Channel Scraper - Posts, Views & Exact Subscribers avatar

Telegram Channel Scraper - Posts, Views & Exact Subscribers

Pricing

from $1.83 / 1,000 post returneds

Go to Apify Store
Telegram Channel Scraper - Posts, Views & Exact Subscribers

Telegram Channel Scraper - Posts, Views & Exact Subscribers

For OSINT, crypto and market research and channel vetting: posts, views, reactions and forwards from any public Telegram channel, plus the exact subscriber count from the profile page. On one 10.9M channel the rounded preview hid 43,313 people. Median views, ERR and cadence are measured.

Pricing

from $1.83 / 1,000 post returneds

Rating

0.0

(0)

Developer

NeverEmpty

NeverEmpty

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

17 hours ago

Last modified

Share

Telegram Channel Scraper - posts, views and the exact subscriber count

For people buying or selling channel advertising, media monitoring and ranking channels: any public Telegram channel read from the pages Telegram serves without a login, returned as two kinds of row — one per post, and one per channel.

The channel row carries the exact subscriber count, which is what the other Telegram scrapers do not give you. Telegram's public preview page shows a rounded figure — Bloomberg's channel reads 172K there — while the channel's own profile page publishes the exact count, 171,899. This Actor reads both, returns both, and puts the difference in its own column. On a large channel the gap is wide enough to matter: Pavel Durov's channel shows 10.9M on the preview and 10,856,687 on the profile — a difference of 43,313 people that a rounded figure hides for weeks at a time.

On top of that, the channel row carries statistics measured from the posts the run actually read — median, mean, highest and lowest views, the top post, median reactions, views per subscriber, posts per day over the window read, the share of posts carrying a photo, a video, a link preview or a forward, and the busiest posting hour in UTC. These are the numbers an advertising buyer asks for, and they are measured here rather than estimated.

A name that is not a public channel is reported as one. Telegram answers the preview URL with a 302 for a bot, a personal account, a group and a channel with no public preview, and answers "no more posts" with a 200 page rather than an error — both are read correctly instead of being passed on as an empty result.

Measured from Apify on 2026-09-07: t.me answered with the full page on 3 of 3 direct requests (145 KB, 217–449 ms), and t.me/robots.txt is a 404 — nothing is declared as disallowed. No API key, no login, no proxy needed. Export as JSON, CSV or Excel.

What one run gives you

Post rows (rowType: "message")

ColumnWhat it is
channel, messageId, postUrlthe channel and the post, with its permanent t.me link
publishedAtthe post time, exactly as Telegram publishes it (UTC, with offset)
text, textLengththe post text with its line breaks kept
views, viewsText, viewsAreRoundedthe view count as a number, the text Telegram printed, and a flag
reactionsTotal, reactions[]each reaction with its emoji or custom emoji id, its count, and whether it is a paid (Stars) reaction
isForwarded, forwardedFromChannel, forwardedFromUrl, forwardedFromNamewhere a forwarded post came from, and the link to the original
authorSignature, isEditedthe signature on signed posts, and whether the post was edited
hasPhoto, hasVideo, hasLinkPreview, linkPreviewUrl/Title/Sitethe attachments this Actor has measured on the public preview
links[], mentions[], hashtags[]outgoing links, @channel mentions and hashtags, told apart

Channel rows (rowType: "channel", one per channel, on by default)

channelTitle, description, verified, subscribers (exact), subscribersDisplay (rounded), subscribersDisplayValue, subscribersDisplayDiff, photosDisplay, videosDisplay, linksDisplay, messagesRead, oldestPostAt, newestPostAt, windowDays, postsPerDay, viewsMedian, viewsMean, viewsMax, viewsMin, topPostUrl, topPostViews, viewsPerSubscriberPct, reactionsMedian, forwardedPct, withPhotoPct, withVideoPct, withLinkPreviewPct, busiestHourUtc.

What is measured, and what is not

  • View counts are rounded by Telegram, to three significant figures (24.2M, 53.1K). There is no exact figure published anywhere on the public pages, so this Actor does not pretend to have one: every post row carries viewsAreRounded, and every channel row carries viewsAreApproximate. The rounding is at most about 0.5% of the value. Reaction counts are printed the same way.
  • The subscriber count on the profile page is not rounded, and that is the one in subscribers. If Telegram ever answers with a rounded figure there, the column is left empty rather than filled with a rounded number labelled exact.
  • Telegram serves 20 posts per page. Reading more pages costs more requests, not more accuracy.
  • Photos, videos and link previews are the attachment types measured on the public preview pages. Other kinds are not claimed either way rather than guessed at.
  • Invite links (t.me/+..., t.me/joinchat/...) and t.me/c/... are private entrances. They are rejected rather than read, and no login or account is ever used.
  • Post text is returned as published, with one exception: email addresses, numbers written with an international + prefix, and numbers directly after phone/tel/call/whatsapp/viber are replaced with [email removed] / [phone removed]. Plain long numbers - block heights, transaction amounts, order ids - are left alone, and textLength is the length of what you receive.
  • postsPerDay is measured over windowDays, the span between the oldest and newest post the run read, using the gaps between posts. It needs at least two posts; with one it is empty rather than guessed. busiestHourUtc is empty when two hours tie rather than picking the earlier one.
  • subscribers is filled only when Telegram labels the figure "subscribers". A group that reports "members", or a page that reports "online", leaves it empty rather than passing off a different number as a subscriber count.
  • A name nobody has taken and a name that exists without a public preview are two different answers, and this Actor tells them apart by asking for the profile page as well - one extra request, so a typo comes back as a typo rather than as "this channel is private".
  • One channel can hold several usernames. t.me/techmeme and t.me/arstechnica both lead to the same channel, and the preview page shows whichever name you asked for - so a list containing both looks like two channels. Every row carries channel (the name Telegram puts on the posts), inputChannel (what you asked for) and channelMatchesInput, and a second name for a channel already read in the run comes back as a free duplicate-channel row instead of the same posts charged twice.

Monitoring: never pay for the same post twice

Turn monitoringMode on and the Actor remembers the newest post id per channel and, on the next run, asks Telegram only for posts published after it. Adding a channel to your list does not re-charge the ones already being watched, because nothing about the list is part of what is remembered.

Posts that could not be delivered - because the run hit its charge limit - are not marked as returned, so the next run delivers them instead of skipping them.

On a run where a channel has posted nothing new, that channel produces no rows at all - not even its channel-statistics row - and a single free no-change row says so. Telegram answers such a request with a 200 page carrying "No posts found" rather than an error, and this Actor reads that as "nothing new", never as "this channel has no posts".

Monitoring adds a flat access fee of $5, charged once per calendar month (UTC), on the first monitoring run of that month that manages to read at least one channel - a run where every name was mistyped costs nothing. That fee is what pays for the days when the channel posted nothing: those runs return no rows and cost nothing else. Runs with monitoring off never trigger it.

Two things worth knowing before you schedule it:

  • What is remembered per channel is the newest post already processed, and that includes posts your filters dropped. A task with keywords and a task without them share that memory, so a post filtered out by one will not be delivered by the other later.
  • Two runs watching the same channel at the same moment both see the same "last post" and will both return it. Runs watching different channels do not interfere - the memory is stored per channel, not as one shared blob.

Rows that are never charged

When there is nothing to sell, you get a row that says why, and it is free:

statusWhat happened
no-such-channelnobody has taken the name. Telegram answers a free name with its generic download page - no title, no subscriber count - instead of a profile
not-a-public-channelthe name exists, but has no public post preview: Telegram answers the preview URL with a 302 back to the plain profile. It does that for a bot, a personal account, a group, and a channel whose owner turned the preview off, so this row does not claim which
no-resultsthe channel page loaded and Telegram published no posts on it
blockedTelegram answered with a bot check instead of the page
unreadablethe page could not be read; nothing is guessed
no-changemonitoring mode, and nothing has been posted since the last run
no-matchposts were read and none matched your filters
duplicate-channelthe name is another username for a channel already read in this run, so its posts are not returned twice
budget-reachedthe run hit the maximum total charge you set for it and stopped; the row says how many posts were left behind

A no-such-channel row is never dressed up as an empty channel, and an empty channel is never dressed up as an error.

Input

FieldWhat it does
channelsthe public channels to read, as @durov, durov, https://t.me/durov or a link to a single post
maxMessagesPerChannelhow many of the most recent posts to read per channel (Telegram serves 20 per page)
maxMessagesa cap across all channels together, applied after the filters
includeChannelStatsadd the one channel row per channel with the exact subscriber count and the measured statistics
monitoringModereturn only posts you have not been given before
resetMonitoringStateforget the remembered post ids and start the history over
postedWithinDays, minViews, onlyWithMedia, onlyWithLinks, excludeForwardedfilters on the posts
keywords, keywordMatch, excludeKeywordskeyword filters
useProxyswitch to a residential proxy and retry if Telegram ever answers with a bot check

Filters

keywords / keywordMatch / excludeKeywords (searched in the text, channel title, forwarded source, link preview title and hashtags), postedWithinDays, minViews, onlyWithMedia, onlyWithLinks, excludeForwarded. Posts whose view count or timestamp cannot be read are kept, not dropped - a filter never silently empties a result because one column was missing.

Connection

Measured from Apify on 2026-09-07: t.me answered with the full page on 3 of 3 direct requests (145 KB, 217-449 ms), and t.me/robots.txt is a 404 - nothing is declared as disallowed. So no proxy is used by default. Turn useProxy on to have the run retry through a proxy if Telegram ever answers with a bot check; a residential proxy is used when your account has one, and a datacenter proxy otherwise.

A request for posts newer than the newest one comes back as a 200 page of 18,684 bytes whose body is "No posts found" rather than an error - which is why monitoring reports no-change there instead of an empty channel.