# Telegram Channel Scraper - Export Messages, No API Key (`flash_scraper/telegram-channel-scraper`) Actor

Scrape any public Telegram channel's messages via the t.me web preview - no API key, bot token, phone or login. Export text, date, views, author, media type and links to CSV, JSON or Excel. Handles multiple channels and paginates back through history. Great for crypto, news, OSINT and research.

- **URL**: https://apify.com/flash\_scraper/telegram-channel-scraper.md
- **Developed by:** [Flash Scrape](https://apify.com/flash_scraper) (community)
- **Categories:** Social media, News
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $6.00 / 1,000 results

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 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 — public channel messages, no API key or bot token

Pull **messages from any public Telegram channel** into a clean, structured dataset — **no API key, no bot token, no phone number, no login**. This actor reads the official Telegram web preview (`t.me/s/<channel>`), the same public page anyone can open in a browser, and turns each post into a row: message text, date, view count, author/signature, media type, and every link. **$5 per 1,000 messages** — pay only for the messages you actually get.

### What does it do?

Give it a list of **public channel usernames or `t.me` links** and how many recent messages you want per channel. The actor fetches each channel's public preview page, parses every post, and **paginates backwards through the channel history** to reach older messages until it hits your limit or the start of the channel. The result is a tidy, deduped, most-recent-first table you can export to **CSV, JSON, or Excel** — ready for a spreadsheet, a BI tool, or an LLM pipeline.

It reads **public broadcast channels only** — the kind that already show a public web preview. It does not log in, does not use a bot token, and cannot access private or invite-only channels or group chats. Because it uses plain HTTP against the public page, it runs fine on datacenter IPs with no proxy required.

### Why use it / who's it for

- **Crypto & DeFi researchers** monitoring announcement, signal, and project channels — track calls, listings, and sentiment over time without babysitting the app.
- **News & journalism teams** archiving official channels from agencies, governments, and outlets that publish first (or only) on Telegram.
- **OSINT & threat-intelligence analysts** collecting public-channel posts into a searchable, timestamped dataset for investigation and monitoring.
- **Community & competitor trackers** watching a rival's or a niche's public channel — posting cadence, engagement (views), what links they push, what media they lean on.
- **Data scientists & ML teams** building text datasets from public broadcast channels for topic modeling, trend detection, or fine-tuning.
- **Marketers & growth teams** benchmarking which posts in a category get the most views, and mining the links a channel shares.

### How to use it

1. Add one or more **channels** — usernames (`telegram`), `@handles` (`@durov`), or full links (`https://t.me/durov`). All three formats are normalized automatically.
2. Set **maxItemsPerChannel** — how many of the most recent messages to pull from each channel (default 100, up to 1,000).
3. Run it. Then export the dataset to **CSV, JSON, or Excel**, or read it straight from the dataset API.

Only `channels` matters — everything else has a sensible default, and the demo run works out of the box.

### Input

| Field | Type | Description |
|---|---|---|
| `channels` | array of strings | Public channel usernames or `t.me` links. `telegram`, `@durov`, and `https://t.me/durov` all work. **Required.** |
| `maxItemsPerChannel` | integer | Most-recent messages to pull per channel (default `100`, max `1000`). |

#### Input example

```json
{
  "channels": ["telegram", "durov"],
  "maxItemsPerChannel": 50
}
```

### Output

One row per message:

| Field | Description |
|---|---|
| `channel` | Channel username the message came from |
| `message_id` | Numeric message id within the channel |
| `message_url` | Direct link, `https://t.me/<channel>/<id>` |
| `text` | Message text, with line breaks preserved |
| `date` | Publish time (ISO 8601, UTC) |
| `views` | View count as shown by Telegram (e.g. `1.18M`, `907K`) |
| `author` | Post signature / author, when the channel signs posts |
| `media_type` | `photo`, `video`, `voice`, `audio`, `document`, `poll`, `sticker`, `location`, `link`, or `none` |
| `has_links` | `true` if the message text contains at least one link |
| `links` | List of URLs found in the message text |

#### Example output row

```json
{
  "channel": "telegram",
  "message_id": 448,
  "message_url": "https://t.me/telegram/448",
  "text": "AI Admins for Groups. Groups can now add AI bots as admins to process join requests with unique features like captcha support.",
  "date": "2026-06-18T14:35:57+00:00",
  "views": "1.06M",
  "author": null,
  "media_type": "video",
  "has_links": true,
  "links": ["https://t.me/telegram/449"]
}
```

### How much does it cost?

This actor uses **pay-per-event pricing: $0.005 per message result ($5 per 1,000 messages)**. You're charged only for messages actually returned — no subscription, and no charge for empty runs. New Apify accounts get roughly **1,000 free results per month** on the platform's free tier, so you can pull a mid-size backlog from several channels and test the output before paying anything. Pulling 5,000 messages costs $25; a 20,000-message archive costs $100.

### FAQ

#### Do I need an API key, bot token, or phone number?

No. The actor reads the **official public web preview** at `t.me/s/<channel>` — the same page any browser can open without logging in. There is no Telegram API key, no bot token, no phone-number login, and no session string. That also means there's nothing to get banned: it never authenticates as a user.

#### Can it read private channels or group chats?

No. It only reads **public channels** that expose a public web preview. Private channels, invite-only channels, and group chats are not accessible this way, by design. If a channel doesn't return public messages, the actor logs a warning and skips it — the run still finishes cleanly for the channels that do work.

#### How far back can it go?

It paginates backwards through the channel's public history using Telegram's `?before=` parameter, so you can pull well beyond the latest page. In practice you're bounded by `maxItemsPerChannel` and by how much history Telegram serves in the public preview. Very large historical pulls are best split across several runs.

#### How fresh is the data?

It's fetched **live at run time**, so results reflect what the channel shows right now, including current view counts. Re-run periodically (or on a schedule) to keep a channel archive up to date.

#### Why is a channel returning fewer messages than I asked for?

Either the channel simply has fewer public messages than your limit, or it reached the start of its public history. Service messages and some media-only edge cases may also be skipped. The actor de-duplicates by message id, so counts reflect unique messages.

#### Is scraping this data allowed?

The actor reads only **publicly available** data from Telegram's own public web preview — no login, no paywall, no private content. Use the collected data responsibly and in line with Telegram's terms and any laws that apply to your use case (privacy, copyright, etc.).

### Related actors

- [Twitter / X Leads Scraper](https://apify.com/flash_scraper/twitter-leads-scraper) — pull public X/Twitter profiles and posts into structured leads.
- [Wikipedia Scraper](https://apify.com/flash_scraper/wikipedia-scraper) — extract clean article text and structured data from Wikipedia.

Questions or a channel that won't parse? Open an issue on the actor's **Issues** tab and we'll take a look.

# Actor input Schema

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

Public Telegram channel usernames or t.me links (e.g. 'telegram', '@durov', or 'https://t.me/durov'). Only PUBLIC channels work - private/invite-only channels cannot be read.

## `maxItemsPerChannel` (type: `integer`):

Maximum number of most-recent messages to pull from each channel. Older messages are fetched by paginating back through the channel history.

## Actor input object example

```json
{
  "channels": [
    "telegram",
    "durov"
  ],
  "maxItemsPerChannel": 50
}
```

# 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": [
        "telegram",
        "durov"
    ],
    "maxItemsPerChannel": 50
};

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

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

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/H8E8ubPEcOJQVEdcq/builds/JX56pZsEk3DmTsHNH/openapi.json
