Telegram Channel Posts Scraper avatar

Telegram Channel Posts Scraper

Pricing

from $1.48 / 1,000 results

Go to Apify Store
Telegram Channel Posts Scraper

Telegram Channel Posts Scraper

Collect public Telegram channel posts with date, text, views, photos, video, links and reactions, plus optional channel profiles with subscriber counts. Reads the public t.me/s preview with no login or phone number; filter by date or keyword. Channels without a preview return a status row.

Pricing

from $1.48 / 1,000 results

Rating

0.0

(0)

Developer

Axiom Works

Axiom Works

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

6 days ago

Last modified

Categories

Share

Returns: one row per public Telegram post with channel, postId, date, text, views, viewsText, and url; optional channel profile rows. Input: {"channels":["durov"],"maxPostsPerChannel":20} Best for: public channel monitoring, post archives, and view-count analysis.

{"id":"telegram/460","channel":"telegram","postId":460,"date":"2026-08-26T19:12:34.000Z","views":1610000,"viewsText":"1.61M","url":"https://t.me/telegram/460"}

What does Telegram Channel Posts Scraper do?

Telegram Channel Posts Scraper collects posts from public Telegram channels through their web preview pages. Give it one or more channel usernames or t.me URLs, and it returns structured post records in an Apify dataset. Each post has a channel, canonical URL, publication date, readable text when present, original text HTML, view count, media URLs, links, and visible reaction counts. You can also request a separate channel profile record for each channel.

The Actor uses the public t.me/s/ preview. It does not sign in or read private channels, member lists, comments, or messages visible only in the Telegram app. A channel that does not expose public preview posts yields no post records; the run log reports its status. This is a batch Actor: it fetches pages, writes records, and exits. It processes up to two channels at once, paces requests within each channel, and retries block responses with backoff and fresh proxy sessions. If default datacenter proxy sessions are blocked, it tries a residential proxy when available.

The optional enrich setting classifies a post's main topic and sentiment. Enrichment sends post text to TypeSafe AI, a third-party AI processor. It costs extra per labelled post and is off by default. If the processor is unavailable or fails, the scraper continues and leaves the enrichment fields empty. Classification is an interpretation of the text, while the other post fields come from the Telegram preview.

What data can you get?

The dataset contains three record types. A post record holds one Telegram post. A channel-status record is emitted when a channel has no web preview (private, group, not found), so the run never ends silently empty. A channel record holds the public profile summary, if includeChannelInfo is enabled. Both have a stable string id (channel/postNumber), channel, url, and sourceUrl. sourceUrl identifies the exact preview page from which the record came. The channel and post number are combined to keep dataset IDs distinct when two channels use the same post number.

FieldRecordMeaning
idBothStable ID in the form channel/postNumber, unique across channels and pages.
recordTypeBothpost, channel or channel-status.
channelBothNormalized public channel username.
urlBothCanonical Telegram post or profile URL.
sourceUrlBothPreview page that supplied the record.
postIdPostTelegram's post number within the channel.
datePostPublication timestamp in ISO 8601 format.
textPostVisible plain text with line breaks preserved as \n, when present.
htmlPostHTML of the visible text element with inline event handlers removed, when present.
viewsPostNumeric view count parsed from the displayed K, M, or B abbreviation.
viewsTextPostOriginal view count displayed by Telegram, such as 1.61M.
photosPostAvailable photo URLs shown in the preview.
videoPostAvailable video URL shown in the preview.
linksPostLinks found in the post's text.
linkPreviewPostLink preview URL when Telegram exposes one.
linkPreviewTitlePostTitle on the link preview card, when present.
linkPreviewDescriptionPostDescription on the link preview card, when present.
linkPreviewSitePostSite name on the link preview card, when present.
videoThumbnailPostThumbnail image URL of the post video, when present.
videoDurationPostVideo length in seconds, when shown.
authorPostAuthor name shown on the post, when present.
mediaTypePostvideo, photo or link for the main media, otherwise null.
forwardedFromPostVisible attribution for a forwarded post, if shown.
editedPostWhether the preview marks the post edited.
reactionsPostReactions as text: the emoji (⭐ for paid stars, emoji:<id> for custom emoji) followed by the count as displayed.
topicPostOptional AI classification: news, crypto, promo, tech, politics, entertainment, or other.
sentimentPostOptional AI classification: positive, neutral, or negative.
titleChannel profilePublic title of the channel.
descriptionChannel profilePublic channel description.
subscribersChannel profileParsed subscriber count, when shown.
photosCount, videosCount, linksCountChannel profileParsed public profile counters, when shown.
statusChannel profile, channel statusWhether public posts were found, or the channel status (not_found, private, no_preview).
detailChannel statusWhy no posts were returned (private, group, not found, redirect).

The HTML preview does not guarantee every optional field on every post. Media-only posts can have empty text. Some previews do not expose a forwarded attribution or link preview. A numeric counter can be null when its visible text cannot be parsed. The Actor preserves available media URLs but does not download images or videos.

How to use

Open the Actor's input form and enter public channel usernames, such as durov, or full https://t.me/ links. Set maxPostsPerChannel to control how far the Actor pages back through each channel, and set maxItems for a hard cap over the whole dataset. A channel profile uses one item from that total cap when profiles are enabled. Then start the Actor and open the dataset when it finishes.

The newest preview page is requested first. If more posts are needed, the Actor requests earlier pages using the smallest post number from the previous page. It deduplicates posts by stable ID. Pagination ends when the post limit is met, a page has no posts, the post numbers stop decreasing, or the selected dateFrom boundary has been passed. searchQuery uses Telegram's public channel web search; its availability depends on Telegram's preview behavior. Set dateTo to exclude newer posts while paging back into a historical window. Set afterPostIds to collect only posts newer than the saved ID for each channel. A date-only dateTo includes the full UTC day.

For a quick sample, use maxItems: 7. If the channel has at least seven available records, the dataset contains exactly seven items, counting an included profile. To receive seven posts rather than six posts plus a profile, set includeChannelInfo to false. For longer runs across many channels, increase both the per-channel limit and the global cap to the amounts you need.

Only public channels with enabled web previews can return posts. A private link, a group, or a channel without preview access cannot be made accessible by this Actor. If Telegram redirects or rejects the preview, check the run log for the channel's status. The default Apify datacenter proxy can switch to residential sessions after repeated blocks when residential access is available. Requests to Telegram are paced to roughly one per second per channel, with at most two channels active at once.

Input

InputRequiredDefaultPurpose
channelsYesPrefilled examplePublic channel usernames or t.me URLs.
maxPostsPerChannelNo50Maximum post records for each channel, 1–1000.
maxItemsNo1000Maximum total records, including profiles, 1–10000.
dateFromNoNoneEarliest publication date in ISO format.
dateToNoNoneLatest publication date in ISO format; date-only values include the UTC day.
afterPostIdsNo{}Last seen numeric post ID for each channel; only newer posts are returned.
searchQueryNoNoneQuery for Telegram's public channel search.
includeChannelInfoNotrueInclude one profile record per channel.
enrichNofalseRequest topic and sentiment classification.
maxJevCallsNo500Maximum AI requests per run, 1–500.
proxyConfigurationNoApify datacenter proxyApify Proxy settings for Telegram requests.

Example input:

{
"channels": ["durov", "https://t.me/telegram"],
"maxPostsPerChannel": 20,
"maxItems": 42,
"dateFrom": "2026-01-01",
"dateTo": "2026-09-30",
"afterPostIds": {"durov": 500},
"includeChannelInfo": true,
"enrich": false
}

The channel list is required in API calls. The Console form shows example channels as a prefill, but an API caller must supply its own channels value. Invalid usernames, unsupported URLs, empty arrays, invalid dates, and limits outside their documented ranges fail at the start of the run with a clear error. Duplicated channel names are processed once. A URL must point to t.me; other hosts are not accepted as channel input.

Enrichment uses our third-party AI processor (TypeSafe AI); no key is needed. Post text is sent to it only when enrich is on. If the service is unavailable, records are still produced without topic and sentiment values.

Output

This channel profile record is from the local prefill run:

{
"id": "durov/0",
"recordType": "channel",
"channel": "durov",
"url": "https://t.me/durov",
"sourceUrl": "https://t.me/s/durov",
"title": "Pavel Durov",
"description": "Founder of Telegram.",
"subscribers": 10500000,
"photosCount": 102,
"videosCount": 46,
"linksCount": 200,
"status": "ok"
}

A post from the local prefill run has these values:

{
"id": "telegram/460",
"recordType": "post",
"channel": "telegram",
"postId": 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": 1610000,
"viewsText": "1.61M",
"url": "https://t.me/telegram/460",
"sourceUrl": "https://t.me/s/telegram"
}

The sample post is shown with the fields most useful for a quick review; the Actor also stores its available HTML, media, links, reactions, and enrichment fields. Values can change as Telegram updates view and reaction counts.

How much does it cost?

Pricing is per result. Each post is charged as one result. Each channel profile record is charged as one result. Channel-status records are not charged. A post is charged an additional enrichment result only if both topic and sentiment enrichment succeeds. The final charge depends on the number of records and whether enrichment was used. See the Actor's Pricing tab for current event prices; they are intentionally not copied into this README.

Use maxItems to place a clear ceiling on the total records in a run. The maxPostsPerChannel setting controls the work for each channel, and dateFrom can stop older-page requests early. Failed AI calls do not trigger the enrichment event. Compute and proxy costs are included in the event prices.

Use with AI agents (MCP)

Apify's MCP server can expose this Actor as a tool. A client configuration can use the server URL below:

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com/?tools=axiomworks/telegram-channel-posts-scraper"
}
}
}

An agent can then ask, “Collect the latest 10 posts from the public durov channel and summarize their dates and view counts.” Another prompt is, “Get public posts from telegram since 2026-01-01, and include the channel profile.” The agent should provide channels explicitly, because the Console prefill is an example rather than a value supplied to API callers. The output schema helps the agent distinguish post rows from channel profile rows.

For topic-based tasks, ask the agent to set enrich only when topic or sentiment is needed, because it costs extra per labelled post. Classification consumes an external AI service and may be incomplete. The original text, date, URL, and source URL remain available for checking a summary against its source.

Integrations and API

You can start the Actor through Apify's API and read its dataset through standard SDKs. Set your Apify API token in the APIFY_TOKEN environment variable and keep it in your application's secret store. The examples show a small public scrape; adjust the limits to suit your workflow.

Python:

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("axiomworks/telegram-channel-posts-scraper").call(run_input={
"channels": ["durov"],
"maxPostsPerChannel": 10,
"maxItems": 10,
"includeChannelInfo": False,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["url"], item.get("date"))

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('axiomworks/telegram-channel-posts-scraper').call({
channels: ['durov'],
maxPostsPerChannel: 10,
maxItems: 10,
includeChannelInfo: false,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const item of items) process.stdout.write(`${item.url}\n`);

cURL:

curl -X POST "https://api.apify.com/v2/acts/axiomworks~telegram-channel-posts-scraper/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"channels":["durov"],"maxPostsPerChannel":10,"maxItems":10,"includeChannelInfo":false}'

The synchronous endpoint is convenient for a short sample. For larger runs, start the Actor asynchronously, wait for completion, then fetch the default dataset. Dataset items can be sent onward to spreadsheets, databases, analysis jobs, or an agent. Keep id as the deduplication key if you collect the same channel repeatedly; view counts can change while that ID stays stable.

FAQ

Can this read private channels or groups? No. The Actor reads only public Telegram channel pages that expose a web preview. It has no account session and does not try to bypass login or access controls.

What happens when a channel has no public posts? The run still ends successfully. The dataset gets a channel-status record (private, not_found or no_preview) and the run status message says what to change, for example using a public channel username.

Why are there fewer posts than my limit? The public preview may have fewer accessible posts, dateFrom may exclude older posts, the channel may redirect, or Telegram may respond with an error. The Actor logs a per-channel status. The maximum is a ceiling, not a promise that a channel contains that many accessible posts.

Why does maxItems include profiles? A profile is a dataset record with its own stable ID and source URL. Counting it makes the global item limit exact. Disable includeChannelInfo when your limit should apply only to posts.

Are images downloaded? No. Photo and video fields are URLs observed in the preview. Some media URLs may be temporary or may stop working later. The Actor does not open those URLs or store binary media.

How are views and subscribers counted? Telegram displays abbreviated values such as 1.2K or 3.4M. The Actor converts them to approximate integers using decimal multipliers. The source display value can change after the run.

What happens if AI enrichment fails? Scraping continues. The relevant post is still returned, topic and sentiment remain empty, and no successful enrichment event is charged for it.

This Actor is designed for publicly visible channel previews. Whether a particular use is permitted depends on your location, the content, and your intended use. Review applicable law and Telegram's terms for your case. Respect copyright, privacy, and any obligations that apply to your downstream storage or publication. The Actor does not provide access to private data or require a Telegram login. It is an independent tool and is not affiliated with Telegram.

Feedback

If a public channel's preview changes or a field stops appearing, report the channel URL, a post URL if available, the run time, and which field was missing. Avoid including secret keys or private data in a report. A reproducible public example helps identify selector changes. You can also suggest additional fields that are actually visible on the public preview. Check the run log first for redirects, rate limits, or an empty public preview.