# Telegram Channel Scraper: Posts, Views & Stats (No Login) (`weyne/telegram-channel-scraper`) Actor

Scrape posts from public Telegram channels without login, phone number or API keys: text, views, reactions, media, forwards, replies, links. Or get channel analytics: subscribers, average views, engagement and posting frequency.

- **URL**: https://apify.com/weyne/telegram-channel-scraper.md
- **Developed by:** [Артем Димко](https://apify.com/weyne) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 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.

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

### What does Telegram Channel Scraper do?

**Telegram Channel Scraper** extracts posts and statistics from **public Telegram channels** using Telegram's own public web preview (`t.me/s/<channel>`).

- ✅ **No login, no phone number, no Telegram API keys, no bot token**
- ✅ Text, **views**, **reactions** (with emoji), **paid Stars**, date, author signature
- ✅ Photos, videos (with duration and thumbnail), albums, documents, polls
- ✅ Forwards, replies, link previews, links, #hashtags and @mentions
- ✅ **Search inside channels** by keyword or hashtag
- ✅ **Date filters**: "last 7 days", "newer than 2026-01-01", etc.
- ✅ **Channel stats mode**: subscribers, average & median views, engagement rate, posting frequency, top post — one row per channel
- ✅ Export to JSON, CSV, Excel, or use via API, MCP, Make, Zapier and n8n

### Why this Telegram scraper? Built from other users' complaints

We read the reviews and issues of other Telegram scrapers and fixed every common problem:

| Common complaint about other scrapers | How this Actor handles it |
|---|---|
| "Logged me out of my Telegram", "my account got blocked", session / auth key errors | **No login, ever.** No QR code, no phone number, no session. Your Telegram account is never touched or put at risk. |
| "Got no results", "paid for nothing" | Every channel that can't be read gets a **free row explaining why**: it's a group, a bot, a personal account, it doesn't exist, or it has no posts in your dates. You pay only for real posts. |
| "Didn't scrape some public channels/groups" | Groups have no public web page, so instead of failing silently we tell you exactly that it's a group, plus how many members it has. |
| "Date filter totally wrong, charged for irrelevant messages" | Dates are filtered **before** charging, a bare date means the whole day in UTC, and the Actor stops reading a channel as soon as it reaches posts older than your date. |
| Wrong or empty dates on video posts | The publish date is always taken from the post's own timestamp, never from the video duration. |
| Paying again for the same posts on every scheduled run | **"Only posts not returned in previous runs"** remembers what you already got. |
| Media links stop working | Optional **"Save photos permanently"** copies photos to your run storage. |
| "Schema validation failed" / crashes on input | Paste channels any way you like: one per line, comma-separated, with @ or full links. Invalid values are skipped with a clear message instead of failing the run. |
| No reply from the developer | Issues are answered within 24 hours. You don't need to dig up a run ID, just describe what happened. |

#### What it can't do (so you don't waste money)

- ❌ **Scrape members or subscribers** of channels or groups — Telegram doesn't make member lists public.
- ❌ **Add members to groups** or send messages — this is a read-only data tool.
- ❌ **Read private channels, groups or invite links** (t.me/+...) — only public channels are visible without an account.
- ❌ **Comments under posts** — they are not part of Telegram's public web preview.

### Why scrape Telegram channels?

- **Media monitoring & news tracking** – follow dozens of news channels and get every new post in a spreadsheet or webhook.
- **Brand & keyword monitoring** – search channels for your brand, competitor or product name.
- **Influencer & ad research** – before buying an ad in a channel, check real average views vs. subscribers, posting frequency and engagement.
- **Research & AI datasets** – collect clean text with dates and engagement for analysis or LLM pipelines.
- **Crypto, finance & OSINT** – archive channels and react to new posts automatically.

### How to use it

1. Add one or more channels — `durov`, `@durov` or `https://t.me/durov` all work.
2. Choose **Posts** (one row per post) or **Channel stats** (one row per channel).
3. Set how many posts per channel you need, and optionally a search keyword or date range.
4. Click **Start** and download your data in any format.

Schedule the Actor (e.g. every hour with "Only posts newer than: 1 day") to build a continuous feed.

### Input example

```json
{
  "channels": ["telegram", "https://t.me/durov"],
  "mode": "posts",
  "maxPostsPerChannel": 100,
  "searchQuery": "",
  "newerThan": "30 days",
  "onlyNewPosts": false
}
```

#### Scheduled monitoring recipe

Create a task with your channels, set **"Only posts not returned in previous runs"** to on, and schedule it every hour. Each run returns only fresh posts, and you can send them to Google Sheets, Slack, Telegram or a webhook through Apify integrations.

### Output example (unavailable channel — free row)

```json
{
  "channel": "pythonchatru",
  "url": "https://t.me/pythonchatru",
  "status": "group",
  "error": "@pythonchatru is a group (1 884 members, 277 online), not a channel. Telegram publishes a public web preview only for channels; reading groups requires a logged-in Telegram account, which this Actor deliberately does not use."
}
```

Possible `status` values: `group`, `bot`, `user`, `not-found`, `preview-disabled`, `no-posts`, `no-matches`, `error`. A summary for every channel is also saved to the `OUTPUT` record of the run.

### Output example (Posts mode)

```json
{
  "channel": "durov",
  "postId": 280,
  "url": "https://t.me/durov/280",
  "date": "2024-06-06T15:57:50+00:00",
  "text": "Big day today, we're launching Telegram Stars ⭐️ – a way to pay for digital services in mini apps...",
  "views": 3160000,
  "reactions": [{ "emoji": "❤‍🔥", "count": 13700 }, { "emoji": "🫡", "count": 4980 }],
  "reactionsTotal": 18680,
  "paidStars": 538,
  "author": "Pavel Durov",
  "isEdited": true,
  "isForwarded": false,
  "forwardedFrom": null,
  "replyTo": null,
  "photos": [],
  "videos": [],
  "documents": [],
  "poll": null,
  "isAlbum": false,
  "mediaCount": 0,
  "linkPreview": {
    "url": "https://telegram.org/blog/telegram-stars",
    "siteName": "Telegram",
    "title": "Telegram Stars: Pay for Digital Goods and More",
    "description": "Over 400 million users interact with bots and mini apps on Telegram every month",
    "image": "https://cdn4.telesco.pe/file/..."
  },
  "links": ["https://telegram.org/blog/telegram-stars"],
  "hashtags": [],
  "mentions": [],
  "channelTitle": "Pavel Durov",
  "channelSubscribers": 10300000,
  "channelVerified": true,
  "scrapedAt": "2026-10-20T08:00:00.000Z"
}
```

### Output example (Channel stats mode)

Values below are illustrative.

```json
{
  "channel": "durov",
  "title": "Pavel Durov",
  "description": "Founder of Telegram.",
  "verified": true,
  "subscribers": 10300000,
  "photosCount": 102,
  "videosCount": 47,
  "linksCount": 200,
  "postsAnalyzed": 20,
  "lastPostDate": "2026-10-11T14:52:40.000Z",
  "daysSinceLastPost": 8.7,
  "postsPerDay": 0.21,
  "avgViews": 2150000,
  "medianViews": 1900000,
  "maxViews": 4060000,
  "avgReactions": 61000,
  "viewsToSubscribersPct": 20.87,
  "reactionsToViewsPct": 2.84,
  "shareWithMedia": 0.65,
  "shareForwarded": 0.05,
  "topReactions": [{ "emoji": "❤‍🔥", "count": 410000 }],
  "topPost": { "url": "https://t.me/durov/284", "views": 4060000, "date": "2024-06-23T13:09:52+00:00", "text": "..." }
}
```

### How much does it cost?

You pay only for results: a small fee **per post** saved, or **per channel** in Channel stats mode. See the Pricing tab for exact prices. You can set a maximum cost per run in the run options — the Actor stops cleanly when the limit is reached.

### Tips

- **Views and subscribers** are shown by Telegram rounded (e.g. `1.45M`); the Actor converts them to numbers (`1450000`).
- **Albums** (several photos in one post) come as one row with all photos in `photos`.
- Use **"Only posts newer than"** for scheduled monitoring — the Actor stops paging as soon as it reaches older posts, so runs stay fast and cheap.
- Channels that can't be read get a free explanatory row (see above) and are never charged.
- Photos: Telegram's image links expire after some time. Turn on **Save photos permanently** if you need to keep them; links appear in `photosStored`.

### Limitations

- Works only with **public channels** that have Telegram's web preview enabled. Private channels, groups that require joining, and invite links (`t.me/+...`) are not supported.
- Comments under posts are not available in the public preview.
- Media URLs point to Telegram's CDN and can expire after some time — use **Save photos permanently** for photos; videos are returned as links only.

### Is it legal to scrape Telegram?

This Actor reads only public pages that Telegram itself publishes on the open web at `t.me/s/...`, the same as any visitor without an account sees. It does not log in, bypass access controls or collect private messages. Posts may still contain personal data; if you process it, make sure you have a legitimate reason and comply with laws such as GDPR. When in doubt, consult a lawyer.

### Feedback

Found a bug or need an extra field? Open an issue in the **Issues** tab — we reply within 24 hours and fixes usually ship within a day.

# Actor input Schema

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

Public Telegram <b>channels</b>: a username (<code>durov</code>), <code>@durov</code> or a link (<code>https://t.me/durov</code>). You can paste many at once. Groups, personal accounts, bots and private invite links (t.me/+...) have no public web page, so they are reported as unavailable and never charged.

## `mode` (type: `string`):

<b>Posts</b>: one row per post. <b>Channel stats</b>: one row per channel with subscribers, average/median views, engagement, posting frequency and the top post, calculated from the latest posts.

## `maxPostsPerChannel` (type: `integer`):

How many of the newest posts to take from each channel. In Channel stats mode, how many recent posts are analyzed. You are never charged for more posts than this.

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

Optional. Only posts containing this word or phrase (Telegram's own channel search). Hashtags work too, e.g. <code>#news</code>.

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

Optional. A date (<code>2026-01-31</code>, start of the day in UTC) or a period (<code>24 hours</code>, <code>7 days</code>, <code>2 weeks</code>, <code>3 months</code>). The Actor stops reading a channel as soon as it reaches older posts, and older posts are never charged.

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

Optional. A date (<code>2025-12-31</code> includes that whole day, UTC) or a period like <code>30 days</code>. Useful for archives.

## `onlyNewPosts` (type: `boolean`):

Remembers the newest post returned for each channel (and search) and next time returns only newer ones. Perfect for scheduled monitoring: you never pay twice for the same post.

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

Adds channelTitle, channelSubscribers and channelVerified to every post row.

## `downloadPhotos` (type: `boolean`):

Telegram's image links expire after a while. When enabled, photos are copied to this run's storage and permanent links are added in <code>photosStored</code>. Makes runs slower.

## `reportUnavailableChannels` (type: `boolean`):

For each channel that can't be read (group, bot, private, doesn't exist) or has no matching posts, adds one free row with <code>status</code> and <code>error</code> so you know exactly why. These rows are never charged.

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

Datacenter proxy is enough for most runs.

## Actor input object example

```json
{
  "channels": [
    "telegram",
    "durov"
  ],
  "mode": "posts",
  "maxPostsPerChannel": 20,
  "onlyNewPosts": false,
  "includeChannelInfo": true,
  "downloadPhotos": false,
  "reportUnavailableChannels": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

All rows of the run: posts (Posts mode), channel analytics (Channel stats mode) and free rows that explain unavailable channels.

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

Status, number of posts and the reason for every channel in the input.

# 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": [
        "telegram",
        "durov"
    ],
    "maxPostsPerChannel": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("weyne/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": [
        "telegram",
        "durov",
    ],
    "maxPostsPerChannel": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

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

```

## MCP server setup

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