# Telegram Channel Monitor (`virtual-constructs/telegram-channel-monitor`) Actor

Monitor and scrape public Telegram channels: post text, views, media URLs, link previews. No login, API key, or phone number. Incremental runs (sinceDate/sinceId) keep scheduled monitoring and alerts cheap. Stable JSON schema built for pipelines, dashboards, and AI agents (MCP-friendly).

- **URL**: https://apify.com/virtual-constructs/telegram-channel-monitor.md
- **Developed by:** [Virtual Constructs](https://apify.com/virtual-constructs) (community)
- **Categories:** Social media, News, Automation
- **Stats:** 2 total users, 0 monthly users, 94.1% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Telegram Channel Monitor

Scrape and monitor public Telegram channels. Posts, view counts, media URLs,
link previews: no login, no API key, no phone number. Data comes from
Telegram's own public preview pages (`t.me/s/<channel>`), the same content
Telegram serves to any logged-out browser.

Built for repeat use: pass `sinceDate` or `sinceId` and scheduled runs return
only new posts, so monitoring stays cheap. Output schema is stable and fully
documented below, which makes this actor easy to wire into alert pipelines,
dashboards, and AI agent workflows (MCP-friendly).

### What data does this Telegram scraper extract?

One dataset item per post, with every field always present (missing data is
`null`, never an absent key):

- Post text, ID, URL, and exact timestamp
- View counts (as Telegram displays them)
- Reaction counts per emoji, plus a total
- Photo and video URLs (optional, `includeMedia`)
- Link previews (URL, title, description, site name)
- Forwarded-post flag and source channel
- Reply/comment counts where Telegram shows them

### How to scrape a Telegram channel without an API key

1. Enter one or more public channels: `durov`, `@durov`, and
   `https://t.me/durov` all work.
2. Choose how many recent posts you want per channel (default 20, max 100).
3. Run it. Results land in the dataset as JSON, exportable as JSON, NDJSON,
   or CSV, or fetched via the API.

No Telegram account, bot token, or phone number is involved at any step.

#### Input

| Field                | Type     | Default  | Notes                                                                                                                                                          |
| -------------------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `channels`           | string[] | required | Usernames or t.me links: `"durov"`, `"@durov"`, `"https://t.me/durov"` all work.                                                                               |
| `postsPerChannel`    | integer  | 20       | Max posts returned per channel, capped at 100.                                                                                                                 |
| `sinceDate`          | string   | null     | ISO 8601. Only posts newer than this are returned.                                                                                                             |
| `sinceId`            | integer  | null     | Only posts with a higher post ID are returned. Post IDs are per-channel, so use this for single-channel monitors; prefer `sinceDate` across multiple channels. |
| `includeMedia`       | boolean  | false    | When true, photo and video URLs are extracted into `mediaUrls`.                                                                                                |
| `proxyConfiguration` | object   | none     | Usually unnecessary; Telegram preview pages tolerate direct fetching.                                                                                          |

#### Output example

```json
{
	"channel": "telegram",
	"postId": 449,
	"url": "https://t.me/telegram/449",
	"date": "2026-06-18T14:36:06+00:00",
	"text": "For all the features from this update...",
	"views": 1260000,
	"forwards": null,
	"mediaType": null,
	"mediaUrls": [],
	"linkPreview": {
		"url": "https://telegram.org/blog/watch-apps-and-more",
		"siteName": "Telegram",
		"title": "Smartwatch Apps, Rich Text for Bots...",
		"description": "Today's update brings..."
	},
	"isForwarded": false,
	"forwardedFrom": null,
	"replyCount": null,
	"reactions": [{ "emoji": "👍", "count": 4200 }],
	"reactionsTotal": 4200
}
````

`mediaType` is `"photo"`, `"video"`, `"mixed"`, or `null`. New fields may be
added in future versions; existing fields will not change shape.

### How to monitor Telegram channels on a schedule

Run on a schedule and pass the highest `postId` from your previous run as
`sinceId` (or use `sinceDate`). The actor stops paginating as soon as it
reaches posts you have already seen, so each scheduled run fetches only one
or two small pages. This is the cheapest way to build Telegram alerts,
trend trackers, or feed integrations.

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

$1.00 per 1,000 posts returned, charged per post. A run that finds nothing
new produces an empty dataset and costs you nothing, so high-frequency
monitoring schedules stay affordable. The actor also respects the maximum
cost per run you set: it stops fetching rather than producing results you
will not be charged for.

### Is it legal to scrape Telegram channels?

This actor only reads Telegram's public channel preview pages, the pages
Telegram itself publishes to logged-out visitors as part of its product.
There is no login, no circumvention, and no access to private content, and
the actor will never add those. Publicly available data is generally
lawful to collect; if you plan to process personal data from posts, make
sure you comply with GDPR and other regulations that apply to you, and
consult a lawyer if unsure.

### Limits, stated plainly

- Public channels with web preview enabled only. Channels that disable the
  preview (and private channels) return no posts; the run log tells you which.
- History depth is limited by Telegram's preview pagination. Recent posts are
  reliable; very old history may be unreachable. `postsPerChannel` caps at 100.
- View and reaction counts above 1,000 are approximate: Telegram renders
  them abbreviated ("1.67M") and the actor parses that. Custom/premium
  emoji reactions have `emoji: null` (Telegram does not render a glyph for
  them on preview pages).
- Forward counts are not shown on preview pages, so `forwards` is currently
  always `null`. The field exists so the schema will not change if Telegram
  adds it.
- Media URLs point at Telegram's CDN with expiring tokens. Download files
  promptly; the links are not permanent.
- Comment threads are not included (only `replyCount` when Telegram shows it).

### FAQ

**Can it scrape private Telegram channels or groups?**
No, and it never will. Public preview pages only: that is what keeps this
actor dependable and compliant. Groups (including public supergroups) do
not have preview pages, so they are out of scope too.

**Do I need a Telegram API key or bot?**
No. Nothing to register, nothing to configure, no rate-limit juggling with
the official API.

**Can my Telegram account get banned for using this?**
No account is involved at any point: no login, no phone number, no API
credentials. There is nothing to ban.

**Can I export results to CSV or Excel?**
Yes. Results land in an Apify dataset, which exports as CSV, Excel, JSON,
NDJSON, or XML from the console or via the API.

**Can I get comments/replies content?**
Not in v1; the actor reports `replyCount` where Telegram shows it. If you
need thread content, open an issue on the Issues tab so demand is visible.

**Can it download the actual photos and videos?**
It returns direct CDN URLs (with `includeMedia: true`); downloading the
files is up to your pipeline, and the URLs expire, so fetch them promptly.

**How fresh is the data?**
Each run fetches the live preview page, so results are as current as what
Telegram publicly shows at that moment.

# Actor input Schema

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

Public channel usernames or t.me links, e.g. "durov" or "https://t.me/durov".

## `postsPerChannel` (type: `integer`):

Maximum number of recent posts to return per channel. Preview pages serve ~20 posts per page; very old history may be unreachable.

## `sinceDate` (type: `string`):

Only return posts newer than this ISO 8601 date or datetime, e.g. "2026-07-01" or "2026-07-01T12:00:00Z". Enables cheap incremental monitoring runs.

## `sinceId` (type: `integer`):

Only return posts with a post ID greater than this. Post IDs are per-channel, so use this for single-channel monitoring runs; prefer sinceDate when monitoring multiple channels.

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

Extract photo and video URLs into mediaUrls. Off by default (text and metadata only).

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

Optional. Telegram preview pages tolerate direct fetching; leave off unless your runs get blocked.

## Actor input object example

```json
{
  "channels": [
    "telegram"
  ],
  "postsPerChannel": 20,
  "includeMedia": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

All scraped posts as JSON. Append ?format=csv or ?format=ndjson to change the export format.

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

// Run the Actor and wait for it to finish
const run = await client.actor("virtual-constructs/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"] }

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

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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"
  ]
}' |
apify call virtual-constructs/telegram-channel-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=virtual-constructs/telegram-channel-monitor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Telegram Channel Monitor",
        "description": "Monitor and scrape public Telegram channels: post text, views, media URLs, link previews. No login, API key, or phone number. Incremental runs (sinceDate/sinceId) keep scheduled monitoring and alerts cheap. Stable JSON schema built for pipelines, dashboards, and AI agents (MCP-friendly).",
        "version": "0.0",
        "x-build-id": "ycmXO6dNK1smrRWGN"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/virtual-constructs~telegram-channel-monitor/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-virtual-constructs-telegram-channel-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/virtual-constructs~telegram-channel-monitor/runs": {
            "post": {
                "operationId": "runs-sync-virtual-constructs-telegram-channel-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/virtual-constructs~telegram-channel-monitor/run-sync": {
            "post": {
                "operationId": "run-sync-virtual-constructs-telegram-channel-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "channels"
                ],
                "properties": {
                    "channels": {
                        "title": "Channels",
                        "type": "array",
                        "description": "Public channel usernames or t.me links, e.g. \"durov\" or \"https://t.me/durov\".",
                        "items": {
                            "type": "string"
                        }
                    },
                    "postsPerChannel": {
                        "title": "Posts per channel",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Maximum number of recent posts to return per channel. Preview pages serve ~20 posts per page; very old history may be unreachable.",
                        "default": 20
                    },
                    "sinceDate": {
                        "title": "Since date",
                        "type": "string",
                        "description": "Only return posts newer than this ISO 8601 date or datetime, e.g. \"2026-07-01\" or \"2026-07-01T12:00:00Z\". Enables cheap incremental monitoring runs."
                    },
                    "sinceId": {
                        "title": "Since post ID",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Only return posts with a post ID greater than this. Post IDs are per-channel, so use this for single-channel monitoring runs; prefer sinceDate when monitoring multiple channels."
                    },
                    "includeMedia": {
                        "title": "Include media URLs",
                        "type": "boolean",
                        "description": "Extract photo and video URLs into mediaUrls. Off by default (text and metadata only).",
                        "default": false
                    },
                    "proxyConfiguration": {
                        "title": "Proxy",
                        "type": "object",
                        "description": "Optional. Telegram preview pages tolerate direct fetching; leave off unless your runs get blocked.",
                        "default": {
                            "useApifyProxy": false
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
