# Telegram Channel Scraper: Messages, Views, No Login (`meskaoui.azeddine/telegram-channel-scraper`) Actor

Scrape messages from any public Telegram channel without an account, API key or phone number: text, date, views, reactions, links, hashtags, photos, videos and subscriber count. Filter by keyword or date. $1.50 per 1,000 messages. CSV, Excel, JSON, API.

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

## Pricing

$1.50 / 1,000 message scrapeds

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?

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 channels, no login

Get messages from any public Telegram channel, with no Telegram account, no API key and no phone number.

For each message: text, date, views, reactions, links, hashtags, photos, video, forwarded source, plus the channel's title and subscriber count.

**Measured on Apify, October 2026:** 18,387 messages from 24 channels in one run of 10 min 40 s through datacenter proxies, no failed channel, no duplicate, 288 MB peak memory. A smaller run of 1,500 messages from 5 channels took under 3 minutes.

### Pricing

**$1.50 per 1,000 messages** ($0.0015 per message delivered). No start fee, no charge for compute time or proxies, and a channel that cannot be read costs nothing.

| You extract | You pay |
|---|---|
| 200 messages (the pre-filled example) | $0.30 |
| 1,000 messages | $1.50 |
| 10,000 messages | $15.00 |

### What it is for

- **Brand and market monitoring**: follow what channels in your industry publish, with a keyword filter.
- **Crypto and trading**: exchange announcements, listings, whale alerts, as structured rows the minute they are posted.
- **News and research**: archive what media and official channels published, with view counts as a reach signal.
- **Content analysis**: which posts get the most views and reactions on a channel, yours or a competitor's.
- **AI pipelines**: clean text and links, ready to summarise or embed.

### What you give it

- **Channels**: usernames or links, in any of these forms: `durov`, `@durov`, `https://t.me/durov`, `https://t.me/s/durov`.
- **How far back to go**: a number of messages per channel, a date (`2026-09-01`), or a period (`7 days`, `2 weeks`, `3 months`). Newest messages come first.
- **Keywords** (optional): keep only messages containing at least one of them.

### Example input

```json
{
    "channels": ["durov", "https://t.me/binance_announcements"],
    "maxMessagesPerChannel": 200,
    "newerThan": "30 days",
    "keywords": ["listing", "launch"],
    "proxyConfiguration": { "useApifyProxy": true }
}
```

### Example output

One row per message. Text is shortened here.

```json
{
    "channel": "durov",
    "messageId": 548,
    "url": "https://t.me/durov/548",
    "date": "2026-09-11T16:04:02+00:00",
    "edited": false,
    "text": "🤝 Telegram has become the sponsor of Codeforces — the largest competitive programming platform in the world…",
    "views": 2050000,
    "reactionsTotal": 71120,
    "reactions": [
        { "emoji": "star", "count": 21200 },
        { "emoji": "5399847211989246390", "count": 31900 }
    ],
    "mediaType": null,
    "photoUrls": [],
    "videoUrl": null,
    "videoThumbnailUrl": null,
    "documentTitle": null,
    "links": ["https://codeforces.com/blog/entry/156620"],
    "hashtags": [],
    "linkPreview": {
        "url": "https://codeforces.com/blog/entry/156620",
        "site": "Codeforces",
        "title": "Telegram Returns as Title Sponsor of Codeforces!",
        "description": "Hi, Codeforces!"
    },
    "forwardedFrom": null,
    "replyToUrl": null,
    "authorSignature": "Pavel Durov",
    "channelTitle": "Pavel Durov",
    "channelSubscribers": 10500000,
    "scrapedAt": "2026-10-05T17:11:15.772Z"
}
```

### Fields

| Field | Description |
|---|---|
| `channel`, `messageId`, `url` | Where the message lives. `url` opens it in Telegram |
| `date`, `edited` | Publication time (UTC) and whether the message was edited |
| `text` | Message text, line breaks kept |
| `views` | View count as shown by Telegram |
| `reactions`, `reactionsTotal` | Each reaction with its count, and the sum. `emoji` is the character; for custom (premium) emoji it is Telegram's numeric id, and `star` for paid reactions |
| `mediaType` | `photo`, `video`, `document`, `audio`, `poll`, `sticker`, or `null` for text only |
| `photoUrls`, `videoUrl`, `videoThumbnailUrl`, `documentTitle` | Media attached to the message |
| `links`, `hashtags` | Links and hashtags found in the text |
| `linkPreview` | The preview card Telegram shows for the first link: site, title, description |
| `forwardedFrom`, `replyToUrl`, `authorSignature` | Source of a forwarded message, the message replied to, the signing author |
| `channelTitle`, `channelSubscribers` | Channel name and subscriber count (can be turned off) |
| `scrapedAt` | When the row was collected |

In a 24-channel test, date and subscriber count were present on 100% of messages, views on 99.7%, text on 98.9% (the rest are media without caption).

### Run summary

Each run stores a `RUN_SUMMARY` record in the key-value store: for every channel, its status, subscriber count, number of messages saved and the date of the oldest one. A channel that cannot be read is reported there and in the log; it does not fail the run and produces no rows.

### Speed and cost

Telegram serves 20 messages per page, so 1,000 messages take 50 requests. Channels are read five at a time. Datacenter proxies are enough; residential proxies are not needed. Some proxy IPs are slow with Telegram: the Actor notices and replaces them during the run, and reports how many in `RUN_SUMMARY`. 512 MB of memory is plenty.

### Limits

- **Public channels only.** Private channels, groups and invite links (`t.me/+…`) cannot be read.
- **Some public channels have no web preview** and cannot be read either: the owner or Telegram disabled it (this is the case for several large media channels). They are reported as "no public preview". You can check a channel yourself by opening `https://t.me/s/<username>` in a browser: if it redirects to the channel's join page, no tool without a Telegram account can read it.
- No member lists and no comments: the Actor reads what the channel itself published.
- Subscriber and view counts are rounded by Telegram (10.5M, 187K).
- Media links point to Telegram's servers and expire after a while. Download the files soon after the run if you need to keep them.
- A keyword search with no date limit stops after scanning 5,000 messages per channel. Add a date or period to search further back.

### FAQ

**Do I need a Telegram account or API key?** No. The Actor reads the public web preview that Telegram publishes for every open channel.

**Can I get only new messages?** Schedule the Actor and set **Only messages newer than** to the schedule interval, for example `1 day` on a daily run.

**Is this legal?** The Actor only reads content that channel owners publish openly. Messages can still contain personal data written by their authors; make sure your use complies with the laws that apply to you, such as GDPR.

**Something is missing or broken?** Open an issue on the Issues tab with the channel you tried. Layout changes on Telegram's side are fixed quickly.

# Actor input Schema

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

Public channels, one per line: a username (durov, @durov) or a link (https://t.me/durov). Private channels, groups and invite links (t.me/+...) cannot be read.

## `maxMessagesPerChannel` (type: `integer`):

Newest messages first. The Actor stops a channel once it has this many messages.

## `newerThan` (type: `string`):

A date (2026-09-01) or a relative period (7 days, 2 weeks, 3 months). The Actor stops going back in time once it passes this point.

## `keywords` (type: `array`):

Keep only messages whose text contains at least one of these words. Case-insensitive. Leave empty to keep everything.

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

Adds the channel title and subscriber count to each message row.

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

Datacenter proxies are enough. Telegram does not require residential IPs for public channel previews.

## Actor input object example

```json
{
  "channels": [
    "durov",
    "https://t.me/telegram"
  ],
  "maxMessagesPerChannel": 100,
  "includeChannelInfo": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

All messages collected: text, date, views, reactions, links, media and channel info.

## `runSummary` (type: `string`):

For each channel: status, subscriber count, messages saved and the date of the oldest one, plus request, retry and slow-proxy-session counts.

# 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",
        "https://t.me/telegram"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("meskaoui.azeddine/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": [
        "durov",
        "https://t.me/telegram",
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

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

```

## MCP server setup

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