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

Export posts from public Telegram channels: text, views, reactions, media links and dates. No account, bot token or API key needed.

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

## Pricing

from $1.00 / 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.

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

Export posts from any public Telegram channel into a spreadsheet, JSON, or your own app. No Telegram account, phone number, bot token, or API key required.

Press **Start** to see it work. The default input scrapes @telegram and @durov straight away.

### What you get

One row per post, newest first, with the fields people actually ask for:

| Field | Example |
|---|---|
| `date` | `2026-09-11T16:04:02+00:00` |
| `text` | Full post text, emoji and line breaks preserved |
| `views` | `688000` (also `viewsRaw`: `"688K"`) |
| `totalReactions` | `146385`, plus a per-emoji breakdown |
| `url` | `https://t.me/durov/548` |
| `photoUrls` / `videoUrls` | Direct media links |
| `linkPreview` | Title, description, site name of any shared link |
| `forwardedFrom` / `replyToUrl` | Where a forward or reply came from |

An optional summary row per channel carries the title, description, subscriber count, verified badge, and post/photo/video counts.

### What people use it for

- **Competitor and market monitoring.** Track what rival channels publish and which posts actually land, using views and reactions.
- **Feeding AI agents and RAG pipelines.** Clean post text with dates and links, ready to embed. One call returns a whole channel history.
- **News and OSINT research.** Pull a dated archive of a channel's posts and filter to the window you care about.
- **Crypto and trading signals.** Watch call channels and capture every post with its timestamp.
- **Content analytics.** Find which posts, formats, and times get the most views in a niche.
- **Backups.** Keep a durable copy of a channel you rely on.

### Input

| Setting | What it does |
|---|---|
| **Telegram channels** | Any format: `telegram`, `@durov`, `t.me/durov`, `https://t.me/s/durov` |
| **Max messages per channel** | Default 100. Paginates back through history as far as you ask. |
| **Only messages after / before** | Optional date window. The run stops early once it passes your start date, so you are not billed for history you did not want. |
| **Include reactions** | On by default |
| **Include a channel summary row** | On by default |
| **Proxy** | Off by default. Telegram is normally reachable without one. |

Bad input does not waste a run. A misspelled channel, a private invite link, or an unparseable date each produce a plain-English message, and the other channels in your list keep going.

### Sample output

```json
{
  "type": "message",
  "requestedChannel": "durov",
  "channel": "durov",
  "messageId": 548,
  "url": "https://t.me/durov/548",
  "date": "2026-09-11T16:04:02+00:00",
  "text": "🤝 Telegram has become the sponsor of Codeforces — the largest competitive programming platform...",
  "authorName": "Pavel Durov",
  "views": 688000,
  "viewsRaw": "688K",
  "totalReactions": 146385,
  "reactions": [
    { "emoji": "❤", "count": 73, "isPaid": false }
  ],
  "mediaTypes": [],
  "links": ["https://codeforces.com/blog/entry/156620"],
  "linkPreview": {
    "url": "https://codeforces.com/blog/entry/156620",
    "title": "Telegram Returns as Title Sponsor of Codeforces!",
    "siteName": "Codeforces"
  }
}
```

### What it cannot do, and why

Being straight about this saves you a wasted run:

- **Only public channels.** If a channel has turned off its web preview, nothing can read it without a logged-in account. This Actor deliberately does not use one. You get a clear message saying so rather than an empty dataset.
- **No private groups or invite links.** `t.me/+...` and `t.me/joinchat/...` are rejected up front.
- **No subscriber lists or member data.** Telegram does not publish them, and this Actor does not attempt to collect personal data.
- **View and reaction counts above 1,000 are rounded by Telegram itself** (`"688K"`). The exact figure is not published. `views` is the expanded number and `viewsRaw` keeps Telegram's original string so you can tell.
- **Custom emoji reactions have no text label** on the web, so those rows carry `customEmojiId` instead of an emoji character.

### More tools from steadyfeeds

- [Airbnb Listings Scraper](https://apify.com/steadyfeeds/airbnb-listings-scraper) — Search Airbnb and export prices, ratings and coordinates.
- [Airbnb Listing Details Scraper](https://apify.com/steadyfeeds/airbnb-listing-details) — Full detail for a listing: amenities, rules, host and photos.
- [Job Board Scraper](https://apify.com/steadyfeeds/job-board-scraper) — Every open role from company career pages across eight systems.
- [Events Scraper](https://apify.com/steadyfeeds/events-scraper) — public events from Eventbrite, Meetup and Luma in one run.

### Notes

Reads the same public pages you can open in a browser at `t.me/s/<channel>`. It collects channel content, not personal data.

Something broken or a field you need? Open an issue on this Actor and I will take a look.

# Actor input Schema

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

Public channels to scrape. Any of these forms work: telegram, @durov, t.me/durov, https://t.me/s/durov. Private groups and invite links (t.me/+...) cannot be read from the web.

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

How many of the most recent messages to return for each channel. Messages come back newest first, so a partial run is still useful.

## `fromDate` (type: `string`):

Stop once messages get older than this date. Use 2026-09-01 or 2026-09-01T12:00:00Z. Leave empty for no lower bound.

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

Skip messages newer than this date. Use 2026-09-30 or 2026-09-30T23:59:59Z. Leave empty for no upper bound.

## `includeReactions` (type: `boolean`):

Collect reaction emoji and counts. Custom emoji have no text label on the web, so those return an ID instead.

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

Add one row per channel with its title, description, subscriber count and photo, alongside the message rows.

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

Telegram is usually reachable without a proxy. Turn one on if you hit rate limits on large runs.

## Actor input object example

```json
{
  "channels": [
    "telegram",
    "durov"
  ],
  "maxMessages": 100,
  "includeReactions": true,
  "includeChannelInfo": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `messages` (type: `string`):

All scraped messages and channel summaries as JSON.

## `spreadsheet` (type: `string`):

The same results as an .xlsx spreadsheet.

## `csv` (type: `string`):

The same results as a CSV file.

# 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"
    ]
};

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

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

```

## MCP server setup

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