Telegram Channel Scraper: Public Posts, Views & Media
Pricing
from $0.30 / 1,000 posts
Telegram Channel Scraper: Public Posts, Views & Media
Scrape public Telegram channels via the t.me web preview: one row per post with text, date, views, media, link previews, polls, reactions, hashtags and links, plus channel info. No login, no API key, no browser. $0.30 per 1,000 posts.
Pricing
from $0.30 / 1,000 posts
Rating
0.0
(0)
Developer
subimpact
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
a day ago
Last modified
Categories
Share
Read public Telegram channels through their t.me/s/<channel> web preview and get clean rows back: post text,
publication time, view counts, media type, photo and video thumbnail URLs, document names, link previews, polls,
reactions, hashtags, mentions and outgoing links. One channel-info row per channel (title, description, subscribers,
media counters, avatar, verified flag), then one row per post. No login, no API key, no browser, no Telegram app.
Pay only for what you get: $0.30 per 1,000 posts and $1.00 per 1,000 channel-info rows. A default run over one channel (50 posts plus its info row) costs about $0.016, plus Apify platform usage.
What you get
- One row per post, newest first:
postId,postUrl,postedAt,text(line breaks kept, HTML stripped),viewsas an integer plus theviewsTextTelegram printed ("5.84M" becomes5840000). - Media without downloading it:
mediaType(photo, video, document, audio, voice, sticker, poll, mixed, none),photoUrls,videoThumbUrls,videoDurationSec,documentNames. - Rich post details:
linkPreview,pollwith option percentages,reactions,hashtags,mentions,links,replyToPostId,isForwardedplusforwardedFrom,authorSignature,isEdited. - Channel info row:
description,subscribers,photosCount,videosCount,linksCount,filesCount,avatarUrl,isVerified,channelUrl. - Filters that save money:
maxPostsPerChannel,maxTotalPosts,postedAfter,postedBefore, and Telegram's own in-channel search viasearchQuery. - Delta mode (
onlyNew) for schedules: each run delivers only posts newer than the highest post id already delivered for that channel. The cursor lives in a key-value store in your own Apify account. - Single post URLs: give
https://t.me/durov/531and you get that post only.
Every run also writes a RUN_SUMMARY record to the run's key-value store: per-channel status, rows, requests and any
problem, so a schedule can be checked without reading logs.
Quick start
Input that works exactly as written:
{"channels": ["durov", "telegram"],"maxPostsPerChannel": 50,"includeChannelInfo": true}
Channel entries may be written as durov, @durov, t.me/durov, https://t.me/durov, https://t.me/s/durov, or a
single post such as https://t.me/durov/531.
A monitoring run for one channel, new posts only:
{"channels": ["telegram"],"onlyNew": true,"includeChannelInfo": false,"maxPostsPerChannel": 100}
Search inside a channel and keep one week of posts:
{"channels": ["durov"],"searchQuery": "Telegram","postedAfter": "2026-10-18","includeChannelInfo": false}
Output example
A post row from t.me/s/durov (CDN image URLs shortened here for readability):
{"recordType": "post","channel": "durov","channelTitle": "Pavel Durov","postId": 531,"postUrl": "https://t.me/durov/531","postedAt": "2026-07-16T20:45:25.000Z","isEdited": false,"editedAt": null,"text": "🩵 Telegram now has a Rich Text Editor.\n\nIt supports tables, headings, inline media, lists, AI content, formulas, and more.\n\n😈 Messaging apps will never be the same!","views": 5840000,"viewsText": "5.84M","authorSignature": "Pavel Durov","isForwarded": false,"forwardedFrom": null,"replyToPostId": null,"mediaType": "video","photoUrls": [],"videoThumbUrls": ["https://cdn4.telesco.pe/file/JcEMS9Bq90aZQ4T4hTjXv8G...jpg"],"videoDurationSec": null,"documentNames": [],"linkPreview": null,"poll": null,"reactions": [{ "emoji": "stars", "count": 6300 },{ "emoji": "emoji-id:5265077361648368841", "count": 54600 }],"hashtags": [],"mentions": [],"links": [],"scrapedAt": "2026-10-25T07:49:34.378Z"}
The matching channel row:
{"recordType": "channel","channel": "durov","channelTitle": "Pavel Durov","description": "Founder of Telegram.","subscribers": 10300000,"photosCount": 102,"videosCount": 47,"linksCount": 200,"filesCount": null,"avatarUrl": "https://cdn4.telesco.pe/file/enJjZA2XzVbFAjeTOqFmqCmKVB5C...jpg","isVerified": true,"channelUrl": "https://t.me/durov","scrapedAt": "2026-10-25T07:49:34.378Z"}
A poll row reads like this (mediaType is poll, question and percentages as Telegram shows them):
{"recordType": "post","channel": "polldemo","postId": 101,"postedAt": "2026-10-20T09:15:00.000Z","views": 18400,"mediaType": "poll","poll": {"question": "Which Telegram app do you use most?","options": [{ "text": "Mobile", "percent": 52 },{ "text": "Desktop", "percent": 31 },{ "text": "Web", "percent": 17 }]}}
Pricing
Pay per event, charged only after the row is in the dataset:
| Event | Price | Charged when |
|---|---|---|
post | $0.0003 per post ($0.30 per 1,000) | a post row was pushed |
channel-info | $0.001 per channel ($1.00 per 1,000) | a channel-info row was pushed |
apify-actor-start | $0.00005 per run | the run starts (platform event) |
Buyer pays Apify platform usage separately. Empty channels, search results with no matches, preview-disabled channels
and failed requests cost nothing: no row, no charge. Turn includeChannelInfo off and you pay only for posts.
Typical costs: 500 posts from one channel with channel info = 500 x $0.0003 + $0.001 = $0.151. A scheduled hourly
onlyNew run that finds 3 posts = $0.0009.
How this compares
Free-plan list prices on the Apify Store, checked 25 October 2026. Competitor platform usage is charged on top by their listings; check the individual listing, prices change.
| Actor | Start fee | Per 1,000 messages | Per 1,000 channel infos | Users on the listing |
|---|---|---|---|---|
| telegram-channel-scraper (this actor) | $0.00005 platform start | $0.30 | $1.00 | new |
| automation-lab/telegram-scraper | $0.005 | $1.00 | $2.00 | 189 in 30 days |
| khadinakbar/telegram-channel-scraper | $0.003 | $2.00 | not listed | 61 |
| tugelbay/telegram-posts-scraper | none listed | $2.00 | not listed | 27 |
What is different here beyond the price:
- Rows as they are ready: every post row is pushed and charged the moment it is parsed, so a run that hits its time limit still delivers everything it collected.
- Caps that hold:
maxPostsPerChannelplus a globalmaxTotalPostsstop a run before it surprises you. - Delta mode built in:
onlyNewkeeps a per-channel post-id cursor in your own key-value store, and never moves the cursor backwards after a failed page. - Per-channel status record:
RUN_SUMMARYsays which channel was ok, empty, not found, or had its web preview disabled, and how many requests it took.
Limits and honest notes
- Public channels with the web preview enabled only. Private groups, private channels (
t.me/c/...), invite links (t.me/+...) and channels whose owner disabled the preview cannot be read. They come back aspreview_unavailableornot_foundinRUN_SUMMARY, with no row and no charge. Telegram groups show no web preview at all. - Telegram serves 20 posts per page. The actor pages with
?before=<post id>and pauses 300 to 800 ms between pages of the same channel.maxPostsPerChannelis a cap, not a promise: a channel with fewer posts returns fewer. - Counts are a snapshot.
views,subscribers,reactionsand poll percentages are what Telegram printed at scrape time. editedAtis always null: Telegram marks a post as edited (isEdited: true) but never prints the edit time on the public preview.forwardedFromcan be null even whenisForwardedis true: Telegram hides the source name for forwards from private or hidden sources.- Media are links, not files. Photo URLs and video thumbnails are the CDN links from the page, and Telegram's CDN links can expire. Nothing is downloaded.
- Animated GIFs are rendered by Telegram's preview as muted video loops, so they arrive as
mediaType: "video". - In-channel search is Telegram's own: it matches post text, results are ordered oldest to newest, and paging uses
the same
before=parameter. It is case-insensitive but not a full-text engine over the whole archive. A single post URL returns that post,searchQueryapplies to channel timelines only. - Reaction glyphs: Telegram prints custom emoji as an image with an id, so such reactions carry
emoji: "emoji-id:<id>"; paid star reactions are reported as"stars". - One post-id watermark per channel for
onlyNew. If you also usesearchQuerywithonlyNew, the cursor is shared with the timeline run of that channel; use a separatestateStoreNameto keep them apart. - Direct requests by default. Ten parallel direct requests to
t.meanswered fine when this actor was built. Enable Apify proxy if your runs get rate limited; a proxy failure fails the request, it never falls back to a direct one.
Responsible use
This actor reads the same pages any browser sees on t.me, for public channels only. Only collect channels you have a
reason to collect. Post text can contain personal data: how you store, process and share it is your responsibility
under the GDPR, PDPA and any other law that applies to you. Do not use it to build profiles of private individuals or
to evade Telegram's rate limits.
Development
npm cinpm test # node:test, parses the saved t.me fixturesnpm run build
Fixtures in test/fixtures/ were saved from live t.me pages on 25 October 2026 (tokens and CDN file names
scrubbed). docs/PARSING.md lists the selectors the parser relies on.