Telegram Channel Scraper: Messages & Search avatar

Telegram Channel Scraper: Messages & Search

Pricing

from $0.48 / 1,000 channel messages

Go to Apify Store
Telegram Channel Scraper: Messages & Search

Telegram Channel Scraper: Messages & Search

Scrape public Telegram channel profiles and 60-field messages with reactions, polls, media, keyword search, date filters, and incremental checkpoints.

Pricing

from $0.48 / 1,000 channel messages

Rating

0.0

(0)

Developer

ScrapingMonkey

ScrapingMonkey

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Telegram Channel Scraper - Channel Profiles, Messages and Keyword Search

Extract public Telegram channel information, message history, media metadata, reactions, polls, and keyword matches without a Telegram account, phone number, API ID, or bot token.

  • Collect channel titles, descriptions, avatars, verification status, subscribers, media counters, and recent engagement metrics
  • Scrape public message history with inclusive date filters and limits up to 5,000 messages per channel
  • Search for keywords or phrases inside multiple public channels
  • Resume recurring runs from a global or per-channel message ID checkpoint
  • Preserve plain text and rich HTML, including formatting, mentions, hashtags, links, and custom emojis
  • Extract views, standard reactions, custom reactions, paid Telegram Stars, polls, forwards, replies, albums, photos, videos, and stickers when exposed publicly
  • Optionally store bounded public media files in the run Key-value store
  • Process up to 100 public channel usernames or URLs in one run
  • Process independent channels or channel/search-term pairs concurrently with a configurable limit
  • Use mandatory built-in Apify Residential Proxy automatically; no proxy input is required
  • Export results to JSON, CSV, Excel, XML, or access them through the Apify API

What can you do with this Actor?

Mode / actionInputOutputBest for
channelInfoPublic channel usernames or URLsOne profile and recent-analytics row per channelChannel discovery, audience sizing, and monitoring
messagesPublic channels, message limit, optional date rangePublic messages in newest-first orderContent archives, media research, and engagement analysis
searchMessagesPublic channels and search termsMessages matched by Telegram's channel searchTopic tracking, brand monitoring, and historical research

One mode runs at a time. Use channelInfo to evaluate channels, then pass the same channels array to messages or searchMessages in another run.

Quick start

  1. Open the Actor and click Try for free.
  2. Keep channelInfo selected and enter a public channel such as durov.
  3. Add more usernames, @usernames, or t.me URLs if needed.
  4. Click Start.
  5. Preview the dataset or download it in your preferred format.

The default input requests the public profile for @durov and returns one useful dataset row.

Input examples

Collect channel information

{
"mode": "channelInfo",
"channels": [
"durov",
"@telegram",
"https://t.me/telegramtips"
]
}

One dataset row represents one public channel. Recent analytics use the posts visible on the first public preview page.

Scrape public channel messages

{
"mode": "messages",
"channels": ["durov"],
"maxMessages": 1000,
"dateFrom": "2025-01-01",
"dateTo": "2025-12-31",
"includeServiceMessages": true,
"mediaMode": "urls",
"maxConcurrency": 5
}

maxMessages applies separately to every channel. Messages are returned newest first after date filtering.

Search messages inside channels

{
"mode": "searchMessages",
"channels": ["durov", "telegramtips"],
"searchTerms": ["privacy", "Telegram"],
"maxMessages": 200,
"dateFrom": "2024-01-01",
"includeServiceMessages": false,
"mediaMode": "urls"
}

The limit applies independently to every channel and search-term pair. Two channels and two terms can therefore return up to 800 message rows.

Resume an incremental channel export

{
"mode": "messages",
"channels": ["durov", "telegram"],
"maxMessages": 1000,
"afterMessageIds": {
"durov": 518,
"telegram": 429
},
"maxConcurrency": 5
}

After every run, read RUN_SUMMARY.nextAfterMessageIds and pass that object into the next scheduled run. Checkpoints are exclusive: a value of 518 returns only messages whose ID is greater than 518.

Store public media files

{
"mode": "messages",
"channels": ["durov"],
"maxMessages": 50,
"mediaMode": "urls",
"downloadMedia": true,
"maxMediaFiles": 25,
"maxMediaSizeMb": 20
}

Successfully downloaded files are stored in the run's default Key-value store. Their record keys are returned in media[].storeKey and mediaStoreKeys. Signed source URLs remain in the dataset even when a file is skipped or cannot be stored.

Complete output examples

The Actor always emits complete, stable shapes. Source fields that are not available use null; repeatable collections use empty arrays; boolean indicators remain explicit. Temporary public media URLs are returned only when mediaMode is urls.

Complete channel output - 30 top-level fields

{
"recordType": "channel",
"channelId": "-1006503122",
"username": "durov",
"title": "Pavel Durov",
"channelUrl": "https://t.me/durov",
"previewUrl": "https://t.me/s/durov",
"description": "Founder of Telegram.",
"avatarUrl": "https://cdn4.telesco.pe/file/example-avatar.jpg",
"verified": true,
"subscriberCount": 11300000,
"subscriberCountRaw": "11.3M",
"subscriberCountApproximate": true,
"photoCount": 101,
"photoCountRaw": "101",
"photoCountApproximate": false,
"videoCount": 45,
"videoCountRaw": "45",
"videoCountApproximate": false,
"linkCount": 194,
"linkCountRaw": "194",
"linkCountApproximate": false,
"latestMessageId": 538,
"latestMessageDate": "2026-08-07T14:35:57Z",
"recentPostsSampleSize": 20,
"recentAverageViews": 5372500.0,
"recentMedianViews": 4910000.0,
"recentAverageReactions": 64215.35,
"recentEngagementRatePercent": 1.1953,
"available": true,
"scrapedAt": "2026-08-08T04:45:00Z"
}

Complete message output - 60 top-level fields

The same shape is used by messages and searchMessages. In regular message mode, searchTerm and searchRank are null.

{
"recordType": "message",
"channelId": "-1006503122",
"channelUsername": "durov",
"channelTitle": "Pavel Durov",
"channelUrl": "https://t.me/durov",
"channelSubscriberCount": 11300000,
"channelSubscriberCountRaw": "11.3M",
"messageId": 518,
"messageUrl": "https://t.me/durov/518",
"date": "2026-06-25T13:03:57Z",
"displayedTime": "21:03",
"searchTerm": "Telegram",
"searchRank": 1,
"text": "Telegram continues to improve privacy. Read the update and independent source. #privacy @telegram",
"textHtml": "<tg-emoji emoji-id=\"5368324170671202286\"><i class=\"emoji\"><b>🔐</b></i></tg-emoji> <b>Telegram</b> continues to improve privacy. Read the <a href=\"https://telegram.org/blog/example\">update</a> and <a href=\"https://example.com/source\">independent source</a>. <a href=\"https://t.me/s/durov?q=%23privacy\">#privacy</a> <a href=\"https://t.me/telegram\">@telegram</a>",
"isEdited": true,
"isService": false,
"serviceText": null,
"authorName": "Pavel Durov",
"authorUrl": "https://t.me/durov",
"authorAvatarUrl": "https://cdn4.telesco.pe/file/example-author.jpg",
"authorSignature": "Pavel Durov",
"views": 5850000,
"viewsRaw": "5.85M",
"viewsApproximate": true,
"reactions": [
{
"emoji": "👍",
"emojiId": null,
"emojiImageUrl": "https://telegram.org/img/emoji/40/F09F918D.png",
"count": 219000,
"countRaw": "219K",
"isPaid": false,
"isApproximate": true
}
],
"totalReactions": 412838,
"paidReactions": 65900,
"reactionsApproximate": true,
"estimatedEngagementRatePercent": 7.0571,
"estimatedViewsPerSubscriberPercent": 51.7699,
"urls": [
"https://telegram.org/blog/example",
"https://example.com/source",
"https://t.me/s/durov?q=%23privacy",
"https://t.me/telegram"
],
"externalUrls": [
"https://example.com/source"
],
"telegramUrls": [
"https://telegram.org/blog/example",
"https://t.me/s/durov?q=%23privacy",
"https://t.me/telegram"
],
"mentions": ["@telegram"],
"hashtags": ["#privacy"],
"customEmojis": [
{
"emojiId": "5368324170671202286",
"emoji": "🔐",
"imageUrl": "https://telegram.org/img/emoji/40/F09F9490.png"
}
],
"mediaType": "album",
"media": [
{
"type": "photo",
"url": "https://cdn1.telesco.pe/file/example-photo.jpg",
"thumbnailUrl": "https://cdn1.telesco.pe/file/example-photo.jpg",
"sourceUrl": "https://t.me/durov/518?single",
"durationSeconds": null,
"width": 600,
"height": 800,
"aspectRatio": 0.75,
"fileName": null,
"fileSizeText": null,
"mimeType": "image/jpeg",
"storeKey": "TG_MEDIA_durov_518_0_6f88af4a31897b67.jpg",
"storeContentType": "image/jpeg",
"storeSizeBytes": 184225
}
],
"mediaCount": 3,
"isAlbum": true,
"hasUnsupportedMedia": false,
"photoUrls": [
"https://cdn1.telesco.pe/file/example-photo.jpg"
],
"videoUrl": "https://cdn1.telesco.pe/file/example-video.mp4",
"videoThumbnailUrl": "https://cdn1.telesco.pe/file/example-video-thumbnail.jpg",
"videoDurationSeconds": 28,
"mediaWidth": 600,
"mediaHeight": 800,
"mediaAspectRatio": 0.75,
"mediaStoredCount": 1,
"mediaStoreKeys": [
"TG_MEDIA_durov_518_0_6f88af4a31897b67.jpg"
],
"linkPreview": {
"url": "https://telegram.org/blog/example",
"siteName": "Telegram",
"title": "Telegram privacy update",
"description": "New privacy and security controls are available.",
"imageUrl": "https://cdn4.telesco.pe/file/example-preview.jpg",
"videoUrl": null,
"videoThumbnailUrl": null,
"videoDurationSeconds": null
},
"forwardedFrom": {
"name": "Telegram Geeks",
"url": "https://t.me/geekschannel/1023"
},
"replyTo": {
"messageId": 500,
"messageUrl": "https://t.me/durov/500",
"authorName": "Pavel Durov",
"text": "Earlier message text",
"isQuote": true
},
"poll": {
"question": "Which topic should be covered next?",
"type": "Anonymous Poll",
"isMultiple": true,
"totalVoters": 611000,
"totalVotersRaw": "611K",
"totalVotersApproximate": true,
"optionsUrl": "https://t.me/durov/518",
"options": [
{
"text": "Privacy",
"percent": 63.0
}
]
},
"commentsCount": 12500,
"commentsCountRaw": "12.5K",
"commentsCountApproximate": true,
"commentsUrl": "https://t.me/durov/518?comment=100",
"scrapedAt": "2026-08-08T04:45:00Z"
}

What Telegram data can you extract?

CategoryFields
Row identityrecordType, scrapedAt
Channel identitychannelId, username, title, channelUrl, previewUrl, description, avatarUrl, verified, available
Channel audience and content counterssubscriberCount, subscriberCountRaw, subscriberCountApproximate, photoCount, photoCountRaw, photoCountApproximate, videoCount, videoCountRaw, videoCountApproximate, linkCount, linkCountRaw, linkCountApproximate
Recent channel analyticslatestMessageId, latestMessageDate, recentPostsSampleSize, recentAverageViews, recentMedianViews, recentAverageReactions, recentEngagementRatePercent
Message contextchannelUsername, channelTitle, channelSubscriberCount, channelSubscriberCountRaw, messageId, messageUrl, date, displayedTime, searchTerm, searchRank
Message content and authorshiptext, textHtml, isEdited, isService, serviceText, authorName, authorUrl, authorAvatarUrl, authorSignature
Views and engagementviews, viewsRaw, viewsApproximate, reactions, totalReactions, paidReactions, reactionsApproximate, estimatedEngagementRatePercent, estimatedViewsPerSubscriberPercent
Entities and linksurls, externalUrls, telegramUrls, mentions, hashtags, customEmojis, linkPreview
MediamediaType, media, mediaCount, isAlbum, hasUnsupportedMedia, photoUrls, videoUrl, videoThumbnailUrl, videoDurationSeconds, mediaWidth, mediaHeight, mediaAspectRatio, mediaStoredCount, mediaStoreKeys
Message relationshipsforwardedFrom, replyTo, poll, commentsCount, commentsCountRaw, commentsCountApproximate, commentsUrl

Nested reactions include emoji, emojiId, emojiImageUrl, count, countRaw, isPaid, and isApproximate. Nested media include type, url, thumbnailUrl, sourceUrl, durationSeconds, width, height, aspectRatio, fileName, fileSizeText, mimeType, storeKey, storeContentType, and storeSizeBytes. Storage fields are null unless downloadMedia successfully stores that file. Nested objects use exactly the keys shown in the complete message example.

The default dataset has one Results view containing every documented channel and message field. Unavailable fields remain visible as null or empty arrays; no reduced “overview” hides the rest of the record.

Input parameters

ParameterTypeRequiredDefaultDescription
modestringYeschannelInfochannelInfo, messages, or searchMessages
channelsstring[]Yes["durov"]Up to 100 public usernames, @usernames, t.me/name, or t.me/s/name URLs
searchTermsstring[]In searchMessages["Telegram"]Up to 20 keywords or phrases, searched separately in every channel
maxMessagesintegerNo100Maximum 1-5,000 messages per channel, or per channel and term in search mode
maxConcurrencyintegerNo5Independent channels or channel-term pairs processed in parallel, from 1 to 20
afterMessageIdintegerNoExclusive global message-ID checkpoint used for incremental runs
afterMessageIdsobjectNoPer-channel exclusive checkpoints; values override afterMessageId
dateFromstringNo""Inclusive ISO 8601 start date or timestamp
dateTostringNo""Inclusive ISO 8601 end date or timestamp
includeServiceMessagesbooleanNotrueInclude channel service records when publicly visible
mediaModestringNourlsurls extracts public media metadata; none returns empty media fields
downloadMediabooleanNofalseStore public message media files in the run Key-value store; requires mediaMode: "urls"
maxMediaFilesintegerNo100Run-wide stored-file limit from 1 to 5,000
maxMediaSizeMbintegerNo25Maximum accepted size for one stored media file, from 1 to 100 MB

Use cases

Channel discovery and competitive research

Compare subscriber audiences, verification, content volume, posting recency, median views, reactions, and recent reaction-to-view rates before selecting channels for partnerships or research.

Brand and topic monitoring

Schedule searchMessages for product names, executives, campaign phrases, or industry terms. Send finished-run webhooks to Slack, Make, Zapier, or n8n.

Public content archives

Collect newest-first public posts with original timestamps, rich HTML, source links, media URLs, replies, forwards, and polls. Store recurring exports in a database or data warehouse.

Engagement and content analysis

Aggregate views, reactions, paid reactions, hashtags, external links, media types, and estimated engagement percentages in a spreadsheet or BI tool.

Editorial and research workflows

Search long-running channels for statements on a subject, retain direct message URLs for verification, and separate Telegram links from external sources.

Performance and cost

channelInfo normally needs one proxied page request per channel. Message modes fetch the first page and then approximately one additional request per public page of older messages. Pages are parsed and saved incrementally instead of retaining a complete channel history in memory. Independent operations run concurrently up to maxConcurrency; pagination inside one channel remains sequential to preserve Telegram's cursor and sticky proxy session.

Date ranges far in the past may require paging through newer posts before reaching the requested period. An afterMessageId checkpoint can stop as soon as already-seen history is reached. Search pagination is controlled by Telegram and may stop before maxMessages is reached.

Actual run cost depends on the Actor's current Store pricing, Apify platform usage, residential proxy traffic, dataset writes, number of channels, and number of pages visited. Check the Actor's Pricing tab before a large run. No fixed speed or cost is claimed until repeatable Apify production measurements are available.

WorkloadMain request patternCost consideration
Channel profilesAbout one public page per channelLowest request volume
Recent messagesInitial page plus older-message pagesIncreases with requested messages
Historical date rangePages newer than the range may also be visitedCan require substantially more proxy traffic
Keyword searchSeparate search and pagination for every channel-term pairMultiplies with channels and terms
Stored mediaOne proxied media download, KVS write, and media-file event per successful fileKeep disabled unless durable files are required

Pay-per-event billing

Only successfully delivered data is billed. Failed channels, retries, empty searches, logs, and RUN_SUMMARY are not billable dataset results.

EventCharged when
channel-infoOne public channel profile is successfully saved
messageOne regular channel-history message is successfully saved
search-resultOne native in-channel keyword match is successfully saved
media-fileOne optional public media file is successfully stored in the Key-value store

The Actor pricing configuration should not include error, apify-actor-start, or apify-default-dataset-item events. Check the Actor's Pricing tab for current tier prices before a large run.

API usage

Replace YOUR_USERNAME with the Actor owner's Apify username after publication.

curl -X POST \
"https://api.apify.com/v2/acts/YOUR_USERNAME~telegram-channel-scraper/runs?token=APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"mode": "searchMessages",
"channels": ["durov"],
"searchTerms": ["privacy"],
"maxMessages": 50
}'

Dataset results can be connected to Google Sheets, Make, Zapier, n8n, Airbyte, webhooks, Slack, or a data warehouse using standard Apify integrations.

Best for / not for

Best for: public broadcast channels, channel profile monitoring, public message archives, topic search, media-link collection, engagement research, and scheduled monitoring.

Not for: private channels, invite-only chats, group message history, member lists, authenticated Telegram search, direct messages, comment-body collection, deleted posts, real-time streaming, or exact unrounded Telegram metrics.

Limits and good to know

  • Only one mode runs at a time.
  • maxMessages is limited to 5,000 and applies per channel or per channel-term pair, not globally.
  • The source must expose a public https://t.me/s/username preview. Public groups usually show only a join page and are not scraped as message feeds.
  • Telegram decides how much public history and how many keyword matches are available. Deleted, restricted, age-gated, copyright-blocked, or unsupported posts may be absent.
  • dateFrom and dateTo filter message timestamps, but reaching an old date can require paging through newer history.
  • Telegram frequently displays K, M, or B counts. The Actor preserves the displayed value in *Raw, parses a numeric estimate, and marks rounded values with *Approximate.
  • Public CDN media URLs can contain temporary tokens and may expire. Download or process them promptly when needed.
  • mediaMode: none keeps the stable 60-field message shape but returns media: [], photoUrls: [], mediaStoreKeys: [], and null primary-media fields.
  • Missing optional source data is represented by null, false, 0, or an empty array according to field type; output fields are not silently removed.
  • Failed channels are written to logs and RUN_SUMMARY, not mixed into the user dataset. Other inputs continue. If every operation fails because of network, proxy, blocking, or parsing errors, the run fails after recording diagnostics.
  • All requests use built-in Apify Residential Proxy. Sticky sessions preserve continuity while paging through a channel; a new proxy session is selected after retryable errors. Direct Telegram traffic is disabled.
  • RUN_SUMMARY.nextAfterMessageIds contains reusable per-channel checkpoints based only on successfully saved messages.
  • Media downloads are optional, bounded by count and size, and may fail independently while the message row and original public URL remain available.

Frequently asked questions

What input should I provide?

Provide a public username such as durov, @durov, https://t.me/durov, or https://t.me/s/durov. Private invite links such as t.me/+... are rejected.

Do I need a Telegram account, phone number, bot token, or API credentials?

No. The Actor reads Telegram's public channel preview pages and does not sign in to Telegram.

How many messages can I extract?

You can request 1-5,000 messages per channel or channel-term pair. The actual result can be smaller when Telegram exposes less public history, a date range removes messages, a search has fewer matches, or posts were deleted.

Does keyword search scan downloaded text locally?

No. searchMessages uses Telegram's public within-channel search and follows its server-provided pagination. This keeps matches consistent with the public website but also inherits its availability limits.

Why do some numeric values have an approximate flag?

Telegram displays large public metrics in abbreviated form, such as 11.3M or 65.9K. The Actor cannot recover precision that the public page does not provide, so it returns the raw label, a parsed estimate, and an approximation flag.

Can it scrape comments or public groups?

Channel posts may expose a comment count and discussion URL. Comment bodies and public-group message history are not reliably available through Telegram's public /s/ channel pages and are not collected.

Can I process multiple channels and search terms?

Yes. Up to 100 channels can be processed in one run. Search mode accepts up to 20 terms and executes every channel-term combination independently.

Can I schedule recurring runs?

Yes. Use Apify schedules for recurring jobs and webhooks to notify another system when a run completes. Copy RUN_SUMMARY.nextAfterMessageIds into the next run's afterMessageIds to request only newer message IDs.

Can the Actor store Telegram media files?

Yes. Set downloadMedia: true with mediaMode: "urls". Successfully stored files appear in the run Key-value store, and their record keys are returned in media[].storeKey and mediaStoreKeys. File storage is bounded by maxMediaFiles and maxMediaSizeMb and is billed separately from message rows.

Where are failed inputs reported?

Failures are logged and summarized in the RUN_SUMMARY Key-value store record. They are deliberately excluded from the Results dataset so exported data contains only usable channel and message records.

Do I need to configure a proxy?

No proxy field is exposed. The Actor always creates and verifies an Apify Residential Proxy configuration internally and refuses to send direct traffic.

Responsible use

This Actor extracts publicly available Telegram channel information. Users are responsible for complying with applicable laws, privacy regulations, contractual obligations, and Telegram's terms. Avoid collecting or redistributing personal data without a lawful purpose.

Telegram is a trademark of its respective owner. This Actor is independent and is not affiliated with, endorsed by, or sponsored by Telegram.

Support

If you encounter a problem, create an issue in the Actor's Issues tab. Include the Apify run ID, the mode, a non-sensitive public channel input, and what you expected to receive. Do not post private invite links, credentials, tokens, or personal data.

Local development

pip install -r requirements.txt
python -m unittest discover -s tests -v
python -m my_actor

Local Actor execution still requires a working Apify Proxy configuration. The scraper intentionally has no direct-network fallback.