# Telegram Channel & Profile Scraper (`automation-lab/telegram-scraper`) Actor

Scrape Telegram public channels and profiles — channel metadata, messages, views, reactions, and media URLs. No API key or login needed.

- **URL**: https://apify.com/automation-lab/telegram-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Social media, Lead generation, News
- **Stats:** 684 total users, 82 monthly users, 82.9% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.52 / 1,000 messages

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 & Profile Scraper

Telegram Channel & Profile Scraper extracts Telegram profile metadata, messages, view counts, reactions, and media URLs from any public Telegram channel — without an API key, Telegram account, or login. Use it as a Telegram Profile Scraper for lightweight channel/profile lookups, or scrape full public channel history via Telegram web preview pages at a cost of $0.001 per message.

### How to scrape Telegram without an API key

Most Telegram scrapers require developer API credentials (`api_id` and `api_hash` from [my.telegram.org](https://my.telegram.org)). This actor needs **zero credentials** — it scrapes Telegram's public web preview pages (`t.me/s/`) directly, the same pages anyone can visit in a browser. Just enter a channel username like `durov` or `bbcnews` and the actor handles everything: pagination, rate limiting, and data extraction.

### What does Telegram Channel & Profile Scraper do?

This actor scrapes public Telegram channels and channel profiles via their web preview pages (`t.me/s/`). It extracts:

- **Messages** with full text, HTML formatting, timestamps, and permalink URLs
- **View counts** parsed as integers (not raw strings like "5.29M")
- **Reactions** with emoji identifiers and counts (including paid Telegram Stars)
- **Media** — photo thumbnails, video CDN URLs with duration
- **Link previews** — URL, site name, title, description, preview image
- **Telegram profile / channel metadata** — title, description, subscriber count, avatar URL, photo/video/link counts, verified badge
- **Message context** — edited flag, forwarded-from source, reply-to message ID, author signature
- **Incremental monitoring** — resume after the last processed `messageId` without downloading or paying for duplicate messages

### Why use this scraper instead of others?

- **Zero credentials** — no Telegram API key, no `api_id`/`api_hash`, no phone number, no login. Just enter a channel username and go. Most competing scrapers require Telegram developer credentials.
- **Reactions data** — the only Apify Telegram scraper that extracts reaction emoji and counts, including paid Telegram Stars.
- **Parsed view counts** — views returned as integers (`5290000`), not raw strings (`"5.29M"`). Ready for analysis without post-processing.
- **Media URLs** — actual photo and video CDN URLs, not just text content.
- **Rich message context** — edited flag, forwarded-from, reply-to chains, author signatures, link previews with images.
- **Pay per result** — transparent per-message pricing. No monthly subscription.

### Who is it for

#### Marketing and brand teams

- **Brand monitoring** — track mentions and discussions in public Telegram channels
- **Competitive research** — analyze competitor Telegram channels for content strategy and engagement
- **Community insights** — understand what your audience discusses in public Telegram communities

#### Finance and crypto teams

- **Crypto/DeFi intelligence** — monitor token announcements, pump channels, and project updates
- **Market sentiment** — track discussions in trading and investment channels for sentiment signals

#### Research and intelligence

- **Media monitoring** — scrape news channels for breaking stories and sentiment analysis
- **Academic research** — collect public discourse data from Telegram communities for social studies
- **OSINT** — gather open-source intelligence from public channels for investigative work

### What data can you extract?

#### Channel metadata

| Field | Example |
|-------|---------|
| `title` | Pavel Durov |
| `description` | Founder of Telegram. |
| `subscriberCount` | 10.5M |
| `verified` | true |
| `avatarUrl` | https://cdn4.telesco.pe/... |

#### Messages (25+ fields per message)

| Field | Example |
|-------|---------|
| `messageId` | 455 |
| `text` | Someone made a game about me... |
| `date` | 2025-10-31T14:12:20+00:00 |
| `views` | 5290000 |
| `author` | Paul Du Rove |
| `mediaType` | video |
| `videoUrl` | https://cdn4.telesco.pe/... |
| `reactions` | \[{emoji: "⭐", count: "39.3K", isPaid: true}] |
| `isEdited` | true |
| `isForwarded` | false |
| `replyToMessageId` | 442 |
| `url` | https://t.me/durov/455 |

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

This actor uses **pay-per-event** pricing — you only pay for what you scrape. No monthly subscription.

| Event | Cost |
|-------|------|
| Actor start | $0.005 |
| Per channel info | $0.002 |
| Per message | $0.001 |

**Real-world cost examples:**

| Query | Messages | Cost |
|-------|----------|------|
| 1 channel, 20 messages | 20 | $0.005 + $0.002 + 20 × $0.001 = **$0.027** |
| 1 channel, 100 messages | 100 | $0.005 + $0.002 + 100 × $0.001 = **$0.107** |
| 5 channels, 50 messages each | 250 | $0.005 + 5 × $0.002 + 250 × $0.001 = **$0.265** |

With the [Apify Free plan](https://apify.com/pricing), you get $5 of free usage per month — enough to scrape ~4,900 messages.

### How to scrape a Telegram channel or profile

1. Go to the actor's input page.
2. Enter one or more **channel usernames** (e.g., `durov`, `telegram`).
3. For a Telegram Profile Scraper lookup, enable **Profile only** to return channel/profile metadata without scraping messages.
4. For message history, leave **Profile only** disabled and set **max messages per channel** (default: 100, prefill: 20).
5. For recurring runs, set **Only messages after ID** to the highest `messageId` saved from the previous run. The cursor is exclusive.
6. Optionally toggle **Include channel info** to get metadata alongside messages.
7. Click **Start** and wait for the run to finish.
8. Download your data in JSON, CSV, Excel, or connect via API.

### Input parameters

| Field | Type | Description | Default |
|-------|------|-------------|---------|
| `channels` | string\[] | Public Telegram channel usernames | — |
| `maxMessages` | integer | Max messages per channel (1–5,000) | `100` |
| `oldestMessageDate` | string | Optional UTC date (`YYYY-MM-DD`); return messages on or after it and stop paginating after older messages | — |
| `afterMessageId` | integer | Optional exclusive cursor; return only messages whose `messageId` is greater and stop paginating when the cursor is reached | — |
| `includeChannelInfo` | boolean | Include channel/profile metadata as separate item | `true` |
| `profileOnly` | boolean | Return only Telegram channel/profile metadata and skip message scraping | `false` |

#### Finding channel usernames

A channel username is the part after `t.me/` in the channel URL:

- `https://t.me/durov` → username is `durov`
- `https://t.me/telegram` → username is `telegram`

You can also use the `@` prefix — the actor strips it automatically.

### Output example

```json
{
    "messageId": 455,
    "channelUsername": "durov",
    "channelTitle": "Pavel Durov",
    "url": "https://t.me/durov/455",
    "date": "2025-10-31T14:12:20+00:00",
    "text": "Someone made a game about me escaping a French prison...",
    "views": 5290000,
    "viewsRaw": "5.29M",
    "author": "Paul Du Rove",
    "isEdited": true,
    "isForwarded": false,
    "mediaType": "video",
    "videoUrl": "https://cdn4.telesco.pe/file/...",
    "videoDuration": "0:18",
    "reactions": [
        {"emoji": "⭐", "count": "39.3K", "isPaid": true},
        {"emoji": "", "emojiId": "5265077361648368841", "count": "86K", "isPaid": false}
    ],
    "scrapedAt": "2026-03-05T21:00:39.599Z"
}
```

### Tips for best results

- **Start small** — use `maxMessages: 20` to preview data before large runs.
- **Resume scheduled monitoring** — save the highest returned `messageId`, then pass it as `afterMessageId` on the next run. The boundary message is excluded, so only new posts are returned and charged.
- **Bound monitoring windows** — set `oldestMessageDate` for date-based limits. You can combine it with `afterMessageId`; both filters apply and `maxMessages` remains the upper result cap.
- **Public channels only** — this actor scrapes `t.me/s/` public preview pages. Private channels and groups are not accessible.
- **Rate limiting** — the actor paginates politely. For very large channels (5,000+ messages), expect runs to take a few minutes.
- **Reactions availability** — reactions appear in the HTML for recent messages. Very old messages may not include reaction data.
- **Media URLs** — video and photo CDN URLs are temporary. Download media promptly if you need to archive it.

### How to export Telegram chat history to CSV

Telegram's built-in export only works for your own chats and requires the desktop app. To export any **public channel's** message history to CSV — including channels you don't belong to — use Telegram Channel Scraper:

1. Open [Telegram Channel Scraper](https://apify.com/automation-lab/telegram-scraper) on Apify Store.
2. Enter the channel username (e.g., `durov`, `telegram`, `bbcnews`).
3. Set **Max messages** to the number of messages you want to export (up to 5,000 per run).
4. Enable **Include channel info** if you want subscriber count and metadata.
5. Click **Start** and wait for the run to finish (usually under a minute).
6. Open the **Dataset** tab and click **Export** → **CSV**.
7. Open the downloaded `.csv` in Excel, Google Sheets, or any data tool.

Each row in the CSV represents one message with columns for: `messageId`, `date`, `text`, `views`, `author`, `mediaType`, `reactions`, `isForwarded`, `url`, and more.

**Tips for large exports:**

- Run multiple sessions with different date ranges if you need more than 5,000 messages.
- Use the JSON export instead of CSV if you need nested reaction data (CSV flattens arrays).
- Schedule recurring daily scrapes to build a running archive of channel activity over time.

### Integrations

Connect Telegram Channel Scraper to your workflow using [Apify integrations](https://apify.com/integrations):

- **Google Sheets** — export messages directly to a spreadsheet for tracking channel activity over time
- **Slack / Discord** — get notifications when scraping finishes, or forward key messages to your team channels
- **Zapier / Make** — automate workflows, e.g., alert on crypto announcements, archive news channel content, or trigger analysis when new messages arrive
- **Webhooks** — send results to your own API endpoint for custom processing pipelines
- **Scheduled runs** — set up hourly or daily scrapes to continuously monitor channels
- **Data warehouses** — pipe messages to BigQuery, Snowflake, or PostgreSQL for large-scale analysis
- **AI/LLM pipelines** — feed messages into sentiment analysis, translation, or summarization workflows

### API usage

#### Node.js

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

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

const run = await client.actor('automation-lab/telegram-scraper').call({
    channels: ['durov', 'telegram'],
    maxMessages: 50,
});

// Profile-only lookup (Telegram Profile Scraper mode):
const profileRun = await client.actor('automation-lab/telegram-scraper').call({
    channels: ['durov'],
    profileOnly: true,
});

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

// On the next scheduled run, resume exclusively after the highest saved ID:
const lastMessageId = Math.max(...items.filter((item) => item.messageId).map((item) => item.messageId));
await client.actor('automation-lab/telegram-scraper').call({
    channels: ['durov', 'telegram'],
    maxMessages: 50,
    afterMessageId: lastMessageId,
});
```

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")

run = client.actor("automation-lab/telegram-scraper").call(run_input={
    "channels": ["durov"],
    "maxMessages": 100,
})

items = client.dataset(run["defaultDatasetId"]).list_items().items
for item in items:
    if "messageId" in item:
        print(f"[{item['date']}] {item['views']} views: {item['text'][:80]}")
```

#### cURL

```bash
curl "https://api.apify.com/v2/acts/automation-lab~telegram-scraper/runs" \
  -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -d '{"channels":["durov"],"maxMessages":50}'
```

### Legality: is it legal to scrape Telegram?

This actor only accesses **publicly available data** from Telegram's own public web preview pages (`t.me/s/`). It does not:

- Access private channels or groups
- Require authentication or user credentials
- Extract personal data like phone numbers
- Bypass any access controls

Always review Telegram's [Terms of Service](https://telegram.org/tos) and comply with applicable data protection laws (GDPR, CCPA) when processing scraped data.

### Use with AI agents via MCP

Telegram Scraper is available as a tool for AI assistants that support the [Model Context Protocol (MCP)](https://docs.apify.com/platform/integrations/mcp). This lets you use natural language to scrape data — just ask your AI assistant and it will configure and run the scraper for you.

#### Setup for Claude Code

```bash
claude mcp add --transport http apify "https://mcp.apify.com/?tools=automation-lab/telegram-scraper"
```

#### Setup for Claude Desktop, Cursor, or VS Code

Add this to your MCP config file:

```json
{
    "mcpServers": {
        "apify": {
            "url": "https://mcp.apify.com/?tools=automation-lab/telegram-scraper"
        }
    }
}
```

Your AI assistant will use OAuth to authenticate with your Apify account on first use.

#### Example prompts

Once connected, try asking your AI assistant:

- "Scrape the last 500 messages from this Telegram channel"
- "Get channel info and recent posts from @durov"
- "Use Telegram Profile Scraper mode to get @durov profile metadata only"

Learn more in the [Apify MCP documentation](https://docs.apify.com/platform/integrations/mcp).

### What is a Telegram channel vs. a Telegram group?

A **Telegram channel** is a broadcast tool where only admins post messages to unlimited subscribers. Channels are one-to-many: subscribers read messages but typically cannot reply. Examples include news outlets (BBC, CNN), crypto projects, brand announcements, and influencer updates. Channels display view counts on every message.

A **Telegram group** is a many-to-many chat where all members can send messages. Groups support up to 200,000 members and are used for discussions, communities, and team communication.

This actor scrapes **public channels only** — channels that have a web preview at `t.me/s/CHANNEL_NAME`. Private channels, groups, and supergroups are not accessible without authentication.

### FAQ

**Q: Do I need a Telegram account or API key?**
No. This actor scrapes public web pages — no Telegram credentials needed.

**Q: Can I scrape private channels or groups?**
No. Only public channels with a `t.me/s/` preview page are supported.

**Q: How many messages can I get?**
Up to 5,000 per channel per run. The actor paginates automatically through the channel history.

**Q: Why are some reaction emojis empty?**
Custom Telegram emojis are identified by `emojiId` rather than a Unicode character. The standard emojis (thumbs up, heart, etc.) show the Unicode emoji.

**Q: How is this different from other Telegram scrapers on Apify?**
Most competitors require Telegram API credentials (`api_id`/`api_hash`). This actor needs **zero credentials** — just enter a channel username. It also extracts reactions, parsed view counts, and media URLs that competitors miss.

**Q: The scraper returns no messages for a channel — what's wrong?**
Check that the channel has a public web preview at `t.me/s/CHANNEL_NAME`. If visiting that URL in a browser shows a "You can view and join" message instead of posts, the channel doesn't have public preview enabled. Only channels with public web previews can be scraped.

**Q: Media URLs are broken or return 404 — how do I fix this?**
Telegram CDN URLs are temporary and expire after some time. If you need to archive media, download the files immediately after scraping. The scraper extracts the URLs as they appear at scraping time, but Telegram may rotate CDN links.

### Related actors

- [Threads Scraper](https://apify.com/automation-lab/threads-scraper) — scrape Meta Threads posts, profiles, and search results
- [TikTok Scraper](https://apify.com/automation-lab/tiktok-scraper) — scrape TikTok profiles and video details
- [Instagram Scraper](https://apify.com/automation-lab/instagram-scraper) — scrape Instagram posts, profiles, and reels
- [Twitter/X Scraper](https://apify.com/automation-lab/twitter-scraper) — scrape tweets and user profiles
- [Reddit Scraper](https://apify.com/automation-lab/reddit-scraper) — scrape Reddit posts and comments
- [Bluesky Scraper](https://apify.com/automation-lab/bluesky-scraper) — scrape Bluesky posts and profiles
- [YouTube Scraper](https://apify.com/automation-lab/youtube-scraper) — scrape YouTube videos, channels, and comments

# Actor input Schema

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

List of public Telegram channel usernames (e.g. "durov", "telegram"). Do not include the @ symbol.

## `maxMessages` (type: `integer`):

Maximum number of messages to extract per channel. The actor paginates automatically.

## `oldestMessageDate` (type: `string`):

Optional UTC date in YYYY-MM-DD format. Only messages on or after this date are returned, and pagination stops after older messages are reached. Has no effect in profile-only mode.

## `afterMessageId` (type: `integer`):

Optional exclusive cursor for incremental monitoring. Only messages with messageId greater than this value are returned, and pagination stops when the cursor is reached. Combine it with maxMessages and oldestMessageDate; it has no effect in profile-only mode.

## `includeChannelInfo` (type: `boolean`):

Add a separate dataset item with channel profile metadata (title, description, subscriber count, avatar, verified status, etc.).

## `profileOnly` (type: `boolean`):

Return only Telegram channel/profile metadata and skip message history scraping. Use this for Telegram Profile Scraper-style lookups.

## Actor input object example

```json
{
  "channels": [
    "durov"
  ],
  "maxMessages": 20,
  "includeChannelInfo": true,
  "profileOnly": false
}
```

# Actor output Schema

## `overview` (type: `string`):

Dataset view containing scraped Telegram messages.

## `channels` (type: `string`):

Dataset view containing public Telegram channel metadata.

# 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"
    ],
    "maxMessages": 20,
    "profileOnly": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/telegram-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"],
    "maxMessages": 20,
    "profileOnly": False,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/telegram-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"
  ],
  "maxMessages": 20,
  "profileOnly": false
}' |
apify call automation-lab/telegram-scraper --silent --output-dataset

```

## MCP server setup

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