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

Scrape public Telegram channels without login: post text, dates, views, media, forwards, replies, links and hashtags from the t.me/s preview. Pay per message.

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

## Pricing

from $2.00 / 1,000 message scrapeds

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

Telegram Channel Scraper extracts posts from any **public Telegram channel** without a Telegram account, phone number, bot token or API key. It reads the same web preview pages that Telegram serves at `https://t.me/s/<channel>`, walks back through the channel history page by page, and returns one clean JSON record per message: text, publication date, view count, author signature, forwarded-from source, reply quote, links, hashtags, mentions and media (photos, videos, documents, audio, polls, stickers).

Typical uses: monitoring crypto, finance or news channels, building datasets for research or NLP, feeding channel posts into an AI agent or n8n/Make automation, archiving a channel, or tracking competitor announcements.

The scraper cannot read private channels, invite-link groups, user profiles or channels whose owner disabled the web preview. For those it returns a status record (`not_found`, `no_preview`) instead of failing the run.

### How to scrape a Telegram channel

1. Open the Actor in Apify Console and click **Try for free**.
2. In **Channels**, add one or more public channels. Any of these forms work: `durov`, `@telegram`, `https://t.me/durov`, `t.me/s/telegram`.
3. Set **Max posts per channel** (default 20, newest first). Optionally set **Since date** to stop at a date, turn off **Include media** to get lighter records, or turn on **Include raw HTML** to keep Telegram's formatting.
4. Click **Start**. Results appear in the **Output** tab within seconds and can be downloaded as JSON, CSV, Excel or XML, or fetched through the API.

Each t.me page holds about 20 messages, so the default of 20 posts is a single page load and 100 posts means roughly five page loads per channel. Channels are processed in parallel (up to five at once) with a one-second delay between requests to the same host.

#### How pagination works

Telegram's preview page renders the 20 most recent messages and a "load more" link of the form `https://t.me/s/<channel>?before=<messageId>`. The Actor follows that link until it has collected the requested number of posts, reaches the `sinceDate` cutoff, or arrives at the beginning of the channel's history. Only strictly older message ids are accepted from each new page, so messages are never duplicated even if a run migrates between servers.

### Telegram Channel Scraper pricing

This Actor uses Apify's **pay-per-event** model. There is no subscription and no per-result platform fee on top:

- **Actor start**: a flat fee of $0.00005 per run.
- **Message scraped**: **$0.002 per message** pushed to your dataset (that is $2 per 1,000 messages).

Status records for channels that do not exist or have no preview are free. You can cap spending with **Maximum cost per run**; when the cap is reached the Actor stops cleanly and keeps everything scraped so far. Apify's free plan credit is enough to scrape thousands of messages for evaluation.

### Input example

```json
{
    "channels": ["durov", "@telegram", "https://t.me/cointelegraph"],
    "maxPostsPerChannel": 100,
    "sinceDate": "2026-01-01",
    "includeMedia": true,
    "includeHtml": false,
    "proxyConfiguration": { "useApifyProxy": true }
}
```

#### Input fields

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `channels` | array of strings | required | Usernames, `@usernames` or `t.me` links of public channels. |
| `maxPostsPerChannel` | integer | 20 | Newest N messages to collect per channel. |
| `sinceDate` | ISO date string | none | Stop once messages are older than this date. |
| `includeMedia` | boolean | true | Include the `media` array. |
| `includeHtml` | boolean | false | Include `textHtml` with Telegram's original markup. |
| `proxyConfiguration` | object | Apify Proxy | Standard Apify proxy settings. |

### Output example

One dataset item per message:

```json
{
    "channel": "durov",
    "channelTitle": "Pavel Durov",
    "channelDescription": "Founder of Telegram.",
    "channelStatus": "ok",
    "messageId": 536,
    "url": "https://t.me/durov/536",
    "date": "2026-08-21T13:02:11.000Z",
    "text": "🚫 India’s IT ministry banned Telegram for one week because some users shared leaked exam questions.\n\nThis punishes 150 million ordinary Telegram users in India...",
    "views": 1550000,
    "author": "Pavel Durov",
    "forwardedFrom": null,
    "replyTo": null,
    "links": ["https://telegram.org/safety"],
    "hashtags": [],
    "mentions": [],
    "media": [
        {
            "type": "photo",
            "url": "https://cdn4.telesco.pe/file/....jpg",
            "thumbUrl": null,
            "duration": null,
            "name": null
        }
    ],
    "isService": false,
    "scrapedAt": "2026-10-10T18:51:57.947Z"
}
```

`forwardedFrom` is `{ "name", "url" }` when the post was forwarded, `replyTo` is `{ "messageId", "text" }` when it quotes another post, and `media.type` is one of `photo`, `video`, `document`, `audio`, `poll`, `sticker`. Channels that could not be scraped produce a single record with `channelStatus` set to `not_found`, `no_preview`, `empty` or `error` and a human-readable `message`.

### Integrations

- **API**: start runs and read results with the [Apify API](https://docs.apify.com/api/v2) or the JavaScript and Python clients. Run the Actor synchronously with `run-sync-get-dataset-items` to get messages in one call.
- **MCP / AI agents**: the Actor is exposed through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp), so Claude, ChatGPT and other agents can call it as a tool with the same input.
- **n8n and Make**: use the Apify node or module, pick this Actor, pass the input JSON above and map the dataset items into your workflow.
- **Schedules and webhooks**: run it hourly or daily from Apify Schedules and let a webhook push new messages to Slack, Google Sheets, a database or a CRM.

### Telegram Channel Scraper FAQ

#### Does it work for private channels or groups?

No. Only channels with a public username and an enabled web preview can be read. Private channels, invite-link groups and user profiles return a `no_preview` or `not_found` status record.

#### Why are some videos or documents missing a direct URL?

Telegram's preview exposes direct CDN links for photos and short videos, but documents and large files are only linked through the message URL. The `media` entry still tells you the type and name.

#### Can I get comments, reactions or subscriber counts?

Not in this version. The web preview shows reactions and subscriber counts, and they may be added on request; comments live in linked discussion groups and are not available without the Telegram API.

#### How fresh is the data?

Every run fetches the live preview page, so results are as current as Telegram's own website. View counts are the rounded values Telegram shows ("1.5M" becomes `1500000`).

#### Can I scrape many channels at once?

Yes. Add as many channels as you like; they are processed in parallel with built-in rate limiting and automatic retries.

### Related actors

Same author, same pay-per-event model and the same no-login approach. They combine well in one pipeline (for example calendar events plus prediction odds plus channel chatter around a release):

- [Substack Scraper](https://apify.com/romajure/substack-scraper) - posts, authors, likes, restacks and comments from public Substack publications, custom domains included.
- [Economic Calendar Scraper](https://apify.com/romajure/economic-calendar) - Forex Factory and Investing.com macro events with UTC times, impact, actual, forecast and previous values.
- [Prediction Market Odds Scraper](https://apify.com/romajure/prediction-market-odds) - Polymarket and Kalshi markets with 0-1 prices, implied probabilities, bid/ask, volume and orderbooks.
- [Product Hunt Scraper](https://apify.com/romajure/product-hunt-scraper) - daily, weekly and monthly leaderboards, topic pages, search and product launches with votes, makers and website URLs.

### Legal and compliance

This Actor only reads publicly available pages that Telegram serves to anyone without logging in, and it does not bypass any access control. You are responsible for using the data in line with [Telegram's Terms of Service](https://telegram.org/tos), applicable law and, where personal data is involved, GDPR or other privacy regulations. Please read Apify's article on the [legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) if you are unsure.

### Support

Found a channel that does not parse correctly, or need an extra field? Open an issue on the Actor's **Issues** tab in Apify Console or contact the author through the Actor page. Bug reports that include the channel username are usually fixed within days.

# Actor input Schema

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

Public channels to scrape. Accepts bare usernames (`durov`), `@usernames` (`@telegram`) or links (`https://t.me/durov`, `t.me/s/telegram`). All forms are normalized to the username. Defaults to the official `telegram` channel when omitted.

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

Stop after this many messages have been collected from a channel (newest first). Each t.me page holds about 20 messages, so 100 posts is roughly 5 page loads.

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

Optional ISO 8601 date or date-time (for example `2026-01-01` or `2026-01-01T12:00:00Z`). Messages older than this are skipped and pagination stops once the channel history passes it.

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

Include a `media` array with photo URLs, video sources and thumbnails, document names, audio, polls and stickers.

## `includeHtml` (type: `boolean`):

Also return the raw message HTML (`textHtml`) next to the plain text. Useful if you need Telegram's formatting (bold, links, spoilers).

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

Proxy settings. Apify Proxy is recommended; t.me rate-limits aggressive scraping from a single IP.

## Actor input object example

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

# Actor output Schema

## `messages` (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"
    ],
    "maxPostsPerChannel": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

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

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

```

## MCP server setup

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