Telegram Channel Scraper avatar

Telegram Channel Scraper

Pricing

from $0.44 / 1,000 messages

Go to Apify Store
Telegram Channel Scraper

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_

mick_

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Telegram Channel Scraper logo

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 itPublic channel names or t.me links, plus optional search, date or message-id limits
You getOne 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)
Speed1 channel and 20 messages in about 7 seconds
NeedsNothing: 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.63M views becomes 1630000, 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 onlyNewMessages and 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) and viewRate (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

FieldWhat it does
channelsUsernames or links: durov, @durov, https://t.me/durov.
maxMessagesPerChannelNewest first. 0 means all public history. Default 100.
searchQueryOnly messages matching this text (Telegram returns about the 20 most recent matches).
oldestMessageDateStop at messages older than this date.
afterMessageIdStop at this message id.
onlyNewMessagesRemember the newest saved message per channel; the next run starts after it.
stateNameOptional. A separate memory per schedule when two schedules watch the same channel.
minViewsSkip messages with fewer views (not charged).
includeChannelInfoOne channel row per channel. Default on.
channelInfoOnlyChannel 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 scrapeActor cost
1 channel + 100 messagesabout $0.09
10 channels + 1,000 messagesabout $0.87
50 channels, info onlyabout $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.

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-start once per run, channel-info per channel row, message per message row. Cap spend with maxMessagesPerChannel or a maximum cost per run.
  • Run it: POST https://api.apify.com/v2/acts/labrat011~telegram-channel-scraper/run-sync-get-dataset-items with 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.