# Telegram Channel Scraper - Public Channel Messages (`sweet_stickball/telegram-public-channel-scraper`) Actor

Scrape messages from public Telegram channels: text, dates, views, media and links. Telegram scraper and channel message extractor using the t.me/s web preview. No Telegram account or API key needed.

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

## Pricing

from $2.10 / 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?

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 - Public Channel Messages

Extract messages from a **public Telegram channel** — no Telegram account, API key or bot token needed. Pass a channel URL or username and get structured messages back.

### How it works

Telegram exposes a public web preview for channels at `https://t.me/s/CHANNEL_NAME`. This actor fetches that static HTML page, parses the messages with BeautifulSoup, and paginates backwards to collect older messages. No headless browser or API credentials are used.

### Features

- **Simple input** — provide a channel URL or username
- **Flexible input parsing** — accepts `https://t.me/channel`, `https://t.me/s/channel`, `@channel`, or bare `channel` name
- **Pagination** — fetches older messages beyond the first page until `maxMessages` is reached
- **Extracted fields** — text, date, views, author, forwarded source, links, and media (photos, videos, documents, stickers)
- **Retries** — retries with exponential backoff on timeouts, rate limits (HTTP 429) and server errors
- **Order** — messages are pushed in chronological order (oldest first)

### Input

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `channelUrl` | string | Yes | — | Channel URL or username. Accepts: `https://t.me/channel`, `https://t.me/s/channel`, `@channel`, or `channel` |
| `maxMessages` | integer | No | 20 | Maximum messages to scrape (1–5000) |
| `includeMedia` | boolean | No | true | Include media URLs (photos, videos, documents, stickers) in output |

### Output

Each message is a flat JSON object:

```json
{
    "message_id": 12345,
    "channel": "example_news",
    "text": "Weekly update is out. Read more at https://example.com",
    "date": "2024-01-15T12:00:00+00:00",
    "author": "Example News",
    "views": 52000,
    "forwarded_from": null,
    "links": ["https://example.com"],
    "url": "https://t.me/example_news/12345",
    "media": [
        {"type": "photo", "url": "https://cdn4.telegram-cdn.org/..."}
    ]
}
```

#### Output fields

| Field | Type | Description |
|-------|------|-------------|
| `message_id` | integer | Unique message ID within the channel |
| `channel` | string | Channel username |
| `text` | string | Plain text content (newlines preserved) |
| `date` | string | ISO 8601 datetime |
| `author` | string | Channel or author name |
| `views` | integer | View count (parsed from K/M suffixes) |
| `forwarded_from` | string | null | Original author if forwarded |
| `links` | array | URLs found in message text |
| `url` | string | Direct link to the message |
| `media` | array | Media attachments (when `includeMedia` is true): `photo`, `video`, `video_thumbnail`, `sticker` (with `url`) or `document` (with `title`) |

### Use cases

- **Content monitoring** — track posts from competitors, influencers, or industry channels
- **OSINT research** — collect public communications for analysis
- **Trend detection** — monitor channel activity and engagement over time
- **Data journalism** — archive public channel content for reporting
- **Market research** — track product announcements and community discussions

### Pricing

Pay-per-event, **no start fee**: **$3.50 per 1,000 messages** on the Apify Free plan, with lower prices on paid plans.

| Event | Free | Starter | Scale | Business | Enterprise |
|-------|------|---------|-------|----------|------------|
| Message (`MESSAGE`) | $3.50 | $3.00 | $2.60 | $2.10 | $2.10 |

Prices in USD per 1,000 events.

#### Cost examples (Free plan)

| Scenario | Messages | Cost |
|----------|----------|------|
| Quick check (default) | 20 | $0.07 |
| Daily monitoring | 100 | $0.35 |
| Channel archive | 1,000 | $3.50 |
| Large-scale research | 5,000 | $17.50 |

### Limitations

- **Public channels only** — the actor reads the `t.me/s/` web preview; private channels and groups are not supported
- **Web preview must be enabled** — some channels disable the `t.me/s/` preview; those runs fail with a "not found or is private" error
- **No real-time streaming** — the actor scrapes a snapshot; for new messages, schedule recurring runs
- **Media URLs are CDN links** — they may expire after some time; download media promptly if needed
- **Rate limits** — Telegram may rate-limit frequent requests; the actor waits and retries on HTTP 429 (up to 3 attempts per page), then stops paginating

Python 3.11, async httpx, BeautifulSoup + lxml, Apify SDK.

### Related Actors

- [YouTube Transcript Scraper - Captions & Comments](https://apify.com/sweet_stickball/youtube-transcripts) — Scrape YouTube video transcripts (captions and auto-generated subtitles) with timestamps, video metadata and optional comments.
- [Google News Scraper - News Articles by Keyword](https://apify.com/sweet_stickball/google-news-scraper) — Scrape Google News articles for any keyword: headlines, sources, publish dates, URLs and snippets.
- [Google Trends Scraper - Interest Over Time & Related Queries](https://apify.com/sweet_stickball/google-trends-scraper) — Scrape Google Trends: interest over time and related queries for up to 5 compared keywords, by country, time range and category.

# Actor input Schema

## `channelUrl` (type: `string`):

The public Telegram channel to scrape. Accepts: full URL (https://t.me/channel_name), preview URL (https://t.me/s/channel_name), @channel_name, or bare channel_name.

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

Maximum number of messages to scrape. The actor paginates automatically to collect older messages.

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

When enabled, each message includes a media array with photo URLs, video URLs, document titles, and sticker URLs.

## Actor input object example

```json
{
  "channelUrl": "https://t.me/s/durov",
  "maxMessages": 10,
  "includeMedia": true
}
```

# Actor output Schema

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

Dataset items shown with the 'messages' view.

# 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 = {
    "channelUrl": "https://t.me/s/durov",
    "maxMessages": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("sweet_stickball/telegram-public-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 = {
    "channelUrl": "https://t.me/s/durov",
    "maxMessages": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("sweet_stickball/telegram-public-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 '{
  "channelUrl": "https://t.me/s/durov",
  "maxMessages": 10
}' |
apify call sweet_stickball/telegram-public-channel-scraper --silent --output-dataset

```

## MCP server setup

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