# Telegram Channel Scraper: Public Posts, Views and Reactions (`pistachio_implementation/telegram-channel-posts`) Actor

Scrape posts from public Telegram channels without login or API keys: text, date, views, reactions, photos, videos, links, hashtags, forwards and channel subscribers. Filter by date and keyword. Reads Telegram's own public web preview.

- **URL**: https://apify.com/pistachio\_implementation/telegram-channel-posts.md
- **Developed by:** [Hay Equipos](https://apify.com/pistachio_implementation) (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

$0.30 / 1,000 post saveds

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

## Telegram Channel Scraper: public posts, views and reactions

Export posts from any public Telegram channel to a clean table: text, date, views, reactions, photos, videos, documents, polls, links, hashtags, link previews and forwards, plus the channel's title and subscriber count. No Telegram account, no phone number, no API key.

The actor reads the public web preview Telegram itself serves at `t.me/s/<channel>`, the same page anyone can open in a browser. It walks back through the channel history page by page until it reaches your date or post limit.

### Who uses it

- **Crypto, markets and news analysts** tracking what channels post and how many views each post gets.
- **Brand and media monitoring** teams following mentions across channels with keyword filters.
- **Researchers** building datasets of public channel content over time.
- **Marketers** comparing channel reach and engagement before buying a placement.
- **AI pipelines** that need fresh channel text as clean JSON.

### Input

| Field | What it does |
|---|---|
| `channels` | Usernames (`telegram`), `@username`, or links (`https://t.me/durov`, `https://t.me/s/durov`) |
| `maxPostsPerChannel` | Newest first; default 100 |
| `postedAfter`, `postedBefore` | Date window, for example `2026-09-01`. Reading stops once older posts are reached |
| `keywords` | Keep only posts whose text contains one of these words |
| `includeServiceMessages` | Also keep notices like "channel photo updated" |
| `maxPosts` | Total cap across channels |

#### Example input

```json
{
    "channels": ["telegram", "https://t.me/durov"],
    "maxPostsPerChannel": 200,
    "postedAfter": "2026-06-01",
    "keywords": []
}
```

### Output

One row per post:

```json
{
    "channel": "durov",
    "channelTitle": "Pavel Durov",
    "channelSubscribers": 10600000,
    "channelVerified": true,
    "postId": 523,
    "postUrl": "https://t.me/durov/523",
    "date": "2026-06-09T19:33:51.000Z",
    "edited": false,
    "text": "A fully native Telegram app for Apple Watch is out.",
    "views": 12700000,
    "reactions": [{ "emoji": "paid star", "count": 7040 }, { "emoji": "custom:5465587407350942612", "count": 55400 }],
    "reactionsTotal": 95635,
    "mediaTypes": ["video"],
    "photoUrls": [],
    "videoCount": 1,
    "videoThumbnailUrl": "https://cdn4.telesco.pe/file/...",
    "documentNames": [],
    "poll": null,
    "links": [],
    "hashtags": [],
    "linkPreview": null,
    "forwardedFrom": null,
    "forwardedFromUrl": null,
    "isServiceMessage": false,
    "scrapedAt": "2026-09-27T06:09:41.563Z"
}
```

A `RUN_SUMMARY` record in the key value store lists each channel with its status, title, subscriber count, description and how many posts were read and saved.

Export as JSON, CSV, Excel or HTML, or use the Apify API, webhooks, Make, Zapier or the Apify MCP server.

### Pricing

Pay per event, no subscription and no platform usage charges on top:

- **$0.30 per 1,000 posts** saved ($0.0003 per post).
- Posts removed by your date or keyword filters, and channels that cannot be read, cost nothing.

### Limits

- **Public channels only.** Private channels, groups, chats and user accounts have no web preview and are reported as "no public preview" in `RUN_SUMMARY`. Some public channels also turn the preview off.
- Views and reactions are the rounded numbers Telegram shows (for example 1.48M becomes 1480000).
- Custom emoji reactions come as `custom:<id>` because Telegram's page shows them as images.
- Media links point to Telegram's CDN and expire after a while; download them soon if you need the files.
- The actor pauses 1.5 seconds between pages to stay polite, so about 800 posts a minute per run.
- Post signatures (the name of the admin who posted) are not collected.

### FAQ

**Do I need a Telegram account or API key?** No. Nothing is logged in and no session is used.

**Can it read group chats or members?** No, by design. It reads only what a public channel shows to any visitor, and it does not collect member lists, phone numbers or user profiles.

**How far back can it go?** As far as the channel's history goes. Set `postedAfter` or `maxPostsPerChannel` to control cost.

**How do I monitor a channel?** Schedule the actor daily with `postedAfter` set to yesterday, or keep the highest `postId` from the last run.

**Is this legal?** It reads pages Telegram publishes openly for anyone without logging in, at a polite rate. You are responsible for how you use the content, including copyright in the posts.

# Actor input Schema

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

One channel per line: a username (telegram), @username, or a link (https://t.me/durov or https://t.me/s/durov). Only public channels with a web preview can be read; private channels and groups cannot.

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

Newest posts first. The run moves to the next channel after this many saved posts.

## `postedAfter` (type: `string`):

Only posts from this date or later, for example 2026-09-01. Reading stops once older posts are reached.

## `postedBefore` (type: `string`):

Only posts before this date, for example 2026-09-15.

## `keywords` (type: `array`):

Keep only posts whose text contains one of these words (case does not matter). Filtered posts are free.

## `includeServiceMessages` (type: `boolean`):

Service messages are things like a changed channel photo or a pinned message notice.

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

The run stops after saving this many posts across all channels.

## Actor input object example

```json
{
  "channels": [
    "telegram",
    "durov"
  ],
  "maxPostsPerChannel": 100,
  "keywords": [],
  "includeServiceMessages": false,
  "maxPosts": 10000
}
```

# Actor output Schema

## `results` (type: `string`):

All rows the run saved to the default dataset.

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

The RUN\_SUMMARY record: counts and problems for the whole run.

# 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"
    ]
};

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

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

```

## MCP server setup

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

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/tG8j3wDQseIiiWXMe/builds/e4pktuo3uanbvqogy/openapi.json
