# Telegram Channel Scraper & Monitor: New Posts, Views (`kislov-data/telegram-channel-monitor`) Actor

Scrape posts from public Telegram channels (text, date, views, reactions, media links, link previews, polls) and monitor only the new or edited ones between runs. Keyword and view filters. No login, no proxies, pay per post.

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

## Pricing

from $1.00 / 1,000 post returneds

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 & Monitor: public posts, views and new-post tracking

Read posts from **public Telegram channels** and get a clean, structured record for every post: text, date, views, reactions, photo and video links, link previews, polls, hashtags and links. Turn on **monitor mode** and each run returns only the **new or edited posts** since the last run.

It reads the public web preview that Telegram serves for channels (`t.me/s/<channel>`): no login, no browser, no proxies, so runs are fast, cheap and stable.

### What you can do with it

- **News and media monitoring:** watch channels and get new posts into Slack, Google Sheets, Make, n8n, Zapier or your own webhook.
- **Brand and keyword tracking:** filter posts by keyword and minimum views.
- **Crypto, finance and market research:** follow announcement channels and measure what gets attention (views and reactions).
- **Competitor and content research:** see which posts perform, how often a channel posts and what it links to.
- **Datasets for analysis:** export posts as JSON, CSV or Excel.

### Why this Actor

- **Monitor mode built in.** Switch on `onlyNewPosts` and schedule the Actor. After the first run it returns only what is new or edited. The state is kept in your own account, per channel.
- **Edits are detected.** A changed post text comes back with `changeStatus: "updated"`. Changing view counts do not count as edits.
- **Rich, flat records.** Views, reaction counts by emoji, media type flags, photo and video links, link preview (site, title, description), poll question and options, outgoing links, hashtags, reply and forward references.
- **Filters.** Keywords, excluded keywords, minimum views, posted within N days.
- **Flexible input.** `telegram`, `@durov`, `https://t.me/bbcrussian` or `https://t.me/s/bbcrussian` all work. Invalid entries are reported instead of failing the run.
- **Cheap and predictable.** Pay per post returned. Channels that are not available cost nothing.

### Channel analytics (optional, no extra charge)

Turn on `analytics` and the run also writes an `ANALYTICS` record to the default key-value store, one section per channel:

- **Reach:** median, mean, 90th percentile and best views; median reach rate (views per subscriber).
- **Reactions:** median per post, reactions per view.
- **Best posts:** top 10 by views and top 10 by reactions per view.
- **Timing:** best posting hours and weekdays by median views (UTC, only buckets with at least 3 posts).
- **Formats:** how text-only, photo, video, link, poll and document posts perform.
- **Text length:** short, medium and long posts compared.
- **Topics:** most frequent terms, hashtags and linked domains.
- **Shares:** forwards, edited posts, posts with media.

Use 100 or more posts per channel for meaningful numbers. You pay only for the posts returned, as usual.

### Input

```json
{
  "channels": ["telegram", "@durov", "https://t.me/bbcrussian"],
  "maxPostsPerChannel": 100,
  "keywords": ["bitcoin", "airdrop"],
  "minViews": 1000,
  "trackChanges": true,
  "onlyNewPosts": true
}
```

| Field | What it does |
|---|---|
| `channels` | Public channel names, handles or links. |
| `maxPostsPerChannel` | Newest posts to return per channel (default 20, up to 5,000). In monitor mode, later runs return every new post since the previous run, up to 1,000 per channel. |
| `keywords` / `excludeKeywords` | Keep posts that contain / skip posts that contain these words (post text, poll question, link title). |
| `minViews` | Keep only posts with at least this many views. |
| `postedWithinDays` | Keep only posts from the last N days. |
| `includeMedia` | Include photo, video and thumbnail links (default on). |
| `analytics` | Also write the `ANALYTICS` record described above (default off). |
| `trackChanges` | Mark each post `new`, `updated` or `unchanged` and remember it for next time. |
| `onlyNewPosts` | Monitor mode: from the second run on, return only new or edited posts. Implies `trackChanges`. |
| `stateName` | Name of the key-value store that remembers previous runs. Use a different name for each monitoring job. |
| `concurrency` | Channels loaded in parallel (default 3). |

### Output

```json
{
  "id": "durov/548",
  "postId": 548,
  "channel": "durov",
  "channelTitle": "Pavel Durov",
  "channelSubscribers": 10500000,
  "url": "https://t.me/durov/548",
  "date": "2026-09-11T16:04:02+00:00",
  "text": "…",
  "views": 2070000,
  "reactions": [{"emoji": "👍", "count": 51200}],
  "reactionsTotal": 71550,
  "edited": false,
  "mediaTypes": ["photo", "link_preview"],
  "photoUrls": ["https://cdn…jpg"],
  "videoUrls": [],
  "linkPreview": {"url": "https://…", "siteName": "…", "title": "…", "description": "…"},
  "links": ["https://…"],
  "hashtags": ["#news"],
  "isForward": false,
  "replyToPostId": null,
  "changeStatus": "new",
  "firstSeenAt": "2026-10-06T09:46:13+00:00"
}
```

A `SUMMARY` record in the default key-value store lists, for every channel, whether it was found, its title and subscriber count, how many posts were loaded and returned, and why a channel was skipped.

### Pricing

Pay per event: **$1.00 per 1,000 posts** returned, plus a tiny start fee. Channels that do not exist or have no public preview are not charged.

### Tips

- Schedule the Actor (hourly or daily) with `onlyNewPosts` on and connect the dataset to a webhook, Google Sheets or Slack.
- Use `maxPostsPerChannel` while testing.
- Photo and video links are Telegram CDN links; video links can expire, so download them soon if you need the files.

### Limits

- Only **public channels that have a web preview** work. Private channels, invite links, groups, bots and user accounts are not supported. Some channels switch the preview off.
- The preview shows the newest posts first, 20 per page. Very old history is reachable by raising `maxPostsPerChannel`, but each page is a separate request.
- View and reaction counts are those shown on the public preview at the time of the run.
- Deleted posts are not reported.

### Responsible use

The Actor reads only what Telegram itself serves to anyone without logging in. It does not collect member lists, user profiles, phone numbers or private chats, and it does not output author signatures or the names of people behind forwarded posts. Telegram's Terms of Service restrict automated collection of content and prohibit using platform data to train AI or machine-learning models. You are responsible for how you use the data and for complying with Telegram's terms and the laws that apply to you.

### Feedback

Found a channel that does not work or want another field? Open an issue from the Actor page and include the input you used.

# Actor input Schema

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

One entry per public channel: <code>telegram</code>, <code>@durov</code>, <code>https://t.me/bbcrussian</code> or <code>https://t.me/s/bbcrussian</code>. Only public channels that have a web preview work. Private channels, invite links, groups, bots and user accounts are not supported.

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

How many of the newest posts to return for each channel (20 posts per page loaded). In monitor mode (see <b>Only new posts</b>) every later run returns all new posts since the previous run, up to 1,000 per channel.

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

Keep only posts whose text, poll question or link title contains at least one of these words (case-insensitive). Example: <code>bitcoin</code>, <code>giveaway</code>.

## `excludeKeywords` (type: `array`):

Skip posts that contain any of these words.

## `minViews` (type: `integer`):

Keep only posts with at least this many views. 0 means no limit.

## `postedWithinDays` (type: `integer`):

Keep only posts published in the last N days. 0 means no limit.

## `includeMedia` (type: `boolean`):

Include photo, video and thumbnail links. Turn off for smaller output.

## `analytics` (type: `boolean`):

Also build an <code>ANALYTICS</code> record (key-value store, no extra charge): reach and reaction rates, best posts by views and by reactions per view, best posting hours and weekdays (UTC), performance by format (text, photo, video, link, poll), top terms, hashtags and linked domains. Works best with 100+ posts per channel (raise <b>Max posts per channel</b>).

## `trackChanges` (type: `boolean`):

Remember what was already returned and mark every post as <code>new</code>, <code>updated</code> (edited text) or <code>unchanged</code>.

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

From the second run on, return only posts that are new or edited since the last run. The first run returns the latest posts. Schedule the Actor (hourly, daily) and connect it to Slack, Google Sheets, Make, Zapier or a webhook.

## `stateName` (type: `string`):

Name of the key-value store used to remember previous runs. Use a different name for each separate monitoring job.

## `concurrency` (type: `integer`):

How many channels to load at the same time. Keep low to be gentle with Telegram.

## Actor input object example

```json
{
  "channels": [
    "telegram",
    "durov"
  ],
  "maxPostsPerChannel": 20,
  "minViews": 0,
  "postedWithinDays": 0,
  "includeMedia": true,
  "analytics": false,
  "trackChanges": false,
  "onlyNewPosts": false,
  "stateName": "telegram-monitor-state",
  "concurrency": 3
}
```

# Actor output Schema

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

No description

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

// Run the Actor and wait for it to finish
const run = await client.actor("kislov-data/telegram-channel-monitor").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("kislov-data/telegram-channel-monitor").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 kislov-data/telegram-channel-monitor --silent --output-dataset

```

## MCP server setup

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

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/7afa3JkWRtrQfbETB/builds/FpflpepO32LNwqAEA/openapi.json
