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

467

Total users

58

Monthly active users

16 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.
  • New messages on a schedule. sinceLastRun establishes a recent baseline, then collects messages newer than the saved checkpoint. An incomplete retry can replay messages; deduplicate by channel and message ID.
  • Date-bounded history. oldestMessageDate filters messages by their observed timestamp. Unknown timestamps are skipped and reported as incomplete coverage.
  • 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 verified older messages. Use YYYY-MM-DD or a timezone-qualified ISO timestamp.
sinceLastRunbooleanCollect messages newer than the saved checkpoint. Default false. See incremental limits below.
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 missing, private, or unsupported public preview, 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, forwarded_from_url, in_reply_toObserved forward display name, source link when available, 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

Example message structure (the media link is illustrative):

{
"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/example.mp4",
"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
COMPLETEThe requested bounded collection completed.
PARTIALA time budget, charge cap, failed channel, unknown filtered date, or incomplete incremental backlog left work unfinished. This can include zero messages.
VALID_EMPTYThe request was valid and there were no messages to return, for example no new posts since the last run.
UPSTREAM_FAILEDRequests failed and no messages were saved. Unverified or mismatched HTML is an error.
INVALID_INPUTInput validation stopped collection before contacting Telegram.

The first sinceLastRun run establishes a baseline using the latest maxMessagesPerChannel messages; it does not backfill all history. Later runs must reach the previous checkpoint before advancing it. If a charge cap, time budget, request failure, unknown date, or message limit prevents that, the old checkpoint is retained. Retrying can replay saved messages. Increase maxMessagesPerChannel to cover the backlog and deduplicate on (channel_username, message_id). Named checkpoint state is shared by this Actor's incremental runs within your Apify account, so run them sequentially.

Very short run timeouts return PARTIAL before opening a browser. The runtime guard reserves time for in-flight requests and saving the final summary. Message limits and named charges apply to saved rows; unbillable summary and diagnostic rows make the total dataset row count larger than the message count.

API integrations can use channelUsernames, channelUrls, handles, or usernames for channels, and maxMessages, maxResults, or limit for the message limit. Explicit limit aliases override the canonical schema default; supply only one limit field. format similarly overrides the default outputFormat.

Preview images, videos, and fonts are not downloaded; their observed links remain in the output. If the default proxy/browser path repeats the current page for an older-page cursor, one bounded direct HTTP request to the same public Telegram URL supplies the older HTML. The channel identity and cursor must still match before saving. Explicit custom proxy inputs are respected; a non-advancing page then remains incomplete rather than switching routes. RUN_SUMMARY.native_pagination_fallbacks reports direct fallback attempts.

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.