Telegram Scraper · Channel Posts by Date, Views & Reactions
Pricing
from $2.00 / 1,000 posts
Telegram Scraper · Channel Posts by Date, Views & Reactions
Scrape public Telegram channels without login: posts in an exact from/to date window (jumps straight to old dates), views, per-emoji reactions, forwards, replies, media and links, keyword filter, only-new mode. Channels without a public preview are reported, never charged.
Pricing
from $2.00 / 1,000 posts
Rating
0.0
(0)
Developer
TheQuietStack
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Telegram scraper for public channels: posts from an exact date range with views, reactions, forwards, media and links, without login or phone number.
Scrape public Telegram channels from Telegram's own public web preview (t.me/s/<channel>): every post becomes one flat row with its ISO date, text, views, reactions per emoji, forward source, reply target, media type and media URLs, links, hashtags and an edited flag. No login, no Telegram account, no API key, no phone number.
Before you use the output, read Personal data & legal use.
Why this scraper
- A date range that is exact - in both directions. Set
dateFromanddateTo(a day or an ISO date-time with offset). Every post is checked against both bounds; paging stops at the first post older thandateFrom. Posts outside the window are never written and never charged. - Old windows without paging through everything newer. If
dateTolies months or years back, the Actor jumps there by binary search over post IDs (?before=) instead of walking every page in between. Measured on 01 Oct 2026: a window ending 31 Mar 2026 was found with 4 extra page requests ondurovand 7 ontelegram. - Every channel gets a clear verdict. A username that has no public preview is not silently skipped: the run summary says whether it does not exist, is a bot or user, is a group, or is a channel whose preview Telegram redirects away from this server (typically a regional or legal restriction). None of these is charged.
- Honest numbers. The preview abbreviates counts (
1.85M). You get the converted number inviewsand the shown text inviewsText, plusviewsExact: falsewhenever Telegram rounded. The channel profile record takes the exact subscriber count from the channel page (10 563 281, not10.6M). - Monitoring mode.
onlyNewPostsremembers the newest post per channel and on the next scheduled run returns only what is newer - you are not charged twice. - A hard limit you can trust.
maxPostsand Apify's Max cost per run stop the run cleanly; nothing beyond is fetched or charged.
Input example
{"channels": ["durov", "https://t.me/telegram"],"dateFrom": "2025-06-01","dateTo": "2026-03-31","maxPostsPerChannel": 500,"keywords": ["update"],"includeChannelProfile": true}
channels- usernames,@names,t.me/<name>,t.me/s/<name>or post links. Invite links (t.me/+...) belong to private chats and are rejected.dateFrom/dateTo- inclusive. A plain date means 00:00:00 / 23:59:59.999 UTC of that day; give an offset (2026-09-01T00:00:00+02:00) for another time zone.daysBackis a shortcut fordateFrom.keywords+keywordMode(any/all) - case-insensitive match on the post text.skipForwardeddrops forwarded posts. Filtered posts are not charged.maxPostsPerChannel,maxPosts(whole run),maxPagesPerChannel(safety cap, 20 posts per page).includeChannelProfile(+exactSubscriberCount) - one extra row per channel.onlyNewPosts+stateStoreName- for schedules.requestDelaySecs- pause between page requests, at least 1 s (default 2 s).
Output example
{"recordType": "post","channel": "durov","channelTitle": "Pavel Durov","postId": 548,"url": "https://t.me/durov/548","date": "2026-09-11T16:04:02.000Z","text": "🤝 Telegram has become the sponsor of Codeforces — the largest competitive programming platform in the world. ...","views": 1850000,"viewsText": "1.85M","viewsExact": false,"reactions": [{ "emoji": "⭐", "customEmojiId": null, "paid": true, "count": 13900, "countText": "13.9K", "countExact": false },{ "emoji": null, "customEmojiId": "5399847211989246390", "paid": false, "count": 30100, "countText": "30.1K", "countExact": false }],"forwardedFrom": null,"replyTo": null,"mediaType": "text","media": [],"mediaUrls": [],"linkPreview": { "url": "https://codeforces.com/blog/entry/156620", "siteName": "Codeforces", "title": "Telegram Returns as Title Sponsor of Codeforces!", "description": "Hi, Codeforces!", "imageUrl": "https://cdn4.telesco.pe/file/..." },"links": ["https://codeforces.com/blog/entry/156620"],"hashtags": [],"mentions": [],"edited": false,"authorSignature": "Pavel Durov","scrapedAt": "2026-10-01T12:00:00.000Z"}
| Field | Meaning |
|---|---|
postId, url, date | Post ID within the channel, permalink, publication time in ISO 8601 UTC (edits keep the original date) |
views, viewsText, viewsExact | Number as shown, converted (1.2K -> 1200); viewsExact is false when Telegram abbreviated it |
reactions | One entry per reaction: emoji (standard emoji), customEmojiId (custom emoji, which the preview shows only as an ID), paid (Telegram Stars), count / countText / countExact |
forwardedFrom | { name, url, channel, postId } of the original, when the post is a forward |
replyTo | { postId, channel, url, author, text } of the replied-to post |
mediaType | text, photo, video, round_video, gif, voice, audio, document, sticker, poll, location, album, mixed, none |
media, mediaUrls | Per item: type, URL, thumbnail, duration, title; mediaUrls is the flat list of downloadable URLs |
linkPreview, links, hashtags, mentions | Link card and everything linked in the text |
edited, authorSignature | Edited marker and the author signature, if the channel shows one |
With includeChannelProfile, one row per channel has recordType: "channel": title, description, subscribers (+ subscribersText, subscribersExact), photoUrl, verified, photos, videos, files, links, url.
The run summary (SUMMARY in the key-value store) lists per channel: status (ok, partial, no_public_preview, not_found, not_a_channel, failed, blocked), the reason, posts written, pages fetched, date-seek pages, what was skipped (after dateTo, keyword, forwarded, service messages, duplicates, already seen) and why paging stopped.
Honest limits
- Public channels only. Groups, private channels, user accounts and bots have no public web preview. They are reported in the summary, never charged.
- Counts above 999 are rounded by Telegram in the preview (
views, reaction counts). We convert them and flag them (viewsExact: false) - we never present a rounded number as exact. Only the subscriber count has an exact public source, and the profile record uses it. - Custom emoji reactions appear in the preview only as an ID (
customEmojiId), not as a character. - Media URLs point to Telegram's CDN and are signed; they expire after some time. Download what you need soon after the run. Large videos the preview does not play come with a thumbnail and
url: null. - Regional restrictions: some channels are not shown to servers in certain regions; Telegram then redirects the preview away. The Actor reports this as
no_public_previewand does not try to get around it. - The date jump assumes post IDs grow with time, which is how Telegram numbers channel posts. Every written post is still checked against both bounds individually.
- Comments under posts are not part of the public preview and not part of this Actor.
Polite access - Bot protection is never bypassed
- One request at a time, with a pause between pages (
requestDelaySecs, minimum 1 s, default 2 s), and hard caps per channel and per run. - Bot protection is never bypassed. If Telegram answers with HTTP 403 or 429, a captcha or challenge page, a redirect to a login page, or HTML without the expected preview structure, the Actor stops the whole run at once with status FAILED and a clear message (
SUMMARY.blockednames the channel and the reason; remaining channels are listed undernotReached). No retries, no proxy or IP rotation, no header tricks, no login. Rows written before the stop stay in the dataset; nothing is charged for the blocked page or anything after it. - Network errors and other HTTP errors are not retried either: the channel is marked
failedorpartialand the run moves on.
Personal data & legal use
Public channel posts are public, but they can still contain personal data (names, photos, opinions, author signatures, forwarded posts of private persons).
- You are the controller. Under the Apify Standard Actor Contract (section 5.2.1) the user who runs this Actor is the controller of the personal data it processes; the Actor's creator acts as processor. You need your own legal basis for your purpose and must give the people concerned the information the law requires.
- Users in the EU/EEA (or processing data of people there) are themselves subject to the GDPR, including Art. 6 (legal basis), Art. 14 (information when data is not collected from the person) and Art. 21 (right to object). Collect only what your purpose needs and delete it when it is no longer needed.
- Not allowed: stalking, profiling or tracking individuals, harassment, and building contact lists for unsolicited messages.
- No enrichment, no accounts. The output contains only what Telegram's public preview shows. For usernames that belong to a person, the Actor records nothing but the status
not_a_channel. - Nothing is kept between runs except, with
onlyNewPosts, the newest post ID per channel in your own key-value store. - Respect Telegram's Terms of Service and the rights of channel owners when you reuse texts or media.
Pricing (pay per event)
- Per post (
post): charged only for posts written to the dataset. - Per channel profile (
channel-profile): only withincludeChannelProfile. - Never charged: channels without a public preview, non-existent or invalid usernames, blocked or failed pages, posts outside the date window, keyword misses, skipped forwards, service messages, duplicates, and posts already delivered by an earlier
onlyNewPostsrun.
Use it via API, integrations and AI agents
curl -X POST "https://api.apify.com/v2/acts/thequietstack~telegram-channel-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \-H "Content-Type: application/json" \-d '{"channels":["durov"],"daysBack":30,"maxPostsPerChannel":100}'
Works with Apify integrations (Make, n8n, Zapier, Google Sheets), schedules and webhooks.
Data source and legal
- Source: Telegram's public channel web preview at
https://t.me/s/<channel>and the public channel pagehttps://t.me/<channel>(exact subscriber count). No login, no Telegram API, no API key. - This Actor is not affiliated with or endorsed by Telegram.