Telegram Channel Scraper — Messages, Views & Media | from $3/1K avatar

Telegram Channel Scraper — Messages, Views & Media | from $3/1K

Pricing

from $2.91 / 1,000 message-scrapeds

Go to Apify Store
Telegram Channel Scraper — Messages, Views & Media | from $3/1K

Telegram Channel Scraper — Messages, Views & Media | from $3/1K

Scrape public Telegram channel messages with text, view counts, timestamps, media type, links, forwards, and reply threading — no API key, no login, no proxy required. Structural HTML parser (not class-name fragile) with parse_confidence drift signal. Paginates backwards via cursor.

Pricing

from $2.91 / 1,000 message-scrapeds

Rating

0.0

(0)

Developer

Vitalii Bondarev

Vitalii Bondarev

Maintained by Community

Actor stats

0

Bookmarked

17

Total users

4

Monthly active users

2 days ago

Last modified

Share

Telegram Channel Scraper — Messages, Views & Media

Scrape messages from any public Telegram channel — no API key, no Telegram account, no proxy required. This Telegram channel scraper extracts message text, view counts, timestamps, media type, links, forward source, and reply threading from public channels accessible via t.me.

Use it for brand monitoring, crypto/news signal aggregation, competitive intelligence, or feeding Telegram content into LLM pipelines.

How the Telegram scraper works

Uses the public Telegram web preview at https://t.me/s/{channel} — the same URL anyone can open in a browser. Paginates backwards via ?before={message_id} to collect historical messages going as far back as the channel's public web history allows.

No unofficial MTProto API, no bot token, no phone number verification. Just HTTP + structural HTML parsing.

Why this Telegram scraper is more reliable than alternatives

Most Telegram scrapers use the MTProto API (requires a phone number and Telegram account) or depend on CSS class names that break on every Telegram web redesign. This actor uses structural XPath parsing on the semantic HTML structure — data-* attributes and element structure, not fragile class names. When Telegram updates its web UI, parse_confidence drops below 0.8 and warnings flag the affected fields — you get a drift signal, not silent wrong data.

Input

{
"channels": ["telegram", "@durov", "https://t.me/cointelegraph"],
"maxMessages": 200
}
FieldTypeDescription
channelsstring[]Public channel usernames, @handles, or t.me URLs
maxMessagesintegerMax messages per channel (default: 100)
beforeIdintegerOptional cursor — only collect messages before this ID

Output

One row per message:

FieldTypeDescription
channelstringChannel username
message_idintegerTelegram message ID
textstring|nullMessage text content
viewsstring|nullView count (e.g. "1.5M", "42K")
datetimestringISO-8601 UTC timestamp
has_mediabooleanWhether the message contains media
media_typestring|null"photo", "video", "document", "sticker", "audio", "poll"
linksstring[]HTTP/HTTPS links in message text
is_forwardedbooleanWhether forwarded from another channel
forward_fromstring|nullSource channel/user name if forwarded
reply_tointeger|nullMessage ID being replied to
message_urlstringFull https://t.me/{channel}/{id} URL
parse_confidencefloat0.0–1.0 quality signal; below 0.8 check warnings
warningsstring[]Parse quality warnings (e.g. "missing_datetime")
scraped_atstringISO-8601 UTC scrape timestamp

What it does NOT support

  • Private channels — only public channels accessible via t.me/s/{channel}
  • Comments/replies within posts — web preview shows channel messages only
  • Media downloads — returns media type detection only, not URLs to media files
  • Real-time streaming — pulls historical messages, not a live feed

Competitive edge

FeatureThis actor@maximedupre/telegram-channel-messages-scraper
parse_confidence field✓✗
Pagination cursor input (beforeId)✓✗
Forward source name✓✗
Reply-to message ID✓✗
Structural parser (not class-name fragile)✓✗
PricePPE $3/1K messages~$50/mo fixed

Frequently asked questions

Can I scrape a private Telegram channel?

No. This actor only works on public channels accessible via t.me/s/{channel}. Private channels, groups, and direct messages are not supported.

Does this require a Telegram bot token or phone number?

No. The actor scrapes the public Telegram web preview (t.me/s/*) — no account, no bot token, no API credentials needed.

How far back can I scrape?

As far back as Telegram's public web preview stores. Most active channels have several years of history available. Use maxMessages and beforeId cursor to control the range.

Does it download media files?

No. The actor detects media type (photo, video, document, sticker, audio, poll) and returns the type flag, but does not download or return media URLs. This keeps the output lean and the cost low.

How is pricing calculated?

Pay-per-result (PPE) at $3.00 per 1,000 messages ($0.003/message). One charge (message-scraped event) per message pushed to the dataset. Failed fetches, retries, and pagination probes are not charged.

Integrations

Built for brand monitors, crypto-signal aggregators, and LLM-pipeline builders ingesting public Telegram channel content — the JSON/dataset output drops into the tools you already run, no glue code:

  • n8n / Make / Zapier — trigger a run or pipe every new dataset item into 500+ apps (Google Sheets, Airtable, Slack, HubSpot, your database) with no code: n8n, Make, Zapier.
  • Webhooks — fire your own endpoint the moment a run finishes, to push results straight into your pipeline (docs).
  • MCP server — expose this actor as a tool to Claude, Cursor, or any MCP client so an AI agent can pull this data mid-conversation (guide).
  • API & SDKs — fetch the dataset as JSON, CSV, or Excel through the Apify REST API or the Python / JS SDKs.

See all Apify integrations.

This actor scrapes the publicly accessible web preview of Telegram channels (t.me/s/*). This is identical to what a browser sees when visiting the URL. Only public channels (already freely accessible to anyone on the internet) are scraped.

Not affiliated with Telegram.

More scrapers from our toolkit

Building a data pipeline? These actors pair well with this one — each runs on your own Apify account with the same pay-per-result pricing, no subscription:

Chain any of them together from the Integrations tab (the Run succeeded trigger) to build a multi-step workflow — one actor's output feeds the next.

Usage statistics

This Actor creates a small, content-free summary at the end of each run. It is used only to monitor reliability and improve this Actor. A copy is saved as USAGE_STATS in your own Apify key-value store, so you can see the exact record created for your run.

Set disableUsageStats to true in the input to opt out. Nothing is sent then; your USAGE_STATS record only says that statistics were disabled.

Only these fields are recorded:

  • schema version, Actor name and build number;
  • UTC start and finish hour (not a precise timestamp);
  • run duration, number of results and time to the first result, each as a coarse range;
  • whether the result was empty, the end status, and an error type from a fixed list;
  • memory setting and counts of charged events;
  • names of the input fields you set, never their values;
  • the selected option for input fields that offer a fixed list of choices (for example a sort order).

We do not collect input text, search terms, URLs, domains, usernames, email addresses, names, proxy credentials, tokens, scraped records, output items, raw error messages, stack traces, or hashes of any of those values. Records are kept for no longer than 13 months, used only as aggregated operational statistics, and never sold or shared.

Additional fields (Phase 2)

This Actor also records your Apify user ID, whether Apify marks the account as paying, the size range of list inputs, the selected country when the input offers a fixed list of countries, and one category from a fixed Actor taxonomy. We use these fields only for aggregate reliability, repeat-use and cross-Actor analysis; reports suppress any cell with fewer than five distinct users.

The same disableUsageStats: true input flag turns these fields off too. The user ID is removed after 13 months; we do not export, sell, share, or attempt to re-identify this data.

Run-outcome signals (v2)

To learn whether a run did what it was asked to do, the record also holds a few more coarse ranges and yes/no flags. None of them contains content:

  • the result limit you asked for (a range, when the input has one) and what share of it was delivered;
  • results delivered per input item you listed (a range);
  • output quality as ranges: how fully the result fields were filled, the share of rows that look like errors, the share of duplicate rows, and how many different fields appeared. These are counted in memory while results are saved; no result content is kept;
  • how the run was started (console, API, schedule, webhook, another Actor);
  • how it ended: stopped by you, timed out, reached the requested limit, stopped by the charge limit, and how many times the platform moved the run;
  • if this Actor reports it: how many items to process worked or failed (ranges) and one failure reason from a fixed list;
  • a short code made from the names of the input fields you set, never their values.

Repeat-run fingerprint (v2)

When your Apify user ID is recorded (see above), the record also holds an 8-character one-way code made from your input (proxy settings left out) and this Actor's name. It only lets us see that the same account ran the same input again soon after an unsatisfying run; we never see the input itself. It is stored only in the database, never published, and reports use it in aggregate with the same five-user minimum. It is the one exception to the statement above that no hashes are collected, and disableUsageStats: true turns it off.