# Telegram Channel Scraper — Messages, Views & Media | from $3/1K (`bovi/telegram-channel-scraper`) Actor

Scrape public Telegram channel messages with text, view counts, timestamps, media type, links, forwards, and reply threading — no API key, no login, no proxy required. Structural HTML parser (not class-name fragile) with parse\_confidence drift signal. Paginates backwards via cursor.

- **URL**: https://apify.com/bovi/telegram-channel-scraper.md
- **Developed by:** [Vitalii Bondarev](https://apify.com/bovi) (community)
- **Categories:** Social media, Marketing, News
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN 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 a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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 — Messages, Views & Media

Scrape messages from any public Telegram channel — no API key, no Telegram account, no proxy required. This Telegram channel scraper extracts message text, view counts, timestamps, media type, links, forward source, and reply threading from public channels accessible via `t.me`.

Use it for brand monitoring, crypto/news signal aggregation, competitive intelligence, or feeding Telegram content into LLM pipelines.

### How the Telegram scraper works

Uses the public Telegram web preview at `https://t.me/s/{channel}` — the same URL anyone can open in a browser. Paginates backwards via `?before={message_id}` to collect historical messages going as far back as the channel's public web history allows.

No unofficial MTProto API, no bot token, no phone number verification. Just HTTP + structural HTML parsing.

### Why this Telegram scraper is more reliable than alternatives

Most Telegram scrapers use the MTProto API (requires a phone number and Telegram account) or depend on CSS class names that break on every Telegram web redesign. This actor uses **structural XPath parsing** on the semantic HTML structure — `data-*` attributes and element structure, not fragile class names. When Telegram updates its web UI, `parse_confidence` drops below 0.8 and warnings flag the affected fields — you get a drift signal, not silent wrong data.

### Input

```json
{
  "channels": ["telegram", "@durov", "https://t.me/cointelegraph"],
  "maxMessages": 200
}
````

| Field | Type | Description |
|---|---|---|
| `channels` | string\[] | Public channel usernames, @handles, or t.me URLs |
| `maxMessages` | integer | Max messages per channel (default: 100) |
| `beforeId` | integer | Optional cursor — only collect messages before this ID |

### Output

One row per message:

| Field | Type | Description |
|---|---|---|
| `channel` | string | Channel username |
| `message_id` | integer | Telegram message ID |
| `text` | string|null | Message text content |
| `views` | string|null | View count (e.g. "1.5M", "42K") |
| `datetime` | string | ISO-8601 UTC timestamp |
| `has_media` | boolean | Whether the message contains media |
| `media_type` | string|null | "photo", "video", "document", "sticker", "audio", "poll" |
| `links` | string\[] | HTTP/HTTPS links in message text |
| `is_forwarded` | boolean | Whether forwarded from another channel |
| `forward_from` | string|null | Source channel/user name if forwarded |
| `reply_to` | integer|null | Message ID being replied to |
| `message_url` | string | Full https://t.me/{channel}/{id} URL |
| `parse_confidence` | float | 0.0–1.0 quality signal; below 0.8 check `warnings` |
| `warnings` | string\[] | Parse quality warnings (e.g. "missing\_datetime") |
| `scraped_at` | string | ISO-8601 UTC scrape timestamp |

### What it does NOT support

- **Private channels** — only public channels accessible via t.me/s/{channel}
- **Comments/replies within posts** — web preview shows channel messages only
- **Media downloads** — returns media type detection only, not URLs to media files
- **Real-time streaming** — pulls historical messages, not a live feed

### Competitive edge

| Feature | This actor | @maximedupre/telegram-channel-messages-scraper |
|---|---|---|
| `parse_confidence` field | ✓ | ✗ |
| Pagination cursor input (`beforeId`) | ✓ | ✗ |
| Forward source name | ✓ | ✗ |
| Reply-to message ID | ✓ | ✗ |
| Structural parser (not class-name fragile) | ✓ | ✗ |
| Price | PPE $3/1K messages | ~$50/mo fixed |

### Frequently asked questions

#### Can I scrape a private Telegram channel?

No. This actor only works on public channels accessible via `t.me/s/{channel}`. Private channels, groups, and direct messages are not supported.

#### Does this require a Telegram bot token or phone number?

No. The actor scrapes the public Telegram web preview (`t.me/s/*`) — no account, no bot token, no API credentials needed.

#### How far back can I scrape?

As far back as Telegram's public web preview stores. Most active channels have several years of history available. Use `maxMessages` and `beforeId` cursor to control the range.

#### Does it download media files?

No. The actor detects media type (`photo`, `video`, `document`, `sticker`, `audio`, `poll`) and returns the type flag, but does not download or return media URLs. This keeps the output lean and the cost low.

#### How is pricing calculated?

**Pay-per-result** (PPE) at **$3.00 per 1,000 messages** ($0.003/message). One charge (`message-scraped` event) per message pushed to the dataset. Failed fetches, retries, and pagination probes are not charged.

### Integrations

Built for brand monitors, crypto-signal aggregators, and LLM-pipeline builders ingesting public Telegram channel content — the JSON/dataset output drops into the tools you already run, no glue code:

- **n8n / Make / Zapier** — trigger a run or pipe every new dataset item into 500+ apps (Google Sheets, Airtable, Slack, HubSpot, your database) with no code: [n8n](https://docs.apify.com/platform/integrations/n8n), [Make](https://docs.apify.com/platform/integrations/make), [Zapier](https://docs.apify.com/platform/integrations/zapier).
- **Webhooks** — fire your own endpoint the moment a run finishes, to push results straight into your pipeline ([docs](https://docs.apify.com/platform/integrations/webhooks)).
- **MCP server** — expose this actor as a tool to Claude, Cursor, or any [MCP client](https://mcp.apify.com) so an AI agent can pull this data mid-conversation ([guide](https://blog.apify.com/how-to-use-mcp/)).
- **API & SDKs** — fetch the dataset as JSON, CSV, or Excel through the Apify REST API or the Python / JS SDKs.

See all [Apify integrations](https://apify.com/integrations).

### Legal

This actor scrapes the publicly accessible web preview of Telegram channels (`t.me/s/*`). This is identical to what a browser sees when visiting the URL. Only public channels (already freely accessible to anyone on the internet) are scraped.

*Not affiliated with Telegram.*

# Actor input Schema

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

Public Telegram channel usernames to scrape. Each item can be a bare username (e.g. 'telegram'), an @handle (e.g. '@durov'), or a full t.me URL (e.g. 'https://t.me/telegram'). Only public channels are supported — private channels are not accessible via the web preview.

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

Maximum number of messages to collect per channel. The actor paginates backwards from the most recent message. Keep low (20–100) for quick sampling; set higher (500+) for bulk research or archive exports. Each message costs one PPE charge.

## `beforeId` (type: `integer`):

Optional: only collect messages with ID lower than this value. Use to scrape a specific historical window or to resume a previous crawl from a known checkpoint. Leave empty to start from the most recent messages.

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

Apify Proxy settings. RESIDENTIAL proxy is recommended for best reliability. Leave default (useApifyProxy: true) unless you have a reason to change.

## Actor input object example

```json
{
  "channels": [
    "telegram"
  ],
  "maxMessages": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset containing Telegram Channel Scraper records (channel, message\_id, datetime, views, text, media\_type, links, message\_url, parse\_confidence).

# 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"
    ],
    "maxMessages": 100,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("bovi/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"],
    "maxMessages": 100,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("bovi/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"
  ],
  "maxMessages": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call bovi/telegram-channel-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Telegram Channel Scraper — Messages, Views & Media | from $3/1K",
        "description": "Scrape public Telegram channel messages with text, view counts, timestamps, media type, links, forwards, and reply threading — no API key, no login, no proxy required. Structural HTML parser (not class-name fragile) with parse_confidence drift signal. Paginates backwards via cursor.",
        "version": "0.1",
        "x-build-id": "fglWmMLRyVORV1cJa"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/bovi~telegram-channel-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-bovi-telegram-channel-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/bovi~telegram-channel-scraper/runs": {
            "post": {
                "operationId": "runs-sync-bovi-telegram-channel-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/bovi~telegram-channel-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-bovi-telegram-channel-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "channels"
                ],
                "properties": {
                    "channels": {
                        "title": "Telegram Channels",
                        "type": "array",
                        "description": "Public Telegram channel usernames to scrape. Each item can be a bare username (e.g. 'telegram'), an @handle (e.g. '@durov'), or a full t.me URL (e.g. 'https://t.me/telegram'). Only public channels are supported — private channels are not accessible via the web preview.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxMessages": {
                        "title": "Max Messages Per Channel",
                        "minimum": 1,
                        "maximum": 50000,
                        "type": "integer",
                        "description": "Maximum number of messages to collect per channel. The actor paginates backwards from the most recent message. Keep low (20–100) for quick sampling; set higher (500+) for bulk research or archive exports. Each message costs one PPE charge.",
                        "default": 100
                    },
                    "beforeId": {
                        "title": "Before Message ID",
                        "type": "integer",
                        "description": "Optional: only collect messages with ID lower than this value. Use to scrape a specific historical window or to resume a previous crawl from a known checkpoint. Leave empty to start from the most recent messages."
                    },
                    "proxyConfiguration": {
                        "title": "Proxy Configuration",
                        "type": "object",
                        "description": "Apify Proxy settings. RESIDENTIAL proxy is recommended for best reliability. Leave default (useApifyProxy: true) unless you have a reason to change.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ]
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
