Telegram Channel Scraper: Messages & Search
Pricing
from $0.48 / 1,000 channel messages
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
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
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 / action | Input | Output | Best for |
|---|---|---|---|
channelInfo | Public channel usernames or URLs | One profile and recent-analytics row per channel | Channel discovery, audience sizing, and monitoring |
messages | Public channels, message limit, optional date range | Public messages in newest-first order | Content archives, media research, and engagement analysis |
searchMessages | Public channels and search terms | Messages matched by Telegram's channel search | Topic 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
- Open the Actor and click Try for free.
- Keep
channelInfoselected and enter a public channel such asdurov. - Add more usernames,
@usernames, ort.meURLs if needed. - Click Start.
- 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?
| Category | Fields |
|---|---|
| Row identity | recordType, scrapedAt |
| Channel identity | channelId, username, title, channelUrl, previewUrl, description, avatarUrl, verified, available |
| Channel audience and content counters | subscriberCount, subscriberCountRaw, subscriberCountApproximate, photoCount, photoCountRaw, photoCountApproximate, videoCount, videoCountRaw, videoCountApproximate, linkCount, linkCountRaw, linkCountApproximate |
| Recent channel analytics | latestMessageId, latestMessageDate, recentPostsSampleSize, recentAverageViews, recentMedianViews, recentAverageReactions, recentEngagementRatePercent |
| Message context | channelUsername, channelTitle, channelSubscriberCount, channelSubscriberCountRaw, messageId, messageUrl, date, displayedTime, searchTerm, searchRank |
| Message content and authorship | text, textHtml, isEdited, isService, serviceText, authorName, authorUrl, authorAvatarUrl, authorSignature |
| Views and engagement | views, viewsRaw, viewsApproximate, reactions, totalReactions, paidReactions, reactionsApproximate, estimatedEngagementRatePercent, estimatedViewsPerSubscriberPercent |
| Entities and links | urls, externalUrls, telegramUrls, mentions, hashtags, customEmojis, linkPreview |
| Media | mediaType, media, mediaCount, isAlbum, hasUnsupportedMedia, photoUrls, videoUrl, videoThumbnailUrl, videoDurationSeconds, mediaWidth, mediaHeight, mediaAspectRatio, mediaStoredCount, mediaStoreKeys |
| Message relationships | forwardedFrom, 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
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
mode | string | Yes | channelInfo | channelInfo, messages, or searchMessages |
channels | string[] | Yes | ["durov"] | Up to 100 public usernames, @usernames, t.me/name, or t.me/s/name URLs |
searchTerms | string[] | In searchMessages | ["Telegram"] | Up to 20 keywords or phrases, searched separately in every channel |
maxMessages | integer | No | 100 | Maximum 1-5,000 messages per channel, or per channel and term in search mode |
maxConcurrency | integer | No | 5 | Independent channels or channel-term pairs processed in parallel, from 1 to 20 |
afterMessageId | integer | No | — | Exclusive global message-ID checkpoint used for incremental runs |
afterMessageIds | object | No | — | Per-channel exclusive checkpoints; values override afterMessageId |
dateFrom | string | No | "" | Inclusive ISO 8601 start date or timestamp |
dateTo | string | No | "" | Inclusive ISO 8601 end date or timestamp |
includeServiceMessages | boolean | No | true | Include channel service records when publicly visible |
mediaMode | string | No | urls | urls extracts public media metadata; none returns empty media fields |
downloadMedia | boolean | No | false | Store public message media files in the run Key-value store; requires mediaMode: "urls" |
maxMediaFiles | integer | No | 100 | Run-wide stored-file limit from 1 to 5,000 |
maxMediaSizeMb | integer | No | 25 | Maximum 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.
| Workload | Main request pattern | Cost consideration |
|---|---|---|
| Channel profiles | About one public page per channel | Lowest request volume |
| Recent messages | Initial page plus older-message pages | Increases with requested messages |
| Historical date range | Pages newer than the range may also be visited | Can require substantially more proxy traffic |
| Keyword search | Separate search and pagination for every channel-term pair | Multiplies with channels and terms |
| Stored media | One proxied media download, KVS write, and media-file event per successful file | Keep 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.
| Event | Charged when |
|---|---|
channel-info | One public channel profile is successfully saved |
message | One regular channel-history message is successfully saved |
search-result | One native in-channel keyword match is successfully saved |
media-file | One 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.
maxMessagesis 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/usernamepreview. 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.
dateFromanddateTofilter message timestamps, but reaching an old date can require paging through newer history.- Telegram frequently displays
K,M, orBcounts. 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: nonekeeps the stable 60-field message shape but returnsmedia: [],photoUrls: [],mediaStoreKeys: [], andnullprimary-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.nextAfterMessageIdscontains 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.txtpython -m unittest discover -s tests -vpython -m my_actor
Local Actor execution still requires a working Apify Proxy configuration. The scraper intentionally has no direct-network fallback.