Telegram Channels Scraper: Messages, Contacts & Leads avatar

Telegram Channels Scraper: Messages, Contacts & Leads

Pricing

from $2.00 / 1,000 messages

Go to Apify Store
Telegram Channels Scraper: Messages, Contacts & Leads

Telegram Channels Scraper: Messages, Contacts & Leads

Scrape public Telegram channel messages with every email and link in each post pulled out for you, plus views, reactions and media. Schedule it to collect only new messages, with no account or phone number.

Pricing

from $2.00 / 1,000 messages

Rating

0.0

(0)

Developer

Khadin Akbar

Khadin Akbar

Maintained by Community

Actor stats

2

Bookmarked

424

Total users

75

Monthly active users

46 days

Issues response

6 days ago

Last modified

Share

What is Telegram Channel Scraper?

Telegram Channel Scraper turns public Telegram channel names or t.me links into a clean dataset of messages. Each message row has the text, post date, view count, reactions, media type and link, forward source, and any links and email addresses found in the text. An optional channel row adds the title, description, subscriber count and verification. Researchers, marketers, lead-gen teams, analysts and AI agents use it to monitor channels and pull contacts, with no Telegram account, phone number or login.

Why teams choose this Telegram scraper

  • Contacts pulled out for you. extracted_emails and extracted_links list every email address and URL found in each message, ready for lead lists.
  • Channel overview in the same dataset. With includeChannelInfo, one channel_info row adds subscribers, description and verification.
  • Only new messages on a schedule. sinceLastRun remembers the last message seen per channel, so scheduled runs return only fresh posts.
  • Date-bounded history. oldestMessageDate stops paging at the date you choose, so a backfill is exactly as deep as you need.
  • Channel discovery. discoverRelated lists channels that your channels forward from, a quick way to map a niche.
  • Built for AI agents. Every message also carries a compact markdown_preview for LLM context, with flat JSON through Apify MCP and the API.

Best fit for this Actor

  • Start here when you know the public channels you want and need their messages, links and contacts.
  • For finding channels by keyword first, start with Telegram Keyword Search Scraper and pass the channel handles into channels.
  • For channel statistics only, with no messages, use Telegram Channel Info Scraper instead.
  • Channels work when their public web preview (https://t.me/s/<channel>) is on, which is the case for most public channels.

What people and AI agents ask this Actor to do

Get the last 200 messages from these three crypto channels. Pull every email address posted in this channel. Monitor these news channels and give me only new posts each morning. Which channels does this channel forward from?

RequestInput to send
Recent messages from a few channels{"channels": ["durov", "telegram"], "maxMessagesPerChannel": 200}
Contacts posted in a channel{"channels": ["durov"], "maxMessagesPerChannel": 1000}, then read extracted_emails
Daily monitoring of new posts{"channels": ["durov"], "sinceLastRun": true} on a daily schedule
History back to a date{"channels": ["durov"], "oldestMessageDate": "2026-01-01", "maxMessagesPerChannel": 5000}
Map related channels{"channels": ["durov"], "discoverRelated": true}
Lean text rows for an LLM{"channels": ["durov"], "includeMedia": false, "includeReactions": false}

Example workflow: from a channel list to a lead sheet

A B2B marketer starts with ten public channels in their industry. They send the handles in channels with maxMessagesPerChannel set to 500. The dataset returns each message's message_text, posted_at, view_count, extracted_emails and extracted_links, plus one channel_info row per channel. They keep the messages that contain emails, export them to a spreadsheet, then schedule the same input with sinceLastRun on so each morning adds only new posts and new contacts.

How to scrape Telegram channels

  1. Add channel usernames, @handles or t.me links in Channels.
  2. Set Max messages per channel, and optionally Oldest message date or Since last run.
  3. Click Start. Export the dataset as JSON, CSV or Excel, or read it through the API.

Quick start input

{
"channels": ["durov", "telegram"],
"maxMessagesPerChannel": 100,
"includeChannelInfo": true,
"includeMedia": true,
"includeReactions": true,
"sinceLastRun": false,
"discoverRelated": false
}

Input reference

FieldTypeWhat it controls
channelsarray of stringsPublic channel usernames, @handles or t.me links.
maxMessagesPerChannelintegerCap on messages per channel. Default 100.
includeChannelInfobooleanAdd one channel_info row per channel. Default true.
includeMediabooleanInclude media type and media URL on each message. Default true.
includeReactionsbooleanInclude the reaction breakdown on each message. Default true.
oldestMessageDatestringStop at messages older than this date, in YYYY-MM-DD format.
sinceLastRunbooleanReturn only messages newer than the previous run. Default false.
discoverRelatedbooleanAdd discovered_channel rows for channels your channels forward from. Default false.
outputFormatstringKept so older saved inputs keep working; every message already includes markdown_preview.
proxyConfigurationobjectOptional Apify Proxy settings.

Output: Telegram channel data you receive

Each dataset row has a record_type. Message rows are the main output.

record_typeWhat one row represents
messageOne public channel message
channel_infoOne channel overview (with includeChannelInfo)
discovered_channelOne related channel handle (with discoverRelated)
channel_errorA channel whose public preview is off, with a note on how to check it
run_summaryTotals for the run: messages, emails, links and channels

Message fields:

FieldWhat it contains
channel_username, message_id, message_urlChannel, message ID and direct link
message_text, posted_atText and post time
view_count, reaction_count, reactionsViews and reactions
has_media, media_type, media_urlMedia details
is_forwarded, forwarded_from, in_reply_toForward and reply context
extracted_links, extracted_emailsLinks and email addresses found in the text
markdown_previewOne-line markdown summary of the message for LLM prompts
source_url, scraped_atProvenance and collection time
{
"record_type": "message",
"channel_username": "durov",
"message_id": "531",
"message_text": "🩵 Telegram now has a Rich Text Editor.\n\nIt supports tables, headings, inline media, lists, AI content, formulas, and more.\n\n\n😈 Messaging apps will never be the same!",
"posted_at": "2026-07-16T20:45:25+00:00",
"view_count": 5730000,
"reaction_count": 0,
"is_forwarded": false,
"forwarded_from": null,
"has_media": true,
"media_type": "video",
"media_url": "https://cdn4.telesco.pe/file/b231b9b161.mp4?token=UG9wsSyeVAOA7L87kUFppLT6N-AKz0c7PuG1BHRgLu5uISDSQP98p-9NnlN7-qiJQIDcaiGdER7teY91Yv9FzhkhIeH9PRwyOV8-TTRBxmhN_sNB4G_UOTBUDQRW5yg4nKww1utDGXuQ_6rZNZlk9b4w_hgT4rlvCw4riJUrYzyMq07Uo2OZYWbH7Tysj4UDJhrB-WR3iTwraWCbYa9_KVnj_fvtcrB-QR9VUPYO1frGbT8fpAJ3Bpys4Esg9FvRgNJhUi0L34ZHxkVKqDyn-mhcOLcQ_l-UMAeVZZCe39Y9h7SyKhzgXLeD19ZbYy51kk5ReSsmL2S2hRiN66qFJTzoLYYGMqknLXWitR9ENcuYlvuH2_duRcW1gSNrDutwJRiNb4oohoOr2QiJZhWoYyGpijaw_6z9cGAq5qraeb67jIHbQJRGf3qFSIx1nXYKlYBH2IGEFbmyeDQT784STQ5YPI-eEt4U2NpNTzs5qqOhyJVQlX8AwFaoOXyE8JMF1U5N6F2kgYRk9lSL-fG7i4rS94h3rQJ8XKuOf9GXGF6tJT-wZRWgCS1AQJnzDxJQ0sz9GR52DM9Ho7mOsVJxsH0JrprSkZ-jLGCuNWz4izHcr0djjMAgjRxHVogYUkwXcmv5R27x7EdgEMGthHOr_gJwSqXM3BRMKCcD7HrBjy0",
"extracted_links": [],
"extracted_emails": [],
"message_url": "https://t.me/durov/531",
"source_url": "https://t.me/s/durov",
"scraped_at": "2026-09-29T09:57:41.733Z"
}

What each run outcome means

Every run writes an OUTPUT record and a RUN_SUMMARY record to the default key-value store. Read OUTPUT.outcome to branch in code or in an agent.

OutcomeMeaning
COMPLETEMessages were collected from the requested channels.
PARTIALMessages were saved and a time budget or charge cap ended the run early.
VALID_EMPTYThe request was valid and there were no messages to return, for example no new posts since the last run.
UPSTREAM_FAILEDTelegram's public preview was unavailable for every requested channel.

Pricing

This Actor uses Pay per event. Apify platform usage is included in the event prices, so you pay only for events: one message event per saved message, one channel-info event per channel_info row, and one start event per run. discovered_channel, channel_error and run_summary rows are free. The live Pricing tab on this page shows the current event prices.

Worked examples:

  • 3 channels × 100 messages with channel info = 300 message events + 3 channel-info events + 1 start event.
  • A daily sinceLastRun run that finds 12 new posts = 12 message events + channel-info events + 1 start event.
  • includeChannelInfo: false = message events + 1 start event only.

Formula: message price × saved messages + channel-info price × channels + start event. Set a maximum charge per run in the run options to cap spend.

Use Telegram Channel Scraper with AI agents (MCP)

Connect this Actor to Claude, ChatGPT, Cursor or any MCP client through Apify MCP, then ask in plain language:

Collect the latest 100 messages from the public Telegram channels durov and telegram. Return message text, post date, view count, links and emails, and tell me the outcome and how many emails were found.

Agent checklist:

  1. Pass channel handles in channels and set maxMessagesPerChannel to the depth you need.
  2. Read rows with get-dataset-items; keep rows where record_type is message.
  3. Read OUTPUT.outcome, and the run_summary row for totals.
  4. Feed markdown_preview into prompts when you want compact message text.
  5. Keep message_url and scraped_at to cite each message.

API example

curl -X POST "https://api.apify.com/v2/acts/khadinakbar~telegram-channel-scraper/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"channels": ["durov"], "maxMessagesPerChannel": 50}'
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('khadinakbar/telegram-channel-scraper').call({
channels: ['durov', 'telegram'],
maxMessagesPerChannel: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const emails = items.filter((row) => row.record_type === 'message').flatMap((row) => row.extracted_emails ?? []);
console.log(emails);

Choosing the right Telegram tool

Other Actors from the same developer pick up where this one stops.

Your starting pointTool to useWhy it fits
When you know the channels and want their messagesThis ActorMessages, links, emails and channel info
When you start from a keyword or topicTelegram Keyword Search ScraperMatching channels, groups and messages; pass the handles into channels here
When you want channel stats onlyTelegram Channel Info ScraperSubscribers, bio, verification and engagement to compare many channels first
When you want the people active in a group or channelTelegram Members ScraperActive members from the public preview
When you want the photos and videos themselvesTelegram Media DownloaderPermanent copies of the files behind media_url

Best results

Starting situationHelpful actionExpected outcome
Known public channelsUse exact usernames or t.me linksClean message rows
Ongoing monitoringSchedule with sinceLastRun onOnly new posts each run
A dated backfillSet oldestMessageDate and a high maxMessagesPerChannelHistory back to that date
Messages for an LLMSet includeMedia and includeReactions to false and use markdown_previewCompact text rows
A channel_error row appearsOpen https://t.me/s/<channel> to confirm its public previewA clear answer on whether the channel is readable

Builder's note

I found that most Telegram research ends in two questions, what was said and who to contact, so every message row carries extracted_emails and extracted_links alongside the text. I learned that monitoring beats one-off pulls for Telegram, which is why sinceLastRun keeps the last message ID per channel and scheduled runs return only fresh posts.

FAQ

Do I need a Telegram account or phone number?

No. The Actor reads Telegram's public web preview and needs no account, phone number or API key.

Can I scrape private channels or groups?

The Actor reads public channels whose web preview is on. Private channels and groups you would need to join are outside its public-data scope.

How much does it cost to scrape 1,000 Telegram messages?

1,000 messages cost 1,000 message events plus channel-info events for each channel and one start event. Platform usage is included. Multiply by the prices on the Pricing tab.

How do I get only new messages every day?

Set sinceLastRun to true and schedule the Actor. Each run returns messages newer than the last one it saw.

What if a channel returns no messages?

Its public web preview is probably off, and the Actor writes a free channel_error row for it. Open https://t.me/s/<channel> in a browser; if no messages show there, the channel is readable only inside the Telegram app.

Responsible use

This Actor collects public Telegram channel content only. Messages can contain names, usernames and email addresses, which are personal data protected by laws such as the GDPR and CCPA. Collect and use them only with a lawful basis, honor opt-outs before any outreach, keep data no longer than you need, and respect Telegram's terms. Read Apify's guide on whether web scraping is legal for more context. Telegram is a trademark of its owner. This independent Actor is not affiliated with, associated with, or endorsed by Telegram. For questions or bugs, open a ticket in the Issues tab.