Telegram Channel Scraper — Posts API, Views & Media | $0.50/1k
Pricing
from $0.50 / 1,000 results
Telegram Channel Scraper — Posts API, Views & Media | $0.50/1k
Scrape public Telegram channels without login: posts with text, views, photos, videos, files, link previews, reactions and forwards, plus exact subscriber counts. Date range and keyword search. Export JSON, CSV or Excel.
Pricing
from $0.50 / 1,000 results
Rating
0.0
(0)
Developer
Raffy
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
What does Telegram Channel Scraper do?
Telegram Channel Scraper reads public Telegram channels and returns their posts (text, views, photos, videos, files, link previews, polls, reactions, forwards, replies, hashtags and links) plus one channel profile row per channel (title, description, exact subscriber count, photo, verified badge). It works as a simple Telegram channel API: give it channel usernames or t.me links and get clean JSON, CSV or Excel back in seconds. No Telegram account, no phone number, no API key, no browser.
Typical use cases:
- 📰 News and media monitoring: follow news, crypto, finance or politics channels in any language and pipe every new post into a spreadsheet, a database or an AI summariser.
- 📊 Channel analytics and benchmarking: compare subscribers, views, reactions and posting frequency across channels, or track them over time with a schedule.
- 🔎 Research and archiving: pull a channel's history for a date range, or search inside channels for a keyword across their whole history.
- 🤖 AI agents and RAG: give an agent a list of channels and get structured, self-describing rows it can reason over.
It reads only what Telegram shows logged-out on its public web preview (t.me/s/<channel>). It does not log in, join groups, or collect member lists, user profiles or phone numbers.
Why use this Telegram scraper?
- Fast. Pure HTTP, about 20 posts per request: 1,000 posts from one channel took 37 seconds and 20 channels × 60 posts took 9 seconds on Apify (real runs, 2026-09-28).
- Cheap. $0.50 per 1,000 results, Apify platform usage included.
- Deep history and date ranges. Pages back as far as you ask. With Posted before it jumps straight to that date by binary search instead of reading every newer page, so "December 2023 on a channel with 400,000 posts" takes about 15 requests.
- Keyword search inside channels. Uses Telegram's own in-channel search, so a keyword finds matching posts across the channel's whole history, not just the newest pages.
- Exact subscriber counts. The channel row reads the channel's profile card, which shows the exact number (10,608,845), not the rounded header figure (10.6M).
- Honest results. Every row carries a
status(ok,not_found,error). A group, a personal account, a bot or a private invite link comes back as one freenot_foundrow that says why. You are billed only forokrows. - Works from Apify's datacenter. In our test runs on Apify (2026-09-28) every one of 428 Telegram page requests succeeded on the first attempt, across 23 public channels in Russian, Arabic, Ukrainian and English, with no proxy.
What data can Telegram Channel Scraper extract?
Two row types share one dataset; type tells them apart.
Post rows (type = post)
| Field | Type | Description |
|---|---|---|
channel | string | Channel username without @ (the channel's primary username) |
channelTitle | string | Channel display name |
postId | integer | Post number in the channel; newer posts have higher numbers |
url | string | Link to the post, https://t.me/<channel>/<postId> |
postedAt | string | Publication time, ISO 8601 UTC |
text | string | Post text or caption as plain text (line breaks and emoji kept) |
textHtml | string | Optional (includeTextHtml): the text with bold, italic, code, quote, spoiler and link formatting |
views | integer | View count as Telegram shows it ("18.9M" becomes 18900000) |
reactions | array | { emoji, count } per reaction; custom emoji carry customEmojiId, paid Star reactions paid: true |
reactionsCount | integer | Sum of all reactions |
photos | array | Photo URLs (albums give several) |
videos | array | { thumbnailUrl, duration, durationSeconds, videoUrl } (videoUrl only for small videos Telegram serves in the preview) |
documents | array | Attached files and audio: { name, details, kind } |
linkPreview | object | The link card: { url, siteName, title, description, imageUrl } |
poll | object | { question, type, options: [{ text, percent }] } |
hashtags | array | Hashtags in the text |
mentions | array | @usernames linked in the text (usually other channels) |
links | array | Web links in the text |
isForwarded | boolean | The post was forwarded from somewhere else |
forwardedFrom | object | { channel, title, postUrl } when the source is a public channel post |
replyToPostId | integer | The earlier post in the same channel this post replies to |
isEdited | boolean | Telegram marks the post as edited |
searchKeyword | string | Which of your keywords found the post |
Channel rows (type = channel, one per channel when Add one channel profile row is on)
| Field | Type | Description |
|---|---|---|
channel, channelTitle, url | string | Username, display name and https://t.me/<channel> |
subscribers | integer | Exact subscriber count |
description | string | Channel description (bio) |
photoUrl | string | Profile photo |
verified | boolean | Telegram's verified badge |
photosCount, videosCount, filesCount, linksCount | integer | Media the channel has posted, as Telegram counts them |
Every row also has status, error and scrapedAt.
Result status (tri-state output)
status | Meaning | Billed? |
|---|---|---|
ok | A post or a channel profile was extracted. | Yes |
not_found | The name is not a public channel (a group, a person, a bot, a private invite link, a name nobody owns, or a channel whose preview is switched off), or no post matched your date range or keyword. error says which. | No |
error | Telegram could not be read after retries (network error, rate limit or a layout change). error says why. | No |
How to use the Telegram Channel Scraper
- Open the Actor in Apify Console and click Try for free.
- Put channels into Telegram channels, one per line:
durov,@bbcrussianorhttps://t.me/s/tass_agencyall work. - Choose Posts per channel (20 is one page). Optionally set Posted on or after / Posted before and Keywords.
- Click Start. The default input (2 channels, 20 posts each) finishes in about 10 seconds.
- Open the Output tab (views: Overview, Media and links, Channel profiles) or Export as JSON, CSV, Excel, XML or HTML.
To automate it, use the API tab (Node.js, Python, curl) or add a Schedule: a daily run with Posted on or after = 1 day gives you each day's new posts.
How much does it cost to scrape Telegram channels?
This Actor uses pay-per-event pricing. Apify platform usage is included in these prices.
| Event | Price |
|---|---|
| Actor start | $0.005 per run |
Result (status: ok row: a post or a channel profile) | $0.0005 per result ($0.50 per 1,000) |
Example: 1,000 posts in one run cost $0.505 ($0.50 for the rows plus $0.005 for the start). The default input (2 channels × 20 posts + 2 channel rows = 42 results) costs about $0.026. Rows with status not_found or error are never billed. Cap spending with Posts per channel, Maximum results and the run's Max total charge option; the Actor stops gracefully when your run's maximum charge is reached.
Input
See the Input tab for the full schema. The main options:
| Field | Type | Default | Description |
|---|---|---|---|
startUrls | array of strings | ["durov", "telegram"] | Channels: usernames, @names or t.me links |
maxPostsPerChannel | integer | 20 | Newest posts per channel (after filters) |
postedAfter | string | - | Only posts on or after: YYYY-MM-DD, ISO time, or 7 days |
postedBefore | string | - | Only posts before this moment (the Actor jumps there directly) |
keywords | array of strings | - | Search inside each channel with Telegram's own search |
includeChannelInfo | boolean | true | Add one channel profile row per channel |
includeTextHtml | boolean | false | Add textHtml with basic formatting |
maxItems | integer | 1000 | Safety cap on rows for the whole run |
proxyConfiguration | object | off | Not needed; datacenter proxy only if you hit HTTP 429 |
API callers may also send the channel list as channels.
Example input (news channels, one week, two keywords):
{"startUrls": ["bbcrussian", "@tass_agency", "https://t.me/s/ajanews"],"maxPostsPerChannel": 200,"postedAfter": "7 days","keywords": ["Путин", "Iran"],"includeChannelInfo": true}
Output
You can download the dataset as JSON, HTML, CSV or Excel. Real rows from a run on Apify (2026-09-28), long URLs shortened with …:
[{"url": "https://t.me/durov","status": "ok","scrapedAt": "2026-09-27T23:43:28.543Z","type": "channel","channel": "durov","channelTitle": "Pavel Durov","description": "Founder of Telegram.","subscribers": 10608845,"photoUrl": "https://cdn4.telesco.pe/file/OpC7B9qam6vvIGLzp…Wb0c5RZJMNAvo0zVC0LWKJJ68TA.jpg","verified": true,"photosCount": 102,"videosCount": 46,"linksCount": 200},{"url": "https://t.me/durov/548","status": "ok","scrapedAt": "2026-09-27T23:43:27.034Z","type": "post","channel": "durov","channelTitle": "Pavel Durov","postId": 548,"postedAt": "2026-09-11T16:04:02Z","text": "🤝 Telegram has become the sponsor of Codeforces — the largest competitive programming platform in the world.\n\n ⚡CodeForces organizes over 100 coding contests every year and has 4 million contestants signed up.\n\n…","views": 1690000,"isForwarded": false,"photos": [],"videos": [],"documents": [],"linkPreview": {"url": "https://codeforces.com/blog/entry/156620","siteName": "Codeforces","title": "Telegram Returns as Title Sponsor of Codeforces!","description": "Hi, Codeforces!","imageUrl": "https://cdn4.telesco.pe/file/pMiBhAOwyapnw…rnP1Q.jpg"},"hashtags": [],"mentions": [],"links": ["https://codeforces.com/blog/entry/156620"],"reactions": [{ "emoji": "⭐", "paid": true, "count": 13600 },{ "customEmojiId": "5399847211989246390", "count": 28700 },{ "customEmojiId": "5936157098181135162", "count": 8260 },{ "customEmojiId": "5373223594484587136", "count": 7760 }],"reactionsCount": 58320,"isEdited": false},{"url": "https://t.me/rt_russian","status": "not_found","error": "@rt_russian is a channel, but Telegram shows no public web preview for it (the owner switched it off, or it is restricted in the region the request came from). Only public channels whose preview opens at t.me/s/rt_russian are supported.","scrapedAt": "2026-09-27T23:43:28.187Z","type": "channel","channel": "rt_russian"}]
A missing field means Telegram did not show it for that post; it is never guessed.
Tips
- Put many channels in one run instead of one run per channel; you pay the start fee once and channels are read in parallel.
- For monitoring, schedule a run with Posted on or after =
1 day(or6 hours) and a generous Posts per channel; paging stops as soon as it reaches older posts. - Media URLs point at Telegram's CDN and are signed; download files you need soon after the run.
- If you read hundreds of channels at once and see HTTP 429
errorrows, enable Apify Proxy (datacenter) in Proxy configuration.
Limitations
- Public channels only. Telegram's web preview shows public channels; public groups, personal accounts, bots and private invite links return a free
not_foundrow. Comments under posts and member lists are not shown there and are not collected. - Some channels switch the preview off or are restricted in some regions; those return
not_foundwith that reason. - A username Telegram does not use for anything public can redirect to telegram.org. That drops the name from the answer, so the
not_foundrow says what happened but cannot name the input; the other rows of the run show which input it was. - View counts and some media counters are rounded the way Telegram displays them (for example 18.9M). The channel's subscriber count is exact.
- Stickers, voice messages, round videos and paid media show only what the preview shows (often a "view in Telegram" placeholder), so such posts may carry just their caption.
- Service messages (channel created, title changed, pinned message) are skipped. Whether a post is currently pinned is not visible in the preview.
- Keywords use Telegram's own search, which matches words (with its own stemming), so it can return posts where the word appears in a different form.
- Results reflect the preview at the time of the run; if Telegram changes its layout, rows come back as
errorand the Actor is updated (report it in the Issues tab).
FAQ
Do I need a Telegram account, phone number or API key?
No. The Actor reads the public web preview at t.me/s/<channel>, the same page anyone can open in a browser without logging in.
Can it scrape Telegram groups, members or users?
No. Only public channels' broadcast posts. A group, a user or a bot returns one free not_found row saying so. The Actor never collects member lists, user profiles or phone numbers, and it does not output post author signatures; a forward is named only when its source is a public channel.
How far back can it go?
As far as the channel's history goes. Posts per channel sets how many; Posted before jumps straight to a date, and Posted on or after stops paging once posts get older than that date.
How do I track new posts every day?
Create a Schedule with Posted on or after = 1 day. Each run returns only posts from the last day, so you pay only for new posts.
Why is a channel not_found?
The error column explains it: the name is a group, a person or a bot, it is not taken, it is a private invite link, or the channel's owner switched the web preview off (or it is restricted in the region the request came from).
Can I use this Actor from an AI agent or MCP client?
Yes. It runs with no input at all (two sample channels), inputs are plain strings, and every row is self-describing (type, status, error).
How fast is it?
About 20 posts per request. On Apify, 1,000 posts from one channel took 37 seconds, three channels × 1,000 posts took 82 seconds, and 20 channels × 60 posts took 9 seconds.
Legal and data-protection notice
This Actor extracts only what Telegram publishes on its public, logged-out channel preview. It does not log in, join chats or get around access controls, and it does not extract private user data such as member lists, user profiles, phone numbers or post author signatures. However, public posts can still contain personal data, for example names mentioned in a news story. Personal data is protected by the GDPR in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you are unsure whether your reason is legitimate, consult your lawyers. You are responsible for complying with Telegram's terms of service and applicable law when using the extracted data.
This Actor is an independent tool and is not affiliated with, endorsed by or sponsored by Telegram or its owners. Telegram is a trademark of its respective owner.