# Telegram Channel Scraper: Posts, Views, Links, No Login (`themineworks/telegram-channel-scraper`) Actor

Scrape public Telegram channel posts with text, view counts, outbound links and timestamps. Walks full channel history over plain HTTP. No Bot API token, no phone number, no login. Pay per post delivered.

- **URL**: https://apify.com/themineworks/telegram-channel-scraper.md
- **Developed by:** [The Mine Works](https://apify.com/themineworks) (community)
- **Categories:** Social media, News, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-usage

## 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: Posts, Views, Links, No Login

> ⚡ Pure HTTP. No Bot API token, no phone number, no MTProto session, no login.

> 💸 You are only charged for a post that actually lands in your dataset. Missing or private channels are never billed.

### Overview

Telegram Channel Scraper reads posts from any **public** Telegram channel and returns them as clean structured rows: post text, view count, outbound links, media flag, timestamp and a direct permalink. Give it a username, an `@handle`, or a `t.me` link.

It walks real channel history, not just the latest screen. Pagination follows Telegram's own cursor backwards through the archive, so you can pull hundreds of posts per channel in one run.

✅ No login or API token · ✅ Full history, not just recent posts · ✅ View counts parsed to numbers · ✅ MCP-ready for AI agents

### What you don't need

Most Telegram tooling asks for a Bot API token or, worse, your phone number and an MTProto session. Both approaches tie scraping to an identity that can be rate-limited or banned, and a bot can only read channels it has been added to.

This actor uses none of that. Telegram publishes every public channel as a server-rendered page at `t.me/s/{channel}`, and that page carries the real post text, view counts and timestamps. We read what Telegram already serves publicly, so there is no account to get restricted.

### Input

```json
{
  "channels": ["durov", "@telegram", "https://t.me/durov"],
  "maxPostsPerChannel": 100
}
```

| Field | What it takes |
| --- | --- |
| `channels` | Public channels. Bare username, `@username`, or any `t.me` link, all normalised for you. |
| `maxPostsPerChannel` | Hard cap per channel. History is walked 20 posts at a time, so this is your main cost and runtime control. |

**Scope, stated plainly:** this reads **public channels only**. Private channels, groups and direct messages require an authenticated session and are out of scope by design. If a channel is private or does not exist, the run reports it and moves on rather than failing.

### Output

```json
{
  "channel": "durov",
  "channel_title": "Pavel Durov",
  "subscribers": "11.2M subscribers",
  "post_id": "540",
  "post_url": "https://t.me/durov/540",
  "text": "🇺🇿 The 2026 International Olympiad in Informatics starts today in Tashkent...",
  "views_label": "1.14M",
  "views": 1140000,
  "has_media": true,
  "posted_at": "2026-08-10T09:29:58+00:00",
  "scraped_at": "2026-08-13T12:04:51.220Z"
}
```

| Field | Description |
| --- | --- |
| 📣 `channel` | Channel username |
| 🏷️ `channel_title` | Channel display title |
| 👥 `subscribers` | Subscriber count as Telegram displays it |
| 🔢 `post_id` | Post number within the channel, stable for deduplication |
| 🔗 `post_url` | Direct public permalink |
| 💬 `text` | Post text, formatting stripped |
| 👁️ `views_label` | Views exactly as shown, e.g. `1.14M` |
| 📊 `views` | The same figure parsed to a sortable integer, e.g. `1140000` |
| 🖼️ `has_media` | Whether the post carries photo, video, document, voice or sticker |
| 🌐 `links` | Outbound links found in the post |
| 📅 `posted_at` | ISO timestamp of publication |
| 🕒 `scraped_at` | ISO timestamp of capture |

**Why two view fields.** Telegram renders views as `1.14M`, which is what a human reads but useless for sorting or thresholds. We return the original label *and* a parsed integer so you can filter on `views > 100000` without writing your own parser.

### Common use cases

**Brand and reputation monitoring.** Watch channels where your product, token or company gets discussed, and catch a post while it is still spreading rather than after it trends.

**Crypto and market signals.** Announcement channels move fast and are frequently the first public source. View counts give you a reach signal alongside the text.

**Competitive and campaign tracking.** Follow a competitor's announcement channel on a schedule and diff what changed.

**Compliance and moderation research.** Collect public posts from channels you are required to monitor, with permalinks for evidence.

**AI agents and RAG.** Feed structured channel history into a summariser or an agent that answers "what did this channel say about X?"

### Pricing

| Event | Price | You pay when |
| --- | --- | --- |
| Post delivered | $0.001 | A post lands in your dataset |

**$1.00 per 1,000 posts.** Channels that are private, missing or empty cost nothing, which matters on a scheduled watchlist where most channels are quiet on a given day.

### Run it on a schedule

Channel monitoring is this actor's natural mode.

1. Run once with the input you want repeated, then click **Save as a task**.
2. In the Apify Console go to **Schedules → Create new**.
3. Pick a frequency and attach the saved task.
4. Wire the dataset to Sheets, Slack or a webhook from the **Integrations** tab.

Deduplicate on `post_id` across runs so a repeated schedule never reprocesses the same post.

### FAQ

**Do I need a Telegram account, bot token or phone number?**
No. None of the three. The actor reads Telegram's public channel preview.

**Can it read private channels or groups?**
No. Those need an authenticated session. This actor is deliberately limited to public channels.

**How far back can it go?**
It walks backwards using Telegram's own cursor until it reaches your cap or the start of the available preview history. Very old posts in long-running channels may not all be exposed publicly.

**Why did a channel return fewer posts than I asked for?**
Either the channel has fewer public posts than your cap, or it has gaps from deleted posts. The run reports what it actually found rather than padding.

**Are view counts exact?**
They are exactly what Telegram publishes, which is rounded for large numbers (`1.14M`). We return that label plus a parsed integer of the same value.

### Use from Claude, ChatGPT and any MCP agent

```
https://mcp.apify.com/?tools=themineworks/telegram-channel-scraper
```

Or call it programmatically:

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });

const run = await client.actor('themineworks/telegram-channel-scraper').call({
  channels: ['durov', 'telegram'],
  maxPostsPerChannel: 100,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

Questions, or need a field we don't return yet? Reach out through the Apify profile.

# Actor input Schema

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

Public Telegram channels. Accepts a bare username, @username, or any t.me link. Private channels, groups and direct messages need an authenticated session and are not supported.

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

Hard cap per channel. History is walked backwards 20 posts at a time, so this is your main cost and runtime control.

## Actor input object example

```json
{
  "channels": [
    "durov",
    "telegram"
  ],
  "maxPostsPerChannel": 40
}
```

# Actor output Schema

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

// Run the Actor and wait for it to finish
const run = await client.actor("themineworks/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": [
        "durov",
        "telegram",
    ],
    "maxPostsPerChannel": 40,
}

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

```

## MCP server setup

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