Telegram Channel Scraper: Messages, Views, Media, No Login avatar

Telegram Channel Scraper: Messages, Views, Media, No Login

Pricing

from $2.00 / 1,000 results

Go to Apify Store
Telegram Channel Scraper: Messages, Views, Media, No Login

Telegram Channel Scraper: Messages, Views, Media, No Login

Scrape messages from public Telegram channels with no login, phone number or API key. Export posts with text, date, views, reactions, media links, polls, replies and forward sources, plus subscriber counts. Keyword and date filters for OSINT, news and crypto monitoring.

Pricing

from $2.00 / 1,000 results

Rating

0.0

(0)

Developer

Michal Pšenčík

Michal Pšenčík

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

17 days ago

Last modified

Share

Telegram Channel Scraper exports the messages of any public Telegram channel to JSON, CSV or Excel. For every post you get the text, the exact posting time in UTC, the view count, reactions, photo, video and voice-note links, poll results, the post it replies to, the channel it was forwarded from, and a link back to the post. Each channel also gets one record with its title, description and subscriber count.

No Telegram account, no phone number, no API key, no api_id, no bot token. The Actor reads Telegram's own public web preview at t.me/s/<channel>, the page anyone can open in a browser, so there is nothing to log in to, no session file to keep alive and no account to get banned.

Try it now: leave the Input tab at its defaults and press Start to get the latest posts from @telegram and @durov in a few seconds.

Why use this Telegram scraper?

  • Zero credentials. Paste channel usernames or t.me links and run. Nothing to register at my.telegram.org, no SIM, no 2FA.
  • $2 per 1,000 posts, platform usage included. Plus $0.005 per run. No subscription, no rental, no separate compute bill. See pricing for worked examples.
  • Pay only for matching posts. The keyword filter runs before anything is saved, so a monitoring run over thousands of messages bills only the handful that mention your terms.
  • Everything the public preview shows. Views as integers, reactions with counts (custom emoji and paid Telegram Stars included), poll questions with vote shares, reply chains, forward sources, link preview cards, file names and sizes, author signatures and the edited flag.
  • Only new posts on a schedule. Turn on onlyNewPosts and each scheduled run returns, and bills, only the posts published since the previous one.
  • Private channels handled cleanly. A channel without a public preview is reported in the log and the run's status message and skipped; the rest of the run carries on.
  • Stable keys for reruns. postId (channel/messageId) never changes, so scheduled runs upsert cleanly and you can track a post's views over time.

What data can you extract from Telegram?

FieldExampleWhat it is
channeldurovChannel username, without the @
messageId546Telegram's post number inside the channel
postIddurov/546Unique, stable key for the post
urlhttps://t.me/durov/546Link to the post
date2026-08-31T16:30:15.000ZPosting time, ISO 8601 in UTC
textGram Wallet in Telegram…Full post text with line breaks and emoji
views992000View count as a number (viewsText keeps the 992K shorthand)
reactions[{ "emoji": "⭐", … }]Each reaction with its count
media[{ "type": "video", … }]Photos, videos, round videos, voice notes, files and stickers
poll{ "question": …, … }Poll question, type, voter count and each option's percentage
replyTo{ "messageId": 123066, …}The post this one replies to
forwardedFrom{ "channel": "luxta_tv" }The channel a forwarded post came from
linkPreview{ "title": …, … }The link preview card under the post
outlinks["https://…"]Every link in the post text
subscribers10900000On the channel record: subscriber count (plus photo, video, link counts)

The full field reference is further down.

Use cases

  • OSINT and investigations. Archive what a set of channels published, with exact timestamps, view counts, forward sources and reply chains to map who amplifies whom.
  • Brand, news and competitor monitoring. Run it on a schedule with a keyword filter to catch every mention of a brand, product, ticker or place across many channels, and push the hits to Slack, Google Sheets or a webhook.
  • Crypto and trading signals. Collect calls and announcements from signal and project channels, with their timing and reach, straight into a spreadsheet or database.
  • Media and audience research. Compare channels by subscribers, posting rhythm, views and reactions.
  • Research datasets and AI pipelines. Page back through a channel's history with a date cut-off and feed clean text into sentiment analysis, translation, summarisation or a RAG index.

How to scrape a Telegram channel

  1. Click Try for free (or open the Actor in Apify Console).
  2. In Channels, add the channels you want. durov, @durov, https://t.me/durov and https://t.me/s/durov all work.
  3. Set Maximum messages per channel. The default is 40, two pages of the preview.
  4. Optionally add a Keyword filter, or a date in Only messages posted since.
  5. Press Start. Forty messages from two channels take a few seconds.
  6. Open the Output tab and download the data as JSON, CSV, Excel, HTML or XML, or read it through the Apify API.

To keep the data fresh, attach a Schedule in Apify Console: every few minutes for a monitoring feed, or once a morning for a daily digest. Turn on Only new posts since the last run so each scheduled run saves, and charges, only the posts published since the previous one.

Input

All fields are optional; the defaults return the latest 40 posts from @telegram and @durov.

FieldTypeDefaultDescription
channelsarray["telegram", "durov"]Channels to scrape. A username, an @username or any t.me link.
maxItemsinteger40Messages to return per channel, newest first. Without keywords it is the only size limit. 0 means no limit.
keywordsarray[]Only return messages whose text contains one of these words or phrases, matched case-insensitively.
sincestringemptySkip messages older than this date and stop paging back at it. YYYY-MM-DD or a full ISO 8601 timestamp.
onlyNewPostsbooleanfalseRemember each channel's newest post and, on later runs, return only posts published since. For scheduled monitoring. See the FAQ.
maxScannedMessagesinteger500Keyword runs only: messages read per channel, matching or not, before giving up on finding more matches. Ignored without keywords. 0 means no limit.
proxyConfigurationobjectApify proxy offOptional. The preview serves these pages without an anti-bot challenge, so datacenter proxies are plenty if you want one.

Latest posts from a few channels:

{
"channels": ["telegram", "durov", "https://t.me/nexta_live"],
"maxItems": 100
}

Keyword monitoring across channels, reading up to 1,000 recent posts in each:

{
"channels": ["nexta_live", "durov"],
"keywords": ["bitcoin", "airdrop", "wallet"],
"maxItems": 50,
"maxScannedMessages": 1000
}

A full backfill since a date:

{
"channels": ["durov"],
"since": "2026-01-01",
"maxItems": 0
}

A scheduled monitor that saves only posts published since its previous run:

{
"channels": ["nexta_live", "durov"],
"maxItems": 200,
"onlyNewPosts": true
}

Output

Each post is one dataset item with "type": "message". Each channel adds one item with "type": "channel" before its messages. Filter on type if you only want one of them. The examples below come from real runs.

The channel record:

{
"type": "channel",
"channel": "durov",
"title": "Pavel Durov",
"description": "Founder of Telegram.",
"url": "https://t.me/durov",
"imageUrl": "https://cdn4.telesco.pe/file/HYnMQg4YKLOXAKQEfmxf0NzfSxGdMvCScrzLMtLj6Mx…",
"subscribers": 10900000,
"subscribersText": "10.9M",
"photosCount": 102,
"videosCount": 46,
"filesCount": null,
"linksCount": 198,
"scrapedAt": "2026-09-03T17:02:12.041Z"
}

A post with a link preview:

{
"type": "message",
"channel": "telegram",
"messageId": 460,
"postId": "telegram/460",
"url": "https://t.me/telegram/460",
"date": "2026-08-26T19:12:34.000Z",
"text": "For all the info from today's update and a look back at 13 years of Telegram features — check out our blog:\nhttps://telegram.org/blog/welcome-messages-buttons-TG-13\n\nAugust Features\n1 • 2 • 3 • 4 • 5 • More",
"views": 843000,
"viewsText": "843K",
"forwardedFrom": null,
"replyTo": null,
"media": [],
"linkPreview": {
"url": "https://telegram.org/blog/welcome-messages-buttons-TG-13",
"siteName": "Telegram",
"title": "Welcome Messages, Buttons in Messages and Signed Gifts",
"description": "Introducing Welcome Messages to greet new members of groups or channels, Buttons in Messages to make any text interactive, Inline Documents in Messages and much more.",
"imageUrl": "https://cdn4.telesco.pe/file/dhX3eCd_S2LrqYN1CQrGUhmYQarf3dPyUfR0Z_uOtu6…"
},
"outlinks": ["https://telegram.org/blog/welcome-messages-buttons-TG-13", "https://t.me/telegram/455"],
"reactions": [],
"poll": null,
"authorSignature": null,
"edited": false,
"scrapedAt": "2026-09-03T17:02:11.938Z"
}

A poll comes back with its options and the share of the vote each one holds:

{
"type": "message",
"channel": "polls",
"messageId": 122,
"url": "https://t.me/polls/122",
"date": "2026-09-03T08:00:15.000Z",
"text": "",
"views": 8,
"poll": {
"question": "What's the most realistic path for China-West relations over the next decade?",
"type": "Anonymous Poll",
"voters": 1,
"options": [
{ "text": "Managed rivalry with guardrails", "percent": 0 },
{ "text": "Full economic decoupling", "percent": 0 },
{ "text": "Gradual cooperation on shared crises", "percent": 100 },
{ "text": "Escalating conflict with no resolution", "percent": 0 }
]
}
}

A reply carries the post it answers, a forward carries its source, files come back as a name and a size, and reactions carry their counts:

{
"replyTo": {
"messageId": 123066,
"url": "https://t.me/nexta_live/123066",
"author": "NEXTA Live",
"text": "Россияне атаковали университет в центре Киева — в это время у студентов шли занятия…"
},
"forwardedFrom": { "name": "LUXTA", "channel": "luxta_tv", "url": "https://t.me/luxta_tv/8235" },
"media": [{ "type": "document", "url": null, "fileName": "Конкретная математика.zip", "fileSize": "15.4 MB" }],
"reactions": [
{ "emoji": "🤬", "emojiId": null, "count": 1280 },
{ "emoji": "😢", "emojiId": null, "count": 173 }
]
}

CDN links above are shortened with … for readability; the real values are full URLs.

Data fields

FieldTypeDescription
typestringmessage or channel.
channelstringChannel username, without the @.
messageIdnumberTelegram's post number inside the channel. Stable, so use channel + messageId as your key.
postIdstring<channel>/<messageId>, the single-field version of the same key.
urlstringLink to the post on t.me.
datestring | nullWhen it was posted, ISO 8601 in UTC.
textstringPost text with line breaks preserved and emoji intact. Empty for media-only posts.
viewsnumber | nullView count, expanded from the preview's 843K shorthand.
viewsTextstring | nullThe shorthand as the preview renders it.
forwardedFromobject | null{ name, channel, url } for a forwarded post. channel and url are null for a private source.
replyToobject | null{ messageId, url, author, text } of the post being replied to.
mediaarrayOne entry per attachment: { type, url, thumbnailUrl, duration, fileName, fileSize }.
linkPreviewobject | nullThe preview card: { url, siteName, title, description, imageUrl }.
outlinksarrayEvery http(s) link inside the post text, deduplicated.
reactionsarray{ emoji, emojiId, count } per reaction. Custom emoji have an id and no character.
pollobject | null{ question, type, voters, options[] }, each option with its text and percent.
authorSignaturestring | nullThe signature on the post, when the channel signs posts.
editedbooleanWhether the post carries Telegram's "edited" mark.
scrapedAtstringWhen this run read the page, ISO 8601 in UTC.

The channel record carries channel, title, description, url, imageUrl, subscribers, subscribersText, photosCount, videosCount, filesCount, linksCount and scrapedAt. A count is null when the channel's preview does not show it.

Media type is one of photo, video, roundvideo, voice, document or sticker. Photos, videos and voice notes come back with a direct CDN URL. Documents do not: Telegram's preview publishes the file name and size but no download link, so url is null for them.

How much does it cost to scrape Telegram channels?

This Actor uses pay per event pricing with platform usage included, so these two numbers are the whole bill:

EventPriceWhen it is charged
Actor start$0.005Once per run (at the default 1 GB of memory)
Result$0.002Per message saved, and per channel record (one for each channel)

That is $2 per 1,000 posts. Some example runs:

RunResultsCost
Default input: 40 posts from 2 channels82$0.17
100 posts from 1 channel101$0.21
1,000 posts from 1 channel1,001$2.01
Keyword run over 500 posts that finds 4 matches5$0.02
10 channels × 50 posts510$1.03
Only-new scheduled run, 3 new posts in 1 of 10 channels4$0.01

Messages that fail the keyword or date filter are read but never saved, so they cost nothing. With onlyNewPosts on, posts an earlier run already covered are not saved again either, and a channel with nothing new adds no channel record, so a scheduled run that finds nothing costs only the start event. The Apify free plan includes $5 of monthly credit, enough for about 2,500 posts to try the Actor. To cap a single run, set a maximum cost in the run options or lower maxItems.

Telegram scraper vs. the Telegram API

This ActorTelegram API (Telethon, Pyrogram)Telegram Bot API
What you needNothingPhone number, api_id, api_hash, a sessionA bot token, and the bot added as channel admin
Which channelsAny public channel with a web previewAny channel your account can openOnly channels the bot administers
HistoryPages back through the whole channelYesNo, only posts sent after the bot joins
Account riskNone, no account involvedRate limits and bans hit your accountTied to the bot
Forward counts, commentsNo (the preview does not show them)YesNo
Scheduling, API, exportsBuilt in through ApifyYou host and run itYou host and run it

If you need forward counts, comments or private groups, you need an account-based client. For public channel posts, views and reactions, this Actor gets you there without one.

Use it through the API, integrations and AI agents

REST API. Run the Actor and get the results in one call:

curl -X POST "https://api.apify.com/v2/acts/thatmike1~telegram-channel-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"channels": ["durov"], "maxItems": 50}'

Node.js with apify-client:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('thatmike1/telegram-channel-scraper').call({
channels: ['durov', 'telegram'],
keywords: ['wallet'],
maxItems: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const messages = items.filter((item) => item.type === 'message');

Python with apify-client:

from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("thatmike1/telegram-channel-scraper").call(
run_input={"channels": ["durov"], "since": "2026-09-01", "maxItems": 0}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
if item["type"] == "message":
print(item["date"], item["views"], item["text"][:80])

Integrations. Send results to Google Sheets, Slack, Zapier, Make, n8n, Airtable or any webhook with Apify integrations, and run it on a schedule for a hands-off feed.

AI agents (MCP). Give Claude, ChatGPT, Cursor or any MCP client a Telegram tool through the Apify MCP server:

$claude mcp add --transport http apify "https://mcp.apify.com?tools=thatmike1/telegram-channel-scraper"

Then ask in plain language, for example: "Get the last 100 posts from @durov and tell me which ones had the most views."

Tips for monitoring and large runs

  • maxItems is per channel, not per run. Ten channels at maxItems: 50 is up to 500 messages. A shared budget would let the first channel eat all of it.
  • maxScannedMessages only matters with keywords. A keyword run stops reading a channel after 500 messages by default, matching or not, so a rare keyword does not walk the whole history. Raise it, or set 0, to search deeper. A run without keywords ignores it: maxItems: 1000 returns 1,000 posts.
  • Scheduled monitoring without repeats. Turn on onlyNewPosts and each run saves only posts newer than the newest one the previous run read, so nothing is charged twice. Set maxItems above what a channel posts between two runs; anything beyond it in one run is skipped, not carried over.
  • Track reach over time. A post scraped twice keeps its postId and comes back with a higher view count, so repeated runs give you a views curve per post.
  • Proxies are optional. Telegram does not challenge these pages. Turn on Apify Proxy datacenter groups only if you run very frequently.

FAQ

Does this Actor need a Telegram account, phone number or API key? No. It reads the public web preview at t.me/s/<channel>, which needs no login, no phone number, no api_id and no bot token.

Which channels can it read? Any public channel that has a web preview, which covers most news, crypto and broadcast channels. Private and invite-only channels, groups, user accounts and bots have no preview: t.me redirects those to a plain landing page, and the Actor logs a warning, names them in the run's status message and skips them rather than failing the run.

Can it scrape Telegram groups or members? No. It reads channels only. Group chats and member lists are not on the public preview.

Does it return forward counts? No, and no scraper of this page can. Telegram's public preview publishes views and reactions but not the number of times a post was forwarded. What the Actor does return is forwardedFrom, the channel a post was forwarded from.

Does it return comments? No. replyTo is the in-channel reply chain. Comments live in the linked discussion group, which the channel preview does not render.

Can it search all of Telegram by keyword? No. The keyword filter works inside the channels you list. You choose the channels; the Actor finds the posts in them that mention your terms.

Why is text sometimes empty? A post can be media only, a poll only, or a forward with no caption. The text is an empty string rather than null in those cases, and the content is in media or poll.

Why did I get fewer messages than I asked for? Without keywords, only maxItems and since limit a run, so the channel is shorter than your limit or your date cuts it off. With keywords, the Actor reads at most maxScannedMessages (500 by default) per channel looking for matches; raise it or set 0 to search deeper. With onlyNewPosts on, posts an earlier run already returned are left out on purpose.

How do I get only new posts on a schedule? Turn on onlyNewPosts (Only new posts since the last run) and attach a schedule. When a channel finishes, the Actor stores the newest post id it read in a key-value store named telegram-channel-scraper-last-seen in your Apify account, one record per channel. The next run stops paging when it reaches that post, so it saves and charges only what was published since. Things to know:

  • The first run with it on has nothing stored yet and behaves like a normal run: maxItems and since decide how much it returns.
  • Each keyword filter is tracked separately (the record key is the channel plus a hash of the keywords), because a keyword run marks every post it read as seen, matching or not. Two schedules on one channel with different keywords do not steal each other's posts, and changing your keywords starts fresh. since, maxItems and maxScannedMessages are not part of the key.
  • maxItems still caps each run. If a channel posted more than that since the last run, the newest are saved and the rest are skipped for good, so set it comfortably above a channel's posting rate.
  • A channel whose pages failed to load keeps its old position, so the next run retries it. That can repeat a few posts, but never loses any.
  • To start over, delete the channel's record, or the whole store, under Storage → Key-value stores.
  • A post's view count is not updated by later only-new runs. Turn the option off for a views curve.

Is scraping Telegram legal? This Actor reads only publicly available pages, the same ones anyone can open without an account, and does not bypass any access control. Scraping publicly accessible information is generally legal in the EU and the US, but you are responsible for how you use the output, including Telegram's Terms of Service, the privacy of the people posting and data protection law such as the GDPR. Talk to a lawyer if you plan to redistribute the data commercially.

Found a bug, or need something else? Open an issue on the Issues tab and it will be picked up. If you need a custom version or a field that is not covered here, say so in the issue.

More scrapers from the same developer

Website Tech Stack Detector for the sites a channel links to, Kalshi Prediction Markets Scraper for event odds next to the news, and Sports Odds Scraper for bookmaker prices.