# Telegram Channel Messages Scraper with Comments (`cleanscrape/telegram-channel-messages-scraper`) Actor

Export public Telegram channel messages: text, date, views, reactions, media and links, with optional comments and exact subscriber counts. Search inside channels, filter by date or words, and get only new posts on a schedule. No login. $0.80 per 1,000 posts. Maintained by CleanScrape.

- **URL**: https://apify.com/cleanscrape/telegram-channel-messages-scraper.md
- **Developed by:** [CleanScrape](https://apify.com/cleanscrape) (community)
- **Categories:** Social media, News, Automation
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.64 / 1,000 posts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Telegram Channel Messages Scraper with Comments

Export public Telegram channel messages without a Telegram account, phone number or API key. Paste channel names or links and get every post's text, date, views, reactions, media and links as a table you can download as CSV, Excel or JSON. Add the public comments, search inside a channel, filter by date or words, and schedule it to get only new posts.

Each channel also gets a row with its name, description and exact subscriber count. This is an independent tool, maintained by CleanScrape.

### Watch the walkthrough

Telegram's own news channel, from its first post in 2015 to a table. This 81-second demo on real runs shows 424 posts read in under 20 seconds, the most viewed post, exact subscriber counts, 745 comments with their replies linked, and a schedule that saves only new posts.

https://youtu.be/yOrtoADrt-Y

### Start with a small run

1. In **Channels or post links**, keep `TelegramTips` or paste the channels you follow: `@durov`, `https://t.me/telegram`, `t.me/s/tginfo` or a link to one post all work, one per line.
2. Leave **Posts per channel** at 20 for a first look.
3. Start the run and open **Posts**. Download CSV or Excel for a spreadsheet, or JSON to keep reactions and media as lists.

No channel IDs, cookies or login are needed. Only public channels work: private channels, groups and invite links don't have a public web view.

### Choose what to collect

**Recent posts:** posts come newest first. **Posts per channel** applies to each channel or post link, and the same channel pasted twice is read once.

**One post:** paste a link such as `https://t.me/TelegramTips/576` to save that post (and its comments, if you turn them on).

**Posts about a topic:** **Search within channels** asks Telegram for the posts that match, in the channels you supplied. Telegram chooses the matches. For a strict check of the post text, use **Include words** or **Exclude words**: any included word or phrase keeps a post, any excluded one drops it, ignoring case.

**A date range:** Last 7 days, Last 30 days or Custom dates, by the post's publication time in UTC. The end date includes the whole day.

**Comments:** turn on **Include comments** to save up to **Comments per post** of each post's most recent public comments, in their own table, for channels that have comments switched on. Each comment has its text, date, reactions, media, the comment it replies to and the commenter's display name as Telegram shows it to visitors who are not logged in (Telegram hides names in some regions; then the name is empty). Names are personal data: store and use them with care.

### Get only new posts on a schedule

Turn on **Only new posts** and schedule the run (hourly or daily, for example):

- The first run saves the newest posts (up to **Posts per channel**) as the starting point.
- Each later run saves only posts published since, and stops reading a channel as soon as it reaches posts it already covered, so a check costs a page or two per channel.
- If more new posts arrived than **Posts per channel** allows, the next run continues where this one stopped. No new post is skipped, and none is saved twice.

Runs with the same channels share one history. To keep the history when you add or remove channels, give it a **Watch name**, such as `Crypto news channels`. Changing the search or the words starts a new history, so different filters are never mixed. The history is kept in your own Apify account, and two runs of the same watch can't overlap.

### Examples

The last 100 posts of three channels:

```json
{
  "channels": ["TelegramTips", "@durov", "https://t.me/telegram"],
  "maxPosts": 100
}
```

Posts that mention a topic in the last 30 days, with their comments:

```json
{
  "channels": ["tginfo"],
  "search": "Stories",
  "period": "30days",
  "includeComments": true,
  "commentsPerPost": 50
}
```

A schedule that saves only new posts from a list of channels:

```json
{
  "channels": ["TelegramTips", "durov", "telegram"],
  "maxPosts": 200,
  "onlyNew": true,
  "watchName": "telegram-news"
}
```

### What you get

| Table | Contents |
| --- | --- |
| Posts | Channel, post ID, date, text, views, reactions, media, links, link preview, poll, forwarded from, signature, post link |
| Comments | One row per comment: post ID, comment ID, date, display name, text, reactions, media, the comment it replies to |
| Channels | Channel name, description and subscriber count |
| Run summary (`SUMMARY`) | For every input: posts saved, pages read, the oldest and newest post, and why collection stopped |

`recordId` (channel/post ID, plus the comment ID for comments) is a stable key for joining exports. IDs are kept as text.

#### Reading the counts

Telegram rounds views and reactions above 1,000: `viewsText: "6.23K"` becomes `views: 6230` with `viewsApproximate: true`. It is a rounded number, not an exact count. Subscriber counts come from the channel page and are exact (`subscribersApproximate: false`). Missing values are `null`, never zero.

Media links point to files in Telegram's public preview; they can expire, and files are not downloaded. Custom emoji reactions have an ID but no readable character.

### Check coverage before treating an export as complete

**Posts per channel** is a maximum, not a promise. Each input's reason in the run summary says why it stopped: the post limit, **Pages per channel**, the start date, the oldest visible post, no matching posts, or no public preview. A channel without a public preview may be private, renamed, removed, a group or a user account; the other channels still run.

Telegram's comment widget shows the most recent comments of a post (in one test, 97 of 104). The summary keeps the total Telegram shows and the number saved, so a large discussion is never presented as complete when it isn't.

This Actor does not search all of Telegram, list group members, read private chats or log in to an account.

### Pricing

You pay for what is saved, with no start fee:

| Event | Price |
| --- | ---: |
| Channel or post link read (once per run) | $0.002 |
| Post saved | $0.80 per 1,000 |
| Comment saved | $0.80 per 1,000 |

Bronze, Silver and Gold plans get 10%, 15% and 20% off. For example, at base prices: 20 posts from one channel cost $0.018; 1,000 posts from one channel $0.802; 5 posts with 200 comments $0.166; a daily check of 5 channels with nothing new $0.01.

Nothing is charged for input that can't run or for a channel without a public preview. Set a spending limit for large runs; the run stops cleanly before it and keeps everything saved.

### Speed and limits

Requests to Telegram are paced (about one every 0.65 seconds) so runs stay polite and reliable. A page has about 20 posts, and each post with comments is one more request. In cloud tests a whole channel of 424 posts took 20 seconds, and 5 posts with 215 comments took 6 seconds. **Pages per channel** (default 50) and **Request limit** (default 500) cap long runs; raise them for deep history. The run stops before its timeout and keeps what it saved.

### Use it from the API

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")
run = client.actor("cleanscrape/telegram-channel-messages-scraper").call(run_input={
    "channels": ["TelegramTips", "durov"],
    "maxPosts": 50,
})
for post in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(post["date"], post["channel"], post["views"], post["text"])
## Comments and channels are the run's other datasets:
comments = client.dataset(run["storageIds"]["datasets"]["comments"]).list_items().items
```

### Common questions

#### Do I need a Telegram account or API key?

No. The Actor reads the public web view of channels (t.me/s/<channel>), which anyone can open in a browser without logging in.

#### Can it search all of Telegram?

No. It searches inside the channels you give it. Searching all of Telegram needs a logged-in account, which this Actor never uses.

#### Can I get private channels or group chats?

No. Only public channels have a public web view.

#### Are views exact?

Views and reactions are rounded by Telegram above 1,000 (`viewsApproximate` says when). Subscriber counts are exact.

#### How far back can it go?

As far as the channel's public history goes; one test reached posts from 2015. Raise **Posts per channel**, **Pages per channel** and **Request limit** for deep history.

#### Is it legal to scrape Telegram channels?

The Actor reads pages that Telegram publishes for anyone, without logging in, at a gentle pace, and it doesn't get around any protection. Telegram's terms restrict some uses of its content, including training AI models without consent, so check the rules that apply to how you store and use the data. This is not legal advice.

### Support

CleanScrape maintains this Actor and fixes it when Telegram changes its pages. If something looks wrong, open an issue or email <contact.cleanscrape@gmail.com> with the run ID and the channel or post link. Never include passwords, session cookies or private messages.

If the Actor was useful, an honest review on its Store page helps other people find it.

### Disclaimer

This Actor is an independent tool developed by CleanScrape. It is not affiliated with, endorsed by, or sponsored by Telegram. Telegram and other trademarks belong to their owners and are used only to identify the source.

### More tools from CleanScrape

- [Google Flights Scraper and Fare Tracker](https://apify.com/cleanscrape/google-flights-scraper): flight prices by route and date, with fare tracking
- [ATP and WTA Tennis Rankings Scraper](https://apify.com/cleanscrape/tennis-rankings-scraper): current ATP and WTA singles, doubles and race rankings with points and movement
- [Flashscore Tennis Scraper for Match History and Stats](https://apify.com/cleanscrape/tennis-match-data): tennis results, statistics, point-by-point and head-to-head
- [Kick Sponsor Tracker for Streamers, Brands and Promo Codes](https://apify.com/cleanscrape/kick-sponsor-tracker): which Kick streamers promote which brands, with codes and broadcast hours
- [Whatnot Scraper for Listings and Live Shows](https://apify.com/cleanscrape/whatnot-scraper): Whatnot listings with prices and seller stats, and live shows
- [Whatnot Seller Tracker for Top Sellers and Sales](https://apify.com/cleanscrape/whatnot-seller-tracker): top sellers per category, items sold, sales per day and followers over time
- [TikTok Shop Product Scraper](https://apify.com/cleanscrape/tiktok-shop-product-scraper): US TikTok Shop prices, sellers and ratings
- [Bilibili Scraper (哔哩哔哩) for Videos, Comments and Danmaku](https://apify.com/cleanscrape/bilibili-scraper): Bilibili videos, danmaku, comments and creators
- [App Store Reviews & Google Play Reviews Scraper (Play Store)](https://apify.com/cleanscrape/app-store-reviews-scraper): reviews from both app stores in one table
- [Google Trends Scraper API for Interest Over Time](https://apify.com/cleanscrape/google-trends-scraper): search interest over time, by region, related queries and trending searches
- [Map Your Show Exhibitor List Scraper for Trade Shows](https://apify.com/cleanscrape/event-exhibitor-monitor): trade show exhibitor lists and booth changes
- [Shopify Product Reviews Scraper for Judge.me and Okendo](https://apify.com/cleanscrape/shopify-reviews-scraper): Judge.me and Okendo reviews from Shopify product links
- [Google News Scraper and RSS Feed Reader](https://apify.com/cleanscrape/google-news-scraper): headlines from Google News and publisher feeds
- [Google Jobs Scraper for Job Search, Listings and Salaries](https://apify.com/cleanscrape/google-jobs-scraper): job listings with salaries and apply links
- [Pinterest Scraper API](https://apify.com/cleanscrape/pinterest-scraper): keyword search, public pin links and board previews; search results may lack a pin link
- [Google Hotels Scraper for Google Travel Hotel Prices](https://apify.com/cleanscrape/google-hotels-scraper): hotel prices and booking offers for your dates
- [Meta Threads Scraper for Posts and Replies](https://apify.com/cleanscrape/threads-scraper): public Threads posts from accounts or post links
- [Likee Scraper API](https://apify.com/cleanscrape/likee-scraper): Likee videos and comments
- [Casino Bonus Checker for Affiliate and Review Sites](https://apify.com/cleanscrape/casino-bonus-checker): the casino bonus each affiliate and review site shows, with promo codes, 18+ notices and affiliate IDs
- [Video Frame Extractor for Scene Changes and Thumbnails](https://apify.com/cleanscrape/video-frame-extractor): still images from video files at scene changes, intervals or timestamps, with contact sheets
- [Career Site Job Listings from Workday, Greenhouse and Lever](https://apify.com/cleanscrape/career-site-jobs-scraper): open jobs from company career pages, with salaries and new or closed jobs per company
- [Economic Calendar Scraper for Official Release Dates](https://apify.com/cleanscrape/economic-calendar-api): central bank decisions and economic releases with dates and times
- [Audio Transcription and Speech to Text for Podcasts](https://apify.com/cleanscrape/podcast-transcription): podcast episodes and audio files to text with timestamps and subtitles
- [Google Shopping Scraper and Price Tracker](https://apify.com/cleanscrape/google-shopping-scraper): product prices, stores and ratings from Google Shopping, each store’s price for a product, and price changes on a schedule

# Actor input Schema

## `channels` (type: `array`):

Paste public channel names or links, one per line. Examples: @TelegramTips, https://t.me/TelegramTips or a link to one post.

## `maxPosts` (type: `integer`):

The most posts to save per channel. Actual results can be lower.

## `period` (type: `string`):

Limit posts by publication date. The post and page limits still apply.

## `startDate` (type: `string`):

For Custom dates only. Leave empty for no lower date limit.

## `endDate` (type: `string`):

For Custom dates only. Includes the entire day in UTC.

## `search` (type: `string`):

Optional phrase to search in the channels you supplied. Telegram chooses matches. Applies to channel inputs, not individual post links.

## `includeWords` (type: `array`):

Keep posts containing any of these words or phrases in their text. Case does not matter.

## `excludeWords` (type: `array`):

Skip posts containing any of these words or phrases in their text.

## `includeComments` (type: `boolean`):

Also save recent public comments in their own table, when available.

## `commentsPerPost` (type: `integer`):

Maximum recent comments to save for each collected post. Telegram may expose fewer.

## `onlyNew` (type: `boolean`):

For scheduled runs: save only posts that earlier runs with the same watch name did not save. The first run saves the newest posts as the starting point; later runs save what was published since. A run cut short by Posts per channel or a limit continues where it stopped on the next run, so no new post is skipped.

## `watchName` (type: `string`):

Leave empty, and runs with the same channels share one history. Or give a name, such as "Crypto news channels", to keep the history when you change the channel list. Changing the search or the words starts a new history.

## `maxPages` (type: `integer`):

Stops long or narrow searches after this many pages. Each page usually contains about 20 posts.

## `maxRequests` (type: `integer`):

Safety limit for all source requests, including comments and retries.

## Actor input object example

```json
{
  "channels": [
    "TelegramTips"
  ],
  "maxPosts": 20,
  "period": "all",
  "includeComments": false,
  "commentsPerPost": 20,
  "onlyNew": false,
  "maxPages": 50,
  "maxRequests": 500
}
```

# Actor output Schema

## `posts` (type: `string`):

No description

## `media` (type: `string`):

No description

## `comments` (type: `string`):

No description

## `channels` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "channels": [
        "TelegramTips"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("cleanscrape/telegram-channel-messages-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "channels": ["TelegramTips"] }

# Run the Actor and wait for it to finish
run = client.actor("cleanscrape/telegram-channel-messages-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "channels": [
    "TelegramTips"
  ]
}' |
apify call cleanscrape/telegram-channel-messages-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,cleanscrape/telegram-channel-messages-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/w7Fzi2lBS3FTcNhtJ/builds/4PZkGbh1Vmb5Jp7MS/openapi.json
