Telegram Channel Scraper: Posts + Media + Metadata
Pricing
from $10.00 / 1,000 posts
Telegram Channel Scraper: Posts + Media + Metadata
Get posts from any public Telegram channel in minutes, no API key or phone number needed. Paste up to 25 channels and get clean JSON: text, views, reactions, forwards, hashtags, mentions, links, plus photos and videos to download. No monthly fee, pay only for posts you get.
Pricing
from $10.00 / 1,000 posts
Rating
5.0
(1)
Developer
Olga
Maintained by CommunityActor stats
6
Bookmarked
219
Total users
7
Monthly active users
2 days ago
Last modified
Categories
Share
📦 Telegram Channel Scraper: Posts + Media + Metadata
Extract channel metadata, recent posts, views, reactions, forwards, hashtags, mentions, replies, and all media with direct download links. This actor scrapes structured content from public Telegram channels using the Telegram API via a pre-authorized session string — no setup required from you.
🆕 Updated on September 28, 2026: up to 25 channels per run, fewer Telegram rate limits, clear run status and a run summary — live now.
💰 Since October 12, 2026: no monthly fee. You pay only for the posts you get. Errors, queue time and service records are free. Details below in Pricing.
🆕 Update (2026-09-28)
- ✅ Channels are remembered between runs — channels you've scraped before no longer need a Telegram username lookup (the thing that causes 10-hour FloodWait limits). Repeat monitoring of the same channels is faster and much safer
- ✅ Up to 25 channels per run (was 10) — of them, up to 10 new channels; previously scraped channels don't count toward that limit
- ✅ Rate limits no longer stop the whole run — if Telegram limits lookups of new channels, only new channels are skipped; channels you've scraped before keep working
- ✅ Clear run status — while waiting in the queue you see how long you've been waiting; at the end you see a summary: posts collected, media files downloaded, which channels were not processed and why
- ✅
RUN_SUMMARYrecord in the run's Key-Value Store — handy for API and automation users - ✅
typefield on every record —postfor content, other values for service messages (see Output), so you can filter them out easily - ✅
t.melinks accepted —https://t.me/channel,https://t.me/s/channel,t.me/channel/123; channels can be separated by commas or new lines - ✅ Optional album merging (
groupAlbums) — merge an album into one record with all its files - ✅
maxMediaSizeMB— files larger than the limit stay as links instead of being downloaded - ✅ Link previews are no longer treated as media —
hasMedianow means real photos, videos or files
Nothing changes in the default output: without the new options, you get the same records as before, plus the type and groupedPostIds fields.
💰 Pricing — pay only for what you get
📢 Since October 12, 2026, there is no monthly fee. Apify is retiring monthly rentals, so the former $9/month rental has been replaced by pay-per-event pricing: you pay only for the posts and files you get. If you scrape fewer than ~900 posts a month, this is cheaper than before.
| What | Price |
|---|---|
| Run start (charged only after a successful connection to Telegram) | $0.01 |
| Post | $10.00 / 1,000 posts |
Downloaded media file (only when downloadMedia is on) | $5.00 / 1,000 files |
| Platform usage | Included |
You are never charged for:
- time in the queue, queue timeouts, or failed connections to Telegram;
- service records — "no posts found", channel errors, rate-limit notices, skipped channels;
- media left as a link (files over
maxMediaSizeMB, or whendownloadMediais off).
Control your spending: set Max cost per run in the run options — the Actor stops cleanly when the limit is reached.
Examples
- 10 channels × 20 posts, text only → $0.01 + 200 × $0.01 = $2.01
- 5 channels × 50 posts, 120 media files downloaded → $0.01 + $2.50 + $0.60 = $3.11
✅ What This Actor Does
- Connects to Telegram automatically (no credentials needed from your side)
- Parses public channels (by username or
t.melink) - Retrieves for each channel:
- Channel metadata: display title, description (about), subscriber count
- Posts: text, date, post URL, views, reactions (with emoji breakdown + total)
- Forwards: detects native Telegram forwards and exposes the source (
isForward,forwardFromType,forwardFromId,forwardFromName,forwardChannelPost,forwardPostAuthor,forwardDate) - Hashtags & mentions: extracted from post text (Unicode-aware — supports Cyrillic, e.g.
#вакансия,#Менеджер_по_продажам) - Edit metadata:
editDateif the post was edited - Reply chain:
replyToMsgIdandreplyToPostUrlfor posts that reply to another post - Links: all URLs found in the post text
- Media: photos, videos, documents — with direct downloadable URLs (
.jpg,.mp4,.pdf, etc.) andmediaTypes
- Handles:
- Text-only and media-only messages
- Albums — one record per message by default, or one record per album with
groupAlbums - Telegram FloodWait limits gracefully (with explanatory record in the dataset)
- Cross-run conflicts via a per-session queue (see "Queue Behavior" below)
- Skips:
- Empty service messages, outdated posts beyond
daysRange
- Empty service messages, outdated posts beyond
- Starts from the most recent post and works backwards
🧾 Input
You don't need to enter any credentials — they're already preconfigured.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
channels | string | ✅ | — | Channel usernames or links, separated by commas or new lines (e.g. @channel1, https://t.me/channel2) |
maxPosts | number | ❌ | 10 | Max number of Telegram messages per channel (1–200) |
daysRange | number | ❌ | 3 | Number of days to look back from today (1–30) |
includeText | boolean | ❌ | true | Whether to include post text in the output |
mediaOnly | boolean | ❌ | false | If true, skip posts that have no photos, videos or files |
downloadMedia | boolean | ❌ | false | If true, download media files into the run's Key-Value Store |
maxMediaSizeMB | number | ❌ | 50 | Files larger than this stay as t.me links (not downloaded). 0 = no limit |
groupAlbums | boolean | ❌ | false | If true, merge an album into one record: all files in mediaUrls, all message ids in groupedPostIds. With merging on you may get fewer records than maxPosts, because maxPosts counts Telegram messages |
📌 Example input
{"channels": "@channel1, https://t.me/channel2, channel3","maxPosts": 10,"daysRange": 3,"includeText": true,"mediaOnly": false,"downloadMedia": true,"maxMediaSizeMB": 50,"groupAlbums": false}
⚠️ Channel limits per run. Up to 25 channels per run, of which up to 10 new channels (not scraped by this Actor before). Previously scraped channels are remembered and don't need a Telegram lookup, so they don't count toward the 10. Channels over the limit are listed in the run status and saved as
type: "skipped"records — just run them again.
▶️ How to Run
- Open the actor in Apify Console
- Fill in the input fields
- Click Save, then Run
- Watch the run status — it shows queue waiting time, progress, and a final summary
- Results are available in:
- Dataset — all posts and channel metadata as JSON records
- Key-Value Store — downloaded media files (when
downloadMedia: true) andRUN_SUMMARY
📤 Output
Each Telegram message (or each album, with groupAlbums: true) is saved as a separate record in the default dataset (JSON format). Every record has a type field:
type | Meaning | Charged |
|---|---|---|
post | A post with content | ✅ |
no_posts | Channel has no posts in the selected period | ❌ |
skipped | Channel postponed (per-run limit or temporary Telegram limit) — run it again | ❌ |
telegram_rate_limit | Telegram asked to slow down; includes waitSeconds | ❌ |
channel_error | Channel not found, private, or another error | ❌ |
To get only content, filter by type = "post".
{"type": "post","channel": "@channel_name","channelLink": "https://t.me/channel_name","channelTitle": "Channel Display Name","channelDescription": "Channel about / bio text","postId": 101,"postUrl": "https://t.me/channel_name/101","date": "2026-09-28T17:38:00.000Z","views": 3456,"subscribers": 12345,"text": "Example post content with #hashtag and @mention","reactions": [{ "emoji": "👍", "count": 42 },{ "emoji": "❤️", "count": 18 }],"totalReactions": 60,"links": ["https://example.com"],"hasMedia": true,"mediaUrls": ["https://api.apify.com/v2/key-value-stores/<storeId>/records/channel_name_101.jpg?disableRedirect=1"],"mediaTypes": ["jpg"],"groupedPostIds": [101],"isForward": false,"forwardFromType": "","forwardFromId": "","forwardFromName": "","forwardChannelPost": 0,"forwardPostAuthor": "","forwardDate": "","hashtags": ["#hashtag"],"mentions": ["@mention"],"editDate": "","replyToMsgId": 0,"replyToPostUrl": ""}
For forwarded posts, isForward: true and the forward* fields are populated:
{"isForward": true,"forwardFromType": "channel","forwardFromId": "1009232144","forwardFromName": "","forwardChannelPost": 181471,"forwardPostAuthor": "","forwardDate": "2026-04-27T15:06:48.000Z"}
RUN_SUMMARY (in the run's Key-Value Store):
{"posts": 48,"channelsProcessed": 5,"mediaDownloaded": 31,"mediaSkippedLarge": 1,"postponedChannels": [],"failedChannels": [],"costLimitReached": false}
⏳ Queue Behavior (Important for parallel users)
The actor uses a shared Telegram session preconfigured by the author. Telegram allows only one active connection per session at any time — if multiple users run the actor simultaneously, the second connection would get AUTH_KEY_DUPLICATED.
To prevent this, the actor uses a cross-run lock: parallel runs are automatically queued and processed one at a time.
What this means in practice:
- If no one else is running the actor → starts immediately
- If another user is currently scraping → your run waits in queue, and the run status shows how long you've been waiting
- A typical wait is a few minutes (depends on what the previous run is doing)
- Maximum queue wait is 15 minutes, after which the run fails with a clear message
🛡️ Telegram Rate Limit Handling
If Telegram returns a FloodWait on contacts.ResolveUsername (too many lookups of new channel usernames in a short period), the actor:
- Stops looking up new channels for the rest of this run, to protect the session
- Keeps processing channels you've scraped before — they don't need a lookup
- Adds a
telegram_rate_limitrecord with the wait duration (waitSeconds) and a clear explanation - Retry the skipped channels after the indicated time (often 10–11 hours)
For any other very long FloodWait (1 hour or more), the run stops early to protect the session and reports it in the dataset and run status.
🛠 Use Cases
- Competitive content monitoring
- Telegram market research
- Dataset building for AI/ML models (with hashtags + mentions for labels)
- Public media archiving
- Social listening and trend analysis
- News aggregation and curation
- Forward chain analysis (track which posts get republished)
📜 Changelog
2026-10-12
- ✅ Pay-per-event pricing is live: no monthly fee — $0.01 per run start, $10 per 1,000 posts, $5 per 1,000 downloaded media files
- ✅ Queue waits, failed connections and service records are free
2026-09-28
- ✅ Pay-per-event pricing announced, effective 2026-10-12 (no monthly fee; service records, queue waits and failed connections will be free)
- ✅ Channel cache: previously scraped channels skip
contacts.ResolveUsername(the main cause of FloodWait); each channel is now resolved once per run instead of twice - ✅ Up to 25 channels per run, max 10 new ones; channels over the limit are reported as
type: "skipped"instead of being silently dropped - ✅ FloodWait on new-channel lookups no longer stops already-known channels
- ✅ Run status messages: queue waiting time, progress per channel, final summary
- ✅
RUN_SUMMARYrecord in the Key-Value Store - ✅
typefield on every record (post,no_posts,skipped,telegram_rate_limit,channel_error) - ✅
channelsacceptst.melinks (incl./s/and post links) and new-line separation; duplicates removed - ✅ New
groupAlbumsoption (off by default) andgroupedPostIdsfield - ✅ New
maxMediaSizeMBoption (default 50 MB) - ✅ Link previews no longer counted as media (
hasMedia,mediaUrls) - ✅ Respects the Max cost per run limit
- ✅ Clearer error messages for invalid, private and non-channel usernames
2026-05-03
- ✅ Added channel metadata (
channelTitle,channelDescription) - ✅ Added forwards detection (7 new
forward*fields) - ✅ Added hashtags + mentions extraction
- ✅ Added
editDateand reply chain fields (replyToMsgId,replyToPostUrl) - ✅ Cross-run lock now uses author-scoped Apify token, so the queue works for all users (not only the actor owner)
- ✅ Replaced silent exit handling with explicit
Actor.fail()so errors are visible in run status - ✅ Added 15-second timeout on Telegram
getMe()to prevent multi-minute hangs on dead sessions - ✅ Disabled
autoReconnectto fail fast and surface real errors
2025-12-05
- ✅ Added explicit handling and logging for Telegram
contacts.ResolveUsernameFloodWait errors - ✅ When Telegram returns a FloodWait, the actor now stops processing further channels in that run and adds a
telegram_rate_limitrecord to the dataset with a human-readable explanation - ✅ Limited the number of channels processed per run to 10 to reduce the risk of hitting global FloodWait on the shared Telegram session
- ✅ Updated input description to recommend no more than 10 channels per run and documented this behavior in the README
2025-10-10
- ✅ Fixed
AUTH_KEY_DUPLICATEDby adding a per-session lock (prevents concurrent reuse of the same Telegram auth key) - ✅ Improved error messages for session conflicts
- ✅ Internal stability tweaks for Telegram requests and media downloads
❓ Troubleshooting
Empty results / type: "no_posts"
- Increase
daysRangeto7..14— the channel may not have posts in the default 3-day window - Increase
maxPoststo20..50 - Make sure the channel is public and the username is correct
type: "skipped" records / channels "not processed" in the run status
- The run hit the per-run channel limits — run again with just those channels
type: "channel_error"
- The channel may be private, deleted, a user or bot rather than a channel, or an invite link (
t.me/+...), which isn't supported
Run waits 5+ minutes in queue
- Another user is currently using the actor; this is normal under load
- Retry in a few minutes when the queue clears
telegram_rate_limit record in dataset
- Telegram applied a FloodWait — wait the indicated number of hours before retrying the skipped channels
- Channels you've scraped before are not affected
Run failed with AUTH_KEY_DUPLICATED
- Should not happen with the built-in queue, but if it does — wait 10 minutes and retry
⚠️ Telegram Albums
Telegram delivers an album (several photos/videos with one caption) as several separate messages, one file each, with the caption on one of them.
By default (groupAlbums: false) the actor returns them as Telegram delivers them — one record per message. They share the same date and have consecutive postId values.
With groupAlbums: true the actor merges them into one record:
text— the album's captionmediaUrls/mediaTypes— all files of the albumgroupedPostIds— ids of all messages in the albumpostId/postUrl— the first message of the album
🔐 License & Usage
This actor is a proprietary paid product.
- ❗ It is not open source
- 📦 It is licensed for private and commercial use by users of this Actor
- 🛑 Any unauthorized copying, reselling, or redistribution is strictly prohibited
- 🧑💻 All activity is logged for abuse prevention and fair use enforcement
To report a bug, please open an issue — I respond quickly.
Made with 💙 for Telegram research & automation.