Telegram Channel Scraper
Pricing
from $0.44 / 1,000 messages
Telegram Channel Scraper
Scrape public Telegram channels without an account: channel info with subscriber count, and every message with text, date, views, reactions, media, links, hashtags and forwards. Search inside a channel, stop at a date or message id. Numbers come back as real numbers.
Pricing
from $0.44 / 1,000 messages
Rating
0.0
(0)
Developer
mick_
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Telegram Channel Scraper
Scrape public Telegram channels without a Telegram account. Get the channel's title, description and subscriber count as a number, and every message with text, date, views, reactions, photos, videos, link previews, outbound links, hashtags, mentions and forwards.
| At a glance | |
|---|---|
| You give it | Public channel names or t.me links, plus optional search, date or message-id limits |
| You get | One row per channel (subscriber count as a number) and one row per message with views, reactions, media and links |
| Price | $0.005 per run + $0.0017 per channel + $0.00085 per message (Free plan, lower on paid plans) |
| Speed | 1 channel and 20 messages in about 7 seconds |
| Needs | Nothing: no login, no API key, no proxy |
What you get
- Channel info: title, description, subscribers, photo/video/link counters, verified badge, avatar.
- Messages, newest first, back through the whole public history if you want it.
- Real numbers:
1.63Mviews becomes1630000, so you can sort, filter and chart. - Search inside channels with Telegram's own channel search (recent posts only; see the FAQ).
- Only new messages, automatically. Turn on
onlyNewMessagesand each run picks up where the last one stopped. No ids to copy between runs, no duplicates, no double charges. - Stop points: a date, or a message id. Only messages after it are fetched and charged.
- Minimum views filter. Skipped messages are not charged.
- Engagement built in: every message has
engagementRate(reactions per view) andviewRate(views per subscriber), ready to rank posts and compare channels. - Extracted for you: outbound links, hashtags, @mentions, link preview title and site, reactions with counts (including paid star reactions) and a total.
- Light: 1 channel and 20 messages used $0.0003 of platform usage in one request.
Use cases
- Crypto and trading signals. Watch channels for tickers and links the moment they post.
- News and OSINT monitoring. Track what public channels say about a topic, with dates and view counts.
- Influencer and channel research. Compare subscriber counts and engagement across many channels.
- Link and lead extraction. Every outbound link a channel shares.
- AI summaries and sentiment. Clean message text with dates and reach.
Example inputs
Latest 100 messages from two channels
{ "channels": ["durov", "https://t.me/telegram"], "maxMessagesPerChannel": 100 }
Everything since a date
{ "channels": ["telegram"], "maxMessagesPerChannel": 0, "oldestMessageDate": "2026-01-01" }
Only new messages, for a schedule
{ "channels": ["durov", "telegram"], "onlyNewMessages": true, "includeChannelInfo": false }
The first run saves the latest 100 messages. Every run after that saves only what was posted since.
Search inside a channel
{ "channels": ["durov"], "searchQuery": "TON", "maxMessagesPerChannel": 50 }
Subscriber counts for a list of channels
{ "channels": ["durov", "telegram"], "channelInfoOnly": true }
Input
| Field | What it does |
|---|---|
channels | Usernames or links: durov, @durov, https://t.me/durov. |
maxMessagesPerChannel | Newest first. 0 means all public history. Default 100. |
searchQuery | Only messages matching this text (Telegram returns about the 20 most recent matches). |
oldestMessageDate | Stop at messages older than this date. |
afterMessageId | Stop at this message id. |
onlyNewMessages | Remember the newest saved message per channel; the next run starts after it. |
stateName | Optional. A separate memory per schedule when two schedules watch the same channel. |
minViews | Skip messages with fewer views (not charged). |
includeChannelInfo | One channel row per channel. Default on. |
channelInfoOnly | Channel rows only, no messages. |
Output
Each row has a type: channel or message. Real rows from a test run on 2026-09-26 (long text shortened here):
Channel
{"type": "channel","channel": "durov","title": "Pavel Durov","description": "Founder of Telegram.","subscribers": 10600000,"subscribersText": "10.6M","photos": 102,"videos": 46,"links": 200,"files": null,"isVerified": true,"avatarUrl": "https://cdn4.telesco.pe/file/PwaBtFuo9UBudJwMKXgYeWSHFhZ1wTCA-wbjfFspV08LLTYiNUdq5ZKgVnBzmW7JXpgszn2y2bWDVCdjZHpaejEJpBeXozIiSN28g0x9smQcPGtDd4gvTPcRcjyp6Iig9cRtYbGowCBalvStcy-ExGW6hv0XLL_VQoN0zCUDSEVA1L4uNKuBVN39trixlnObeO3ptQRxDs44wIzdxy5NAZe-zu4xiejgJYWH8axLd1c6zC66Qw4EHiZUdp8jsSd7k0wyM1bh8o7q3fx16W1hr8RSuYQYatgs2Nim8zi1NTaStvFnH1fdI6DvLoYbKh4qlajW4vlWSJ3CKkUM1q5qQA.jpg","url": "https://t.me/durov"}
Message
{"type": "message","channel": "durov","messageId": 548,"url": "https://t.me/durov/548","date": "2026-09-11T16:04:02+00:00","text": "🤝 Telegram has become the sponsor of Codeforces , the largest competitive programming platform in the world. \n\n ⚡CodeForces organizes over 100 coding contests every year and has 4 million contestants signed up.\n\n🌱 Since 2010, I've supported Codeforces through ...","views": 1630000,"author": "Pavel Durov","isEdited": false,"isForwarded": false,"forwardedFrom": null,"forwardedFromUrl": null,"replyToMessageId": null,"mediaType": "text","photoUrls": [],"videoUrls": [],"videoThumbnailUrls": [],"videoDuration": null,"documents": [],"pollQuestion": null,"linkPreview": {"url": "https://codeforces.com/blog/entry/156620","site": "Codeforces","title": "Telegram Returns as Title Sponsor of Codeforces!","description": "Hi, Codeforces!"},"links": ["https://codeforces.com/blog/entry/156620"],"hashtags": [],"mentions": [],"reactions": [{"emoji": "⭐","emojiId": null,"count": 13500,"isPaid": true},{"emoji": null,"emojiId": "5399847211989246390","count": 28100,"isPaid": false},{"emoji": null,"emojiId": "5936157098181135162","count": 8080,"isPaid": false},{"emoji": null,"emojiId": "5373223594484587136","count": 7580,"isPaid": false}],"totalReactions": 57260,"channelTitle": "Pavel Durov","channelSubscribers": 10600000,"engagementRate": 0.0351,"viewRate": 0.1538,"searchQuery": null}
Standard reactions come with the emoji. Custom emoji reactions come back as emojiId only, with emoji empty: Telegram's public preview does not name them. The id is stable, so you can still group and count them.
engagementRate is totalReactions divided by views. viewRate is views divided by channelSubscribers. Both are fractions (0.0351 means 3.51%) and empty when the numbers behind them are missing.
mediaType is one of text, photo, video, document, poll, sticker, voice, unsupported (media the web preview can't show; open url in Telegram) or other. links holds outbound links from the text; @mentions and #hashtags are in their own fields, and links to the channel's own posts are left out. Service notices such as "live stream started" are skipped and not charged.
Pricing
Pay per event:
- $0.005 per run start
- $0.0017 per channel info row
- $0.00085 per message
Lower on higher Apify plans. Apify platform usage is billed separately to your account and is tiny: 1 channel and 20 messages used $0.0003.
| What you scrape | Actor cost |
|---|---|
| 1 channel + 100 messages | about $0.09 |
| 10 channels + 1,000 messages | about $0.87 |
| 50 channels, info only | about $0.09 |
Automate it with n8n
Each workflow uses n8n's official Apify node, operation Run actor and get dataset, actor labrat011/telegram-channel-scraper. Paste the input into Input JSON; switch it to Expression when it contains {{ }}.
1. New messages to Slack or Discord every 15 minutes
Schedule Trigger (every 15 minutes)> Apify: Run actor and get dataset{ "channels": ["channel_one", "channel_two"], "onlyNewMessages": true, "includeChannelInfo": false }> Discord / Slack: "{{ $json.channel }}: {{ $json.text }} {{ $json.url }}"
2. Keyword alerts across channels
Schedule Trigger (hourly)> Apify: Run actor and get dataset { "channels": [...], "searchQuery": "airdrop", "oldestMessageDate": "<1 hour ago>" }> Telegram / Email: forward each hit with its link
3. Channel leaderboard in Google Sheets
Schedule Trigger (weekly)> Apify: Run actor and get dataset { "channels": [ ...50 channels... ], "channelInfoOnly": true }> Google Sheets: Append rows (date, channel, subscribers)
Week-over-week subscriber growth per channel, charted from the sheet.
4. Link harvesting
Schedule Trigger (daily)> Apify: Run actor and get dataset (your channels, last 24 hours)> Split Out: links> Remove Duplicates: on the link> Airtable: store link, channel, date, views
5. Daily AI digest of a busy channel
Schedule Trigger (daily 18:00)> Apify: Run actor and get dataset (one channel, last 24 hours, minViews 1000)> Aggregate: text, views, url> OpenAI / Anthropic: "Summarize today's most-viewed posts in 5 bullets with links"> Email: send the digest
For AI agents
- Actor:
labrat011/telegram-channel-scraper - Smallest input:
{ "channels": ["durov"] } - One row = one channel (
type: "channel") or one message (type: "message"). Key fields: channels:channel,title,subscribers; messages:messageId,url,date,text,views,engagementRate,viewRate,links. - Scheduled runs: set
onlyNewMessages: true; each run returns only messages posted since the last one. - Billing:
apify-actor-startonce per run,channel-infoper channel row,messageper message row. Cap spend withmaxMessagesPerChannelor a maximum cost per run. - Run it:
POST https://api.apify.com/v2/acts/labrat011~telegram-channel-scraper/run-sync-get-dataset-itemswith the input as the JSON body, or call it from the Apify MCP server. - Done signal: the run's status message reads
Saved N channels and M messages in R requests.
FAQ
Why does a channel return nothing? Only public channels with Telegram's web preview turned on can be read without an account. The run log says which channels had no preview. Some large brands turn it off.
Can it read groups or private channels? No. Public channels only, and no login is used.
Why does search return fewer posts than I expected? Search uses Telegram's public web search, which returns about the 20 most recent matches per channel and does not reach far back. For a full keyword scan of older posts, fetch the history (with oldestMessageDate) and filter the text yourself.
How does "only new messages" remember? It keeps the newest saved message id per channel in a key-value store named telegram-channel-scraper-state in your Apify account. A search keeps its own memory, separate from plain runs. To start over, delete that store or use a new stateName. If a run stops early at maxMessagesPerChannel or your maximum cost per run, the next run starts after the newest message saved, so older unread messages from that gap are skipped. Keep the limit above what a channel posts between runs.
Do I need a proxy? No.
Support
Open an issue on the actor's Issues tab with the run ID and it will be looked at.