# Telegram Channel Scraper: Messages, Views, Media & Polls (`stratumics/telegram-channel-scraper`) Actor

Get messages from public Telegram channels with views, dates, media, reactions, polls and forwards, plus channel info with exact subscriber counts. No login or bot token needed.

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

## Pricing

from $0.60 / 1,000 messages

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 Scraper** collects messages from public Telegram channels: text, posting time, views, photos and videos, reactions, polls, forwards, links and hashtags, plus a profile for each channel with its exact subscriber count. It reads the public web preview at [t.me](https://t.me), so it works as a **Telegram API alternative** with no Telegram account, no phone number and no bot token.

It reads public channels only. Private channels, groups and chats stay out of reach, and it never logs in.

### What does Telegram Channel Scraper do?

Give it channel usernames (`durov`), @handles (`@durov`) or links (`https://t.me/durov`) and it returns one clean record per message, newest first:

- **Messages**: plain text (HTML optional), exact posting time, view count as a number, edit mark and author signature.
- **Media**: photos, videos and round videos with their length, documents and audio with file names, voice notes, stickers, locations and link previews.
- **Reactions**: every reaction with its count, including paid Telegram Stars, plus a total per message.
- **Polls and quizzes**: the question, each option with its share of the votes, and the number of voters.
- **Forwards and replies**: the original channel, link and message number of a forwarded post, and the message a reply answers.
- **Links, hashtags, mentions and buttons** pulled out of every message.
- **Channel profiles**: title, description, exact subscriber count, photo, verified badge, links in the description, and photo, video, file and link counts.

### Why use this Telegram scraper?

- **No login of any kind.** No API id, no phone number, no bot token, and no account that can be banned.
- **Exact subscriber counts.** Profiles carry the real number (10,345,409), not the rounded "10.3M" the preview shows.
- **Forward sources that are always filled in.** The plain preview page sometimes blanks out "Forwarded from" names. This scraper asks for the version of the page that always includes them.
- **Jump straight to a date.** Ask for messages from before 1 January 2024 in a news channel that has posted over 150,000 messages, and it lands there in 18 requests instead of paging through about 3,600 pages.
- **Date ranges that stop early.** With "newer than", paging stops at the first older message, so you only pay for what is in range.
- **Monitoring with no gaps and no repeats.** Turn on "Only new messages" and schedule the run. Each run returns what was posted since the last one, oldest first, and remembers its place per channel, even when a run stops at your spending limit.
- **Keyword search that keeps going.** Telegram's own search stops after about 20 matches. The scraper uses it for the newest matches, then keeps reading older history and matching your words itself.
- **Fast and light.** Plain web requests, about 20 messages per request, 10 channels in parallel. 500 messages from 5 channels took 15 seconds in testing.
- **You pay for results only.** Service messages ("channel created", "message pinned"), skipped messages and errors are never charged.

On top of that you get everything the Apify platform offers: scheduled runs, an API, webhooks, run history, and exports to JSON, CSV, Excel and more.

### What data can you extract from Telegram?

| Field | What it holds | Example |
|---|---|---|
| `channelUsername`, `channelTitle` | The channel the message belongs to | `durov`, `Pavel Durov` |
| `messageId`, `url` | Message number and direct link | `552`, `https://t.me/durov/552` |
| `date` | Posting time, ISO 8601 in UTC | `2026-10-11T14:52:40.000Z` |
| `text` | Message text or caption, emoji and line breaks kept | `Designers × AI ...` |
| `views` | View count as a number | `1040000` |
| `reactions`, `reactionsTotal` | Each reaction with its count, and their sum | `27370` |
| `media` | Photos, videos, documents, audio, voice, stickers, polls, link previews | `[{ "type": "video", "durationSeconds": 75 }]` |
| `poll` | Question, options with vote share, voter count | `{ "voters": 3270 }` |
| `forwardedFrom` | Original channel, link and message number | `{ "username": "designers" }` |
| `replyToMessageId` | The message this one replies to | `146472` |
| `links`, `hashtags`, `mentions`, `buttons` | Everything linkable inside the message | `["designers"]` |
| `subscribers` (channel records) | Exact subscriber count | `10345409` |

Every record has a `type` field: `message` for posts, `channel` for profiles. The full list of fields, with descriptions, is on the Dataset tab of the output.

### How to scrape Telegram channels

1. Open Telegram Channel Scraper in Apify Console and click **Try for free**.
2. In **Channels**, enter usernames, @handles or t.me links, one per line.
3. Set **Max messages per channel**. The default is 100. Set 0 to collect only channel profiles.
4. Optionally add a date range, a search word, or turn on monitoring.
5. Click **Start**. When the run finishes, download the data as JSON, CSV or Excel, or read it through the API.

### How much does it cost to scrape Telegram?

The scraper uses pay-per-event pricing, so you pay for what you get and nothing else:

| Event | Price |
|---|---|
| Message saved | $0.80 per 1,000 ($0.0008 each) |
| Channel profile saved | $0.001 each |

A small fee per run start may also apply; the **Pricing** tab always shows the current prices.

Larger Apify plans pay less automatically: messages cost $0.70 per 1,000 on Scale and $0.60 on Business.

Worked examples:

- **1,000 messages from 5 channels with profiles** cost 1,000 × $0.0008 + 5 × $0.001 = **about $0.81**.
- **A monitor that runs every hour** over 5 channels and finds 10 new messages each time costs about $0.008 per run, or **about $5.80 a month**. Turn off channel profiles in monitoring runs if you do not need a fresh subscriber count every hour.
- Apify's free plan includes $5 of monthly usage, which covers **about 6,000 messages**.

Set **Maximum cost per run** in the run options to cap your spend. The scraper stops cleanly at that amount, keeps everything collected so far, and in monitoring mode the next run continues exactly where this one stopped.

### Input

See the **Input** tab for every option. A typical input:

```json
{
    "channels": ["durov", "@telegram", "https://t.me/bbcpersian"],
    "maxMessagesPerChannel": 200,
    "newerThan": "30 days",
    "includeChannelInfo": true
}
```

- **Channels**: usernames, @handles or links, including links to a single post. Private invite links (`t.me/+...`) cannot be read and are skipped with a warning.
- **Only messages newer than / older than**: a date (`2026-10-01`), a date and time in UTC (`2026-10-01T12:00:00Z`), or a relative value (`7 days`, `12 hours`, `3 months`). Use both for a window, such as one day of a news channel.
- **Search inside each channel**: one or more words; a message must contain all of them. Hashtags such as `#ai` work too.
- **Only new messages (monitoring mode)** with a **Monitor name**: the scraper remembers the last message delivered per channel under that name. Use one name per schedule.
- **Include message HTML**: adds a `textHtml` field with bold, links and quotes kept.
- **Channels in parallel** and **Proxy configuration**: rarely needed. Telegram's preview answers without a proxy; if it starts throttling, the scraper switches to Apify datacenter proxy by itself.

### Output

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel. Three records from a real run, trimmed:

```json
[
    {
        "type": "message",
        "channelUsername": "durov",
        "channelTitle": "Pavel Durov",
        "channelId": 1006503122,
        "messageId": 552,
        "url": "https://t.me/durov/552",
        "date": "2026-10-11T14:52:40.000Z",
        "text": "✨ Designers × AI\n\n🆕 The mockup era is over. Today’s AI tools give every designer a superpower: you can now craft your ideas, not just draw them. ...",
        "views": 1040000,
        "authorSignature": "Pavel Durov",
        "forwardedFrom": { "name": "Telegram Designers", "url": "https://t.me/designers/266", "username": "designers", "messageId": 266 },
        "replyToMessageId": null,
        "isEdited": false,
        "media": [
            { "type": "video", "url": null, "thumbnailUrl": "https://cdn4.telesco.pe/file/o7BWfq8rgMp2Xz0pGEz2...", "durationSeconds": 75, "fileName": null, "fileSize": null, "performer": null }
        ],
        "linkPreview": null,
        "links": [],
        "hashtags": [],
        "mentions": ["designers"],
        "reactions": [
            { "emoji": "⭐", "customEmojiId": null, "isPaid": true, "count": 5720 },
            { "emoji": null, "customEmojiId": "5936157098181135162", "isPaid": false, "count": 12300 }
        ],
        "reactionsTotal": 27370,
        "poll": null,
        "buttons": [],
        "scrapedAt": "2026-10-17T23:27:14.025Z"
    },
    {
        "type": "message",
        "channelUsername": "rbc_news",
        "channelTitle": "РБК. Новости. Главное",
        "channelId": 1099860397,
        "messageId": 158878,
        "url": "https://t.me/rbc_news/158878",
        "date": "2026-10-17T11:00:04.000Z",
        "text": null,
        "views": 40800,
        "media": [{ "type": "poll", "url": "https://t.me/rbc_news/158878", "thumbnailUrl": null, "durationSeconds": null, "fileName": null, "fileSize": null, "performer": null }],
        "reactions": [
            { "emoji": "🤣", "customEmojiId": null, "isPaid": false, "count": 45 },
            { "emoji": "👍", "customEmojiId": null, "isPaid": false, "count": 5 }
        ],
        "reactionsTotal": 113,
        "poll": {
            "question": "Работодатели в этом году не спешат бронировать площадки под новогодние корпоративы. ... А что для вас корпоратив?",
            "type": "Anonymous Poll",
            "options": [
                { "text": "Возможность отдохнуть и расслабиться с коллегами", "percent": 19 },
                { "text": "Лучше премия или дополнительный выходной", "percent": 54 }
            ],
            "voters": 3270
        },
        "scrapedAt": "2026-10-17T23:27:14.221Z"
    },
    {
        "type": "channel",
        "username": "durov",
        "channelId": 1006503122,
        "title": "Pavel Durov",
        "description": "Founder of Telegram.",
        "subscribers": 10345409,
        "photoUrl": "https://cdn4.telesco.pe/file/TJlcB2FMC5MFuE1r78AGKLAjjuxstW5Xk...",
        "isVerified": true,
        "links": [],
        "photoCount": 102,
        "videoCount": 47,
        "fileCount": 0,
        "linkCount": 200,
        "hasPublicPreview": true,
        "url": "https://t.me/durov",
        "scrapedAt": "2026-10-17T23:27:14.021Z"
    }
]
```

Each run also saves a `SUMMARY` record in its key-value store with the status of every channel (done, preview turned off, not found, not a channel, failed), the number of messages collected and the reason for any problem.

### Tips for scraping Telegram

- **Start small.** Run 20 messages from one channel to see the data before a large run.
- **Collect a period of history.** Combine "newer than" and "older than". The scraper jumps to the end of the period and reads backwards only through the messages inside it.
- **Follow channels.** Schedule a monitoring run every hour or every day. Each channel and search word gets its own memory, so you can add channels to a monitor at any time.
- **Searching for a rare word in a very large channel?** Add a date range so the run reads only that period.
- **Download media you want to keep.** Photo and video links come from Telegram's servers and expire after a while.
- **Views and reaction counts above 1,000 are rounded by Telegram** ("12.4K" arrives as 12400). Subscriber counts on channel profiles are exact.
- **Albums count as one message.** A post with five photos is one record with five items in `media`.
- **A channel with no messages?** Its owner may have turned off the web preview. You still get its profile, and the `SUMMARY` record says what happened.

### Integrations and API

- **API**: start runs and read results over HTTP from any language. See the **API** tab for ready-made requests.
- **JavaScript**:

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('stratumics/telegram-channel-scraper').call({
    channels: ['durov', 'telegram'],
    maxMessagesPerChannel: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((item) => item.type === 'message').length);
```

- **Python**:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("stratumics/telegram-channel-scraper").call(
    run_input={"channels": ["durov"], "maxMessagesPerChannel": 50, "newerThan": "7 days"}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    if item["type"] == "message":
        print(item["date"], item["views"], (item["text"] or "")[:80])
```

- **No-code tools**: connect runs to Zapier, Make, n8n, Google Sheets, Slack or your own webhook from the **Integrations** tab, for example to post new messages from a monitored channel into a team chat.
- **AI agents**: add the Actor to any agent or chat app that supports the Model Context Protocol through the Apify MCP server at `https://mcp.apify.com?tools=stratumics/telegram-channel-scraper`, then ask in plain words, such as "get this week's posts from @durov with more than a million views".

### FAQ

#### Do I need a Telegram account, phone number or bot token?

No. The scraper reads the same public preview pages anyone can open in a browser at `t.me/s/<channel>`.

#### Can it scrape private channels, groups or chats?

No. Only public channels with a web preview can be read without joining them.

#### How many messages can I get from one channel?

As many as the channel's public history holds. Set **Max messages per channel** as high as you need, or use a date range.

#### Why does my keyword search return few results?

A message must contain all the words you entered, at the start of a word ("bitcoin" also finds "bitcoins"). Try a single word, or check its spelling in the channel's language.

#### Why are a few message numbers missing?

Deleted messages leave gaps, and the photos of an album share one record. Service messages such as "channel created" are skipped.

#### Is it legal to scrape Telegram?

Our Actors are ethical and do not extract any private user data, such as email addresses, gender, or location. They only extract what the user has chosen to share publicly. We therefore believe that our Actors, when used for ethical purposes by Apify users, are safe. However, you should be aware that your results could contain personal data. Personal data is protected by the GDPR in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.

This scraper reads public channel posts only. Posts can still name people: author signatures, mentions and forward sources are personal data in some cases, so collect and keep only what you need. Telegram is a trademark of its owner, and this tool is not affiliated with or endorsed by Telegram.

#### Something looks wrong. Where do I report it?

Open an issue on the **Issues** tab with the run link and the channel. Most problems can be reproduced and fixed quickly.

### Other tools from this developer

### Other tools from Stratum ICS

- [App Store Reviews Scraper](https://apify.com/stratumics/app-store-reviews-scraper): Get Apple App Store reviews with star ratings, titles, text, app versions, helpful votes and developer replies, well past Apple's 500-review limit, for any country, plus app ratings.
- [Google Maps Scraper](https://apify.com/stratumics/google-maps-scraper): Get the businesses on Google Maps for any search and area: name, address, phone, website, rating, review count, opening hours, plus emails and social profiles.
- [Google News Scraper](https://apify.com/stratumics/google-news-scraper): Get Google News articles with real publisher URLs (not Google redirects), source, date, image, author and optional full text.
- [Google Play Reviews Scraper](https://apify.com/stratumics/google-play-reviews-scraper): Get Google Play reviews with star ratings, text, app versions, thumbs-up counts, developer replies and feature ratings in any language, plus app details with installs and star histogram.
- [Google Trends Scraper](https://apify.com/stratumics/google-trends-scraper): Get Google Trends data as JSON, CSV or Excel: interest over time, interest by region and city, related queries, and trending searches by country.
- [LinkedIn Jobs Scraper](https://apify.com/stratumics/linkedin-jobs-scraper): Scrape LinkedIn jobs with full descriptions, salary ranges, seniority, job type and applicant counts.
- [Website Contact Scraper](https://apify.com/stratumics/website-contact-scraper): Turn a list of websites into one row per company with verified emails, formatted phone numbers, social profiles (LinkedIn, Facebook, Instagram, X), address and contact page.
- [YouTube Scraper](https://apify.com/stratumics/youtube-scraper): Get YouTube videos from searches, channels, playlists and links with exact views, likes, comment counts, dates and tags, plus channel profiles and comments.

# Actor input Schema

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

Public Telegram channels to scrape. Enter usernames (durov), @handles (@durov) or links (https://t.me/durov, https://t.me/s/durov, or a link to any post). Private invite links (t.me/+...) cannot be read.

## `maxMessagesPerChannel` (type: `integer`):

The most messages to collect from each channel, newest first. Set 0 to collect only the channel profile (title, subscribers, description). Combine a high limit with a date range to get everything in that range.

## `newerThan` (type: `string`):

Keep messages posted on or after this date. Use a date (2026-10-01), an ISO date-time in UTC (2026-10-01T12:00:00Z), or a relative value such as "7 days" or "12 hours". Paging stops as soon as messages get older than this, so you only pay for what is in the range. Leave empty for no lower limit.

## `olderThan` (type: `string`):

Keep messages posted before this date (the date itself is excluded). Same formats as above. The scraper jumps straight to this point in the channel history instead of paging through newer messages. Leave empty for no upper limit.

## `searchQuery` (type: `string`):

Return only messages that match this word or phrase, using Telegram's own in-channel search (a #hashtag works too). Leave empty to collect every message.

## `includeChannelInfo` (type: `boolean`):

Add one record per channel with its title, description, exact subscriber count, photo, verified badge, links in the description, and photo, video, file and link counts.

## `includeTextHtml` (type: `boolean`):

Also save each message's formatted text as HTML (bold, links, quotes, custom emoji) in the textHtml field. Plain text is always included.

## `onlyNewMessages` (type: `boolean`):

Remember the last message delivered from each channel and, on later runs, return only messages posted after it, oldest first, with no gaps and no repeats. The first run returns the latest messages up to your limit. Run it on a schedule to follow channels.

## `monitorName` (type: `string`):

Name of the memory used by monitoring mode. Runs with the same name share it, so use one name per schedule. Letters, digits and hyphens only.

## `maxConcurrency` (type: `integer`):

How many channels to scrape at the same time. Each channel's history is read page by page.

## `proxyConfiguration` (type: `object`):

Telegram's preview pages normally answer without a proxy, so none is used by default. If t.me starts throttling, the scraper switches to Apify datacenter proxy by itself. Choose a proxy here to use it for every request.

## Actor input object example

```json
{
  "channels": [
    "durov",
    "@telegram",
    "https://t.me/bbcpersian"
  ],
  "maxMessagesPerChannel": 100,
  "newerThan": "",
  "olderThan": "",
  "searchQuery": "bitcoin",
  "includeChannelInfo": true,
  "includeTextHtml": false,
  "onlyNewMessages": false,
  "monitorName": "default",
  "maxConcurrency": 10,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `messages` (type: `string`):

One record per message and one per channel profile, told apart by the type field.

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

Status, message count and any problem for each channel.

# 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": [
        "durov",
        "telegram"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("stratumics/telegram-channel-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": [
        "durov",
        "telegram",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("stratumics/telegram-channel-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": [
    "durov",
    "telegram"
  ]
}' |
apify call stratumics/telegram-channel-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,stratumics/telegram-channel-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/oRZhPybwG38vYORCm/builds/HzhcoxQpGsc00n7xM/openapi.json
