Telegram Channel Scraper — Posts, Views, Media avatar

Telegram Channel Scraper — Posts, Views, Media

Pricing

from $0.90 / 1,000 posts

Go to Apify Store
Telegram Channel Scraper — Posts, Views, Media

Telegram Channel Scraper — Posts, Views, Media

Public Telegram channel posts with date, text, views, reactions, forwards, replies, media links and channel info. Date range, Arabic-safe keyword filter and a new-posts-only alert mode. No login or API key. Status per channel; channel rows are free.

Pricing

from $0.90 / 1,000 posts

Rating

0.0

(0)

Developer

Dottti

Dottti

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Categories

Share

Telegram Channel Scraper: Posts, Views, Media

Get posts from public Telegram channels in one run. Each post comes with its date, full text, views, reactions, links, hashtags, mentions, forward and reply details, and media links. Each channel also gets one free row with its title, description, exact subscriber count and photo.

The actor reads the public web preview of a channel (t.me/s/<channel>). This is the same page anyone can open in a browser. You need no Telegram account, no phone number and no API key.

Who uses it

  • OSINT and research analysts who archive what public channels post, with dates and post links they can cite.
  • News and crisis monitoring teams who follow Arabic and English news channels and filter by keyword.
  • Crypto and market watchers who track announcement channels and want an alert when a new post appears.
  • Marketers who compare views, reactions and posting rhythm across channels.
  • AI and data pipelines that need clean post text in JSON, with Arabic and other right-to-left text kept exactly as posted.

What you can do

  • Read one or many channels. Paste usernames (durov), @names or links (https://t.me/bbcarabic, https://t.me/s/durov).
  • Limit each channel to the newest N posts.
  • Pick a date range. When the end date is in the past, the actor jumps straight to it with a few requests.
  • Keep only posts with your keywords. You choose whether a post needs any keyword or all of them.
  • Turn on alert mode. Later runs then return only posts published since the last run.
  • Leave media links on or off. Media type and count are always included.

Input examples

The newest 50 posts from two channels:

{
"channels": ["durov", "https://t.me/bbcarabic"],
"maxPostsPerChannel": 50
}

Arabic news about two topics in October 2026:

{
"channels": ["ajanews", "alarabiya", "bbcarabic"],
"keywords": ["غزة", "إسرائيل"],
"keywordMode": "any",
"dateFrom": "2026-10-01",
"dateTo": "2026-10-31",
"maxPostsPerChannel": 500
}

Alert mode for a schedule:

{
"channels": ["insiderpaper", "ajanews"],
"onlyNew": true,
"stateName": "news-watch",
"maxPostsPerChannel": 100
}

Output

Every row has a type field.

typeOne row isCharged
postOne channel postYes
channelOne input channel: its info and its statusNo

Post row (real output, 2026-10-21)

{
"type": "post",
"channel": "AjaNews",
"id": 517920,
"url": "https://t.me/AjaNews/517920",
"date": "2026-10-21T14:15:31.000Z",
"text": "عاجل | المتحدث باسم الحكومة العراقية: ننفي وجود مقرات للحوثيين في #العراق ولن نسمح باستخدام أراضينا لتهديد دول الجوار",
"textLength": 117,
"hashtags": ["#العراق"],
"mentions": [],
"links": [],
"views": 1320,
"viewsText": "1.32K",
"author": null,
"edited": false,
"forwardedFrom": null,
"replyTo": null,
"mediaType": "none",
"media": [],
"mediaCount": 0,
"linkPreview": null,
"poll": null,
"reactions": [],
"isService": false
}

A post with a photo and reactions (real output, some fields left out, media URL shortened):

{
"type": "post",
"channel": "insiderpaper",
"id": 45415,
"url": "https://t.me/insiderpaper/45415",
"date": "2026-10-21T13:42:13.000Z",
"text": "ALERT - Multiple websites worldwide could go dark as critical PHP flaws spark global cyber alert\n\nREAD: https://insiderpaper.com/critical-php-flaws-websites-down/",
"links": ["https://insiderpaper.com/critical-php-flaws-websites-down/"],
"views": 2260,
"viewsText": "2.26K",
"mediaType": "photo",
"media": [{ "type": "photo", "url": "https://cdn4.telesco.pe/file/jdJIaVWXKbJd4UNbfy5K5zmLkC4OJOg...", "postUrl": "https://t.me/insiderpaper/45415" }],
"mediaCount": 1,
"reactions": [
{ "emoji": "🔥", "count": 22, "countText": "22" },
{ "emoji": "🤡", "count": 13, "countText": "13" }
]
}

An album of 10 photos is one post row with mediaType: "album_photo" and 10 items in media. Each item has its own postUrl.

Paid star reactions look like {"emoji": "⭐", "paid": true, "count": 6000}. Custom emoji reactions have no character on the page, so they carry customEmojiId instead of emoji.

Channel row (real output, free)

{
"type": "channel",
"input": "ajanews",
"status": "ok",
"username": "AjaNews",
"url": "https://t.me/AjaNews",
"title": "قناة الجزيرة",
"description": "الحساب الرسمي لقناة الجزيرة على تيليغرام",
"subscribers": 1308166,
"subscribersExact": true,
"subscribersText": "1.31M",
"photoUrl": "https://cdn4.telesco.pe/file/FIcDDmiGCKqhOIl8CqK42p4zQ4Hw4Zd...",
"verified": true,
"kind": "channel",
"counters": { "photos": 508, "videos": 220, "files": 9, "links": 9490 },
"postsDelivered": 100,
"pagesFetched": 5,
"stopReason": "max_posts",
"error": null,
"charged": false
}

Post fields

FieldMeaning
id, urlPost number in the channel and its public link
datePublish time, ISO 8601 in UTC
textFull post text. Line breaks are kept. Emoji are kept as characters.
hashtags, mentions, linksPulled from the text. Hashtags work in Arabic and other scripts.
views, viewsTextTelegram rounds large counts on the page ("5.83M"). views is that number as an integer; viewsText is the original.
authorThe signature shown on the post, when the channel signs posts
editedTrue when the page marks the post as edited
forwardedFromName, username and post link of the source. hidden: true means Telegram shows a forward with no source name.
replyToThe post this one replies to: id, link, author and a short text preview
mediaTypenone, photo, video, gif, round_video, voice, audio, document, sticker, location, poll, link_preview, album_photo, album_video, album or unsupported
mediaOne item per photo, video or file: URL, thumbnail, duration, file name and size when the page shows them
linkPreviewSite name, title, description and image of a shared link
pollQuestion, options and percentages, when the page shows a poll
reactionsEach reaction with its count
isServiceNotes like "Channel photo updated". These are skipped unless you turn them on.

Channel status values

A bad channel never stops the run. Every input gets one free channel row with a status:

  • ok: posts were read.
  • not_found: Telegram has no public chat with this username.
  • private: the input is an invite link (t.me/+...). Private chats need a login, so the actor does not read them.
  • no_preview: the chat exists, but Telegram shows no web preview for it. Public groups are in this case.
  • not_channel: the username belongs to a user or a bot.
  • invalid_input: the text is not a Telegram username or link.
  • blocked: Telegram refused every retry and every proxy tier.
  • cut_by_cost_limit or skipped_cost_limit: your maximum cost for the run was reached.

stopReason says why a channel ended: max_posts, reached_from_date, reached_last_seen, end_of_channel, max_pages or cost_limit.

The RUN_SUMMARY record in the key-value store lists every channel with its status, pages read and timing. It also lists the requests made, status codes, retries, the proxy tier used and the bytes downloaded per 1,000 posts.

Keyword filter and Arabic text

Keywords are case-insensitive. The filter searches the post text, the link preview title and description, poll text and file names.

For Arabic, the filter ignores diacritics (harakat) and tatweel. It treats these letters as the same: أ إ آ ا, ى ي, ة ه, ؤ و, ئ ي. Arabic-Indic digits match Western digits. So افريقيا finds أفريقيا, and العربية finds الْعَرَبِيَّةُ.

The output text is never changed. Normalizing is only used to compare.

Posts that fail the filter are skipped and free. A rare keyword can mean many pages are read for few matches. maxPagesPerChannel (default 50 pages, about 1,000 posts) caps that scan.

Dates

  • dateFrom and dateTo take YYYY-MM-DD (UTC), a full ISO time, or a relative value such as 7 days or 12 hours.
  • A date-only dateTo includes that whole UTC day.
  • Newest posts come first. The walk stops at the first post older than dateFrom.

Alerts on a schedule

  1. Turn on onlyNew and give the list a stateName.
  2. The first run returns the newest posts as a baseline and saves the last post id per channel.
  3. Each later run returns only posts newer than the saved id. These rows have isNew: true. Their channel row has alert: "new_posts".
  4. New posts come oldest first, so if a cost limit cuts the run, the next run picks up right after the last delivered post.
  5. If more than maxPostsPerChannel posts arrived between two runs, only the newest that many are returned.

State lives in the named key-value store telegram-channels-state, under STATE-<stateName>. Use different names for different lists.

To schedule it, open the actor in Apify Console, save your input as a task, then add a schedule to the task. Every 15 minutes or every hour works for news and announcement channels. When nothing is new, the run outputs only the free channel rows and you pay nothing for posts.

Pricing

You pay per post row: $0.90 per 1,000 posts ($0.0009 per post).

  • Channel info rows are free.
  • Status rows for channels that return nothing are free.
  • Posts removed by your keyword or date filters are free.
  • Set a maximum cost per run in Apify. The actor stops cleanly at that limit and marks the channels it could not finish.

Platform usage is included in the price.

Speed and limits

Measured on 2026-10-21 from a home connection, no proxy, 256 MB memory:

RunPostsRequestsTimeDownloaded
Empty input (default channel)2021.2 s25 KB
English, 200 posts200138 s269 KB
Arabic news, 200 posts200116.5 s94 KB
Media-heavy, 200 posts200137.7 s149 KB
News channel, 975 posts9755130.6 s794 KB
5 channels mixed, 100 each4003017.5 s384 KB
Date range in 2020, 2 channels481611.4 s321 KB
  • One preview page holds about 20 posts. The actor waits about 0.6 seconds between requests across all channels, to stay polite. Expect about 30 seconds per 1,000 posts.
  • Telegram rounds view, reaction and subscriber counts on the preview page. The exact subscriber count comes from one extra small request per channel. Turn off exactChannelInfo to skip it.
  • Media URLs point to Telegram's CDN. They are signed and expire after some hours. Download what you need soon after the run.
  • Some media shows only "Please open Telegram to view this post" on the web. The post row is still output, with mediaType: "unsupported" or a note on the media item.
  • Some channels deleted most of their history. The preview then ends early and stopReason is end_of_channel.
  • The public preview leaves out comments under posts, member lists and private chats. The actor collects none of these.
  • Proxy: requests start with no proxy. If Telegram keeps answering 429 or errors, the actor moves to Apify datacenter proxy, then residential. In our tests no proxy was needed.

Privacy

The actor reads only what the public web preview shows to any visitor. It never logs in, joins chats, reads member lists or looks up phone numbers. You are responsible for using the data in line with the laws that apply to you, such as GDPR or Saudi PDPL when posts name people.

Input reference

FieldDefaultWhat it does
channels["telegram"]Usernames or links
maxPostsPerChannel20Posts kept per channel, after filters
dateFrom, dateToemptyDate window
keywordsemptyKeep only posts with these words
keywordModeanyany or all
includeMediatrueAdd media URLs
includeServiceMessagesfalseKeep notes like "Channel photo updated"
maxPagesPerChannel50Scan cap when filters are on (about 20 posts per page)
exactChannelInfotrueOne extra request for the exact subscriber count
onlyNewfalseAlert mode
stateNamedefaultSeparate memory per alert list
proxyConfigurationoffYour own proxy; turns the fallback off
autoProxyFallbacktrueNo proxy, then datacenter, then residential
allowResidentialFallbacktrueAllow the residential step
maxConcurrency2Channels read in parallel