Telegram Channel Scraper
Pricing
from $3.10 / 1,000 scraped items
Telegram Channel Scraper
Scrapes posts from public Telegram channels via their t.me/s web preview. No account or API keys needed.
Pricing
from $3.10 / 1,000 scraped items
Rating
5.0
(1)
Developer
Twizzler Fan
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Scrapes posts from public Telegram channels using their t.me/s/<channel> web preview. No Telegram account, phone number or API keys are required.
For every post the Actor extracts the text, publish time, views, reactions, media (photos, videos, audio, documents, stickers), link previews, forward and reply information, hashtags and mentions, together with channel metadata (title, avatar, subscriber count, verified badge).
What can this Actor do?
- Monitor one or many public channels for new posts in a time window (last N minutes/hours/days or an explicit
since/untilrange). - Deduplicate across runs with the stable
uniqueKey(<channel>:<messageId>). - Run many channels in parallel with per-channel safety caps on posts and pages.
- Rotate Apify Proxy sessions automatically, retrying blocked or geo-restricted previews on a fresh IP.
Input
| Field | Type | Description |
|---|---|---|
channels | string[] | Required. Channel URLs (https://t.me/durov, https://t.me/s/durov), @usernames or bare usernames. |
lookbackValue | integer | How far back to fetch (default 24). |
lookbackUnit | minutes | hours | days | Unit for lookbackValue (default hours). |
sinceTimestamp | string | Optional ISO 8601 date or Unix timestamp. Overrides the lookback. |
untilTimestamp | string | Optional ISO 8601 date or Unix timestamp. Defaults to now. |
maxPostsPerChannel | integer | Cap on posts per channel, 0 = unlimited (default). |
maxPagesPerChannel | integer | Safety cap on preview pages (~20 posts each) per channel (default 50). |
concurrency | integer | Channels scraped in parallel (default 8). |
proxyConfiguration | object | Standard Apify proxy settings (default: Apify Proxy on). Residential proxies help with geo-restricted channels. |
Example:
{"channels": ["https://t.me/s/telegram", "@durov"],"lookbackValue": 7,"lookbackUnit": "days"}
Output
One dataset item per post:
{"uniqueKey": "telegram:350","id": 350,"url": "https://t.me/telegram/350","channel": {"username": "telegram","title": "Telegram News","url": "https://t.me/telegram","avatarUrl": "https://cdn4.telesco.pe/file/....jpg","isVerified": true,"subscribers": 10123456},"text": "Telegram 11.0 is out ...","publishedAt": "2026-10-20T14:03:11.000Z","publishedAtTimestamp": 1792504991000,"views": 2345678,"isEdited": false,"isAlbum": false,"postAuthor": null,"isForwarded": false,"forwardedFrom": null,"isReply": false,"replyToMessageId": null,"replyToUrl": null,"reactions": [{"type": "emoji","emoji": "❤","customEmojiId": null,"imageUrl": "https://telegram.org/img/emoji/40/E29DA4.png","count": 12000},{"type": "custom_emoji","emoji": null,"customEmojiId": "5780596797219016124","imageUrl": null,"count": 66},{ "type": "paid", "emoji": "⭐", "customEmojiId": null, "imageUrl": null, "count": 5 }],"totalReactions": 12071,"hasMedia": true,"mediaTypes": ["video"],"media": [{"type": "video","url": "https://cdn4.telesco.pe/file/....mp4","thumbnailUrl": "https://cdn4.telesco.pe/file/....jpg","caption": null,"duration": 42,"isDownloadable": true}],"linkPreview": null,"hashtags": [],"mentions": [],"scrapedAt": "2026-10-21T09:00:00.000Z"}
A per-run summary (time window, per-channel page/post counts, skipped inputs and errors) is stored in the default key-value store under the SUMMARY key. If the run is aborted, the summary written so far is flagged with "aborted": true.
Reactions
Each entry in reactions has a type:
emoji– a standard emoji reaction;emojiholds the character andimageUrlthe icon shown on t.me.custom_emoji– a Telegram Premium custom emoji; onlycustomEmojiIdis available (the web preview does not render it).paid– Telegram Stars;emojiis⭐.
Media
media[].url is the direct CDN link to the file (photo, video, audio, document, sticker) as served on the web preview; thumbnailUrl is the poster image for videos and link previews. linkPreview is a convenience copy of the first link-type media entry.
Telegram does not serve large videos on the web preview ("Media is too big"). Such entries have isDownloadable: false, caption set to Telegram's reason, url pointing at the post on t.me and thumbnailUrl still populated.
Limitations
- Only channels with a public web preview can be scraped. Private channels, groups, users and invite links (
t.me/+…,t.me/joinchat/…,t.me/c/…) are skipped. - Some channels are geo-restricted on the web preview; using residential proxies in
proxyConfigurationusually resolves this. - Comments / discussion threads are not part of the web preview and are not scraped.
- Telegram's preview serves ~20 posts per page; very large lookback windows on busy channels need a higher
maxPagesPerChannel.
Local development
npm installapify run # reads storage/key_value_stores/default/INPUT.json, writes storage/datasets/default/npm test # unit tests for input parsing and the HTML parser
Project structure
.actor/├── actor.json # Actor config: name, version, schemas├── input_schema.json # Input validation & Console form definition├── dataset_schema.json # Shape of each post item + Console table view├── key_value_store_schema.json # The SUMMARY record└── output_schema.json # Links to the dataset and SUMMARYsrc/├── main.ts # Entry point: input → scrape channels concurrently → dataset + SUMMARY├── input.ts # Input validation, channel/timestamp parsing├── scraper.ts # Walks a channel's t.me/s preview backwards page by page├── http.ts # undici GET with proxy sessions, retries and redirect detection├── proxy.ts # Sticky proxy session pool + undici dispatcher cache├── parser.ts # Cheerio parser for the web preview HTML├── output.ts # Maps parsed posts to dataset items├── types.ts # Shared types└── utils.ts # Helpers (counters, concurrency)