# Telegram Channel Scraper (`viremo-labs/telegram-channel-scraper`) Actor

Scrape public Telegram channels into structured posts, views, reactions, media, polls, forwards, discussion comments, capped participant samples, channel analytics, and discovery. Use no-login widget mode or publisher-pool MTProto. Run snapshots or monitor new posts with change events.

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

## Pricing

from $0.30 / 1,000 telegram messages

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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 Scraper (Store README - EN)

Status: APPROVED Store copy; published on 2026-09-13.

> **Available on Apify Store.** Widget mode needs no login; MTProto mode uses
> the publisher's own account pool. Final-build extraction, PPE charging, and
> spend-limit proofs pass.

### 1. Value proposition

Turn public Telegram channels into clean structured data — message texts,
views, reactions, media flags, channel headers — with new-message monitoring
between runs. Widget mode needs no login, API key, or browser. Optional
MTProto mode adds
comments, forwards, members, polls, stories and channel discovery.

### 2. What the Actor does / 3. For whom / 4. Snapshot-monitor

- **Snapshot**: read the listed channels (paged history where available); one
  `channel` row plus one `message` row per post.
- **Monitor**: same read against the stored baseline plus `change_event`
  rows for new messages (`message_added`).
- For news digests, brand/channel monitoring, research datasets, and feeding
  RAG pipelines with channel content.

### 5. Key features / 6. Responsible use / 7. Input guide / 8. Output schema

- Static widget pages (`t.me/s/<channel>`) parsed into text (+ opt-in raw HTML),
  links, hashtags, mentions, emails published in posts, sender + author with
  profile URLs, views, reactions, photo URLs (albums included), direct video
  file URLs with durations, document names/sizes, stickers, voice durations,
  polls with per-option results, rich link previews, channel avatar, media
  flags, dates.
- Channel profile: subscribers, verification, scam/fake badges, photo/video/
  file/link totals, related channels (forwards + description links),
  optional linked discussion group with member counts, plus engagement analytics over the
  collected window (average/median/max views, average reactions, posts per
  day, engagement rate).
- Date windows (absolute or relative like "7 days"), keyword search filter,
  minimum-views filter, media-only / text-only modes, history paging,
  per-channel caps, profile-only mode (no history fetch).
- Polite by design: throttled (default 2 s), max 3 concurrent, timeouts,
  byte caps, 25-page safety cap per channel.
- Honest coverage: `complete`/`partial` + structured `warnings[]`; source and
  optional-feature failures are surfaced, and missing
  feeds are classified (`CHANNEL_NOT_FOUND` / `CHANNEL_PREVIEW_DISABLED` /
  `CHANNEL_IS_GROUP` / `CHANNEL_IS_USER`), never silent empty runs.

### MTProto mode (owner account pool)

Set `authMode: "mtproto"` to read through the Telegram API instead of widget
pages: discussion comments with authors, forward/repost counters, reply
counters, real poll votes (closed/quiz/solution included), media metadata
(dimensions, durations, document names, sticker emoji), participant counts,
capped discussion participant export, Telegram's own similar channels, global topic
discovery, exact post URLs, service events, sender ids, rich-text entities,
TTL timers, forward origin tracing, active channel stories. Needs the owner
pool (`TG_SESSION_*`, live source only); accounts rotate automatically on
flood waits and quarantine on bans. Read-only calls — no joins, invites
or writes.

- Responsible use: public channels only; you are accountable for how you use
  collected posts. See `RESPONSIBLE_USE.md`.
- Input: `channels` or `channelObjects` (stable ids), `mode`, `maxPosts`,
  `includeText`, limits, `baselineKey`. Output: `channel` + `message` +
  `change_event` rows; fields in `.actor/dataset_schema.json`.

### 9. Examples / 10. Monitoring / 11. Coverage / 12. Cost

- Example input: `{ "mode": "snapshot", "channels": ["durov"], "maxPosts": 25 }`.
- Monitor example: same input with `"mode": "monitor"`; first run creates the
  baseline, later runs add `change_event` rows only for newly observed messages.
- Coverage: `complete`/`partial` + `warnings[]` for detected source, budget,
  cap, and optional-feature failures.
- Store pricing: pay-per-event - `$0.00030` per unique message and
  `$0.001` per monitor change event. `apify-actor-start` is synthetic and never
  charged manually. Channel/member/story rows are free; monitor re-runs bill
  only new messages. Active cloud proof is tracked in `PRICING_DRAFT.md`.

### 13. Scheduling / 14. API examples / 15. Views / 16. FAQ

- Schedule via Apify Schedules (hourly/daily) for digest mode.
- API: standard Apify run + dataset endpoints; envelope carries `recordType`,
  `canonicalId`, `queryId`, `fetchedAt`.
- Dataset views: `records` (all rows), `messageFields`, `changeFields`.
- **Do I need login or an API key?** No for widget mode — public pages only.
  `authMode: "mtproto"` uses the publisher's own pool for comments/forwards.
  **Private channels?** Not readable by design (`CHANNEL_NOT_FOUND`).
  **How far back?** History paging per channel up to the cap.

### 17. AI assistants (MCP)

Call this actor from Claude, ChatGPT or any agent framework through the
Apify MCP server (`https://mcp.apify.com`). Agent guidance:

- Default to widget mode (no login, fastest, cheapest): monitoring, keyword
  search, lead extraction, analytics.
- Switch to `authMode: "mtproto"` only when the task needs discussion
  comments, forward counters, exact polls, members or similar channels.
- Prefer `messagePreview: true` for summarization tasks (one line per post,
  small context), full `text` for RAG ingestion.
- Prefer `includePosts: false` + `resolveDiscussion: true` to validate a
  channel list cheaply before a deep run.
- Example prompts: "pull the last 50 posts from @durov with views and
  reactions", "find crypto channels talking about staking and list their
  subscriber counts" (`discover` + MTProto), "watch @tginfo for new posts
  mentioning airdrop" (`mode: "monitor"` + `searchKeywords` on a Schedule).

### 18. Troubleshooting / 19. Support / 20. Privacy-security / 21. Changelog link

- `partial` coverage: see `warnings[]` for per-channel causes.
- Empty text on a row: media-only post (flagged via `hasPhoto/hasVideo`).
- Support: message Viremo Labs through Apify Console or the support email on
  the actor website (response goal: three business days).
- Privacy: public channel and linked public-discussion data only. Owner pool
  credentials stay secret and are never written to output.

# Actor input Schema

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

snapshot scrapes current state; monitor diffs against the stored baseline.

## `authMode` (type: `string`):

widget needs no login; mtproto uses the publisher account pool for deeper history and optional API-only fields.

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

Usernames, @usernames or t.me links.

## `channelObjects` (type: `array`):

Channels with stable query ids.

## `postUrls` (type: `array`):

Individual public post URLs to fetch exactly.

## `discover` (type: `array`):

Global public channel discovery by topic (MTProto only).

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

History paging stops at the cap.

## `includeText` (type: `boolean`):

Extract message text (otherwise only metadata).

## `searchKeywords` (type: `array`):

Keep only messages whose text or hashtags contain a keyword.

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

Keep only messages with at least this many views.

## `mediaOnly` (type: `boolean`):

Keep only posts carrying media.

## `textOnly` (type: `boolean`):

Keep only posts without downloadable media.

## `includePosts` (type: `boolean`):

Fetch message history (off = channel profile row only).

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

Include the raw message HTML (formatting preserved).

## `includeComments` (type: `boolean`):

Fetch discussion comments per post (MTProto mode only).

## `maxCommentsPerPost` (type: `integer`):

Comment cap per post (MTProto mode only).

## `minReplies` (type: `integer`):

Keep only posts with at least this many discussion replies.

## `minId` (type: `integer`):

Keep only messages with id >= minId.

## `maxId` (type: `integer`):

Keep only messages with id <= maxId.

## `resolveDiscussion` (type: `boolean`):

Discover the linked discussion group and its member counts.

## `messagePreview` (type: `boolean`):

Add a one-line LLM-ready preview per message.

## `includeSimilar` (type: `boolean`):

Add Telegram's similar-channel picks (MTProto only).

## `includeMembers` (type: `boolean`):

Export discussion-group members (MTProto only).

## `maxMembers` (type: `integer`):

Member cap per channel (MTProto only).

## `includeServiceEvents` (type: `boolean`):

Include pins, title changes and joins (MTProto only).

## `fromUser` (type: `string`):

Keep only posts from this sender @username or id (MTProto only).

## `includeStories` (type: `boolean`):

Fetch active channel stories (MTProto only).

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

How many pages may be fetched at once. Keep at 1 to stay polite.

## `requestTimeoutSecs` (type: `integer`):

Request Timeout Secs.

## `requestDelayMillis` (type: `integer`):

Minimum 1000 ms.

## `maxBytesPerPage` (type: `integer`):

Max Bytes Per Page.

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

Keep messages posted on/after this date (YYYY-MM-DD or a relative lookback such as "7 days"). Older history stops.

## `untilDate` (type: `string`):

Keep messages posted on/before this date (YYYY-MM-DD or a relative lookback such as "7 days").

## `baselineKey` (type: `string`):

Monitor baseline slot in the monitor key-value store.

## Actor input object example

```json
{
  "mode": "snapshot",
  "authMode": "widget",
  "postUrls": [],
  "discover": [],
  "maxPosts": 50,
  "includeText": true,
  "searchKeywords": [],
  "mediaOnly": false,
  "textOnly": false,
  "includePosts": true,
  "includeTextHtml": false,
  "includeComments": false,
  "maxCommentsPerPost": 20,
  "resolveDiscussion": false,
  "messagePreview": false,
  "includeSimilar": false,
  "includeMembers": false,
  "maxMembers": 100,
  "includeServiceEvents": false,
  "includeStories": false,
  "maxConcurrency": 1,
  "requestTimeoutSecs": 20,
  "requestDelayMillis": 2000,
  "maxBytesPerPage": 2000000,
  "baselineKey": "default"
}
```

# Actor output Schema

## `dataset` (type: `string`):

Channel, message, member, story and change-event rows. Use recordType to discriminate rows.

## `runSummary` (type: `string`):

Run status, counts, request statistics, coverage and warnings.

# 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 = {};

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

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

```

## MCP server setup

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