# Telegram Channel Scraper & Keyword Alerts | $0.50/1K (`layerwiselabs/telegram-channel-scraper`) Actor

Scrape posts from public Telegram channels without login: text, date, views, reactions, photos, videos, files, polls, link previews, forwards and replies. Exact date ranges, only new posts since the last run, and keyword alerts to Slack, Discord, webhook or e-mail.

- **URL**: https://apify.com/layerwiselabs/telegram-channel-scraper.md
- **Developed by:** [Layerwise Labs](https://apify.com/layerwiselabs) (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

$0.50 / 1,000 posts

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

### What does Telegram Channel Scraper & Keyword Alerts do?

It reads posts from **public Telegram channels** and returns them as clean, structured data, with no Telegram account, no phone number and no API keys. It can also **watch channels for you**: every run returns only the posts published since the last one, and posts that match your keywords can go straight to Slack, Discord, any webhook (Make, Zapier, n8n) or your e-mail.

Give it a channel name (`durov`, `@durov`) or a link (`https://t.me/durov`). For every post you get:

- **The content**: full text with line breaks and emoji, links, hashtags and mentions.
- **Media**: photos, videos with thumbnail and duration, albums with every picture, files and audio with their names, polls with options and results, link previews with title, description and image.
- **Engagement**: views, reactions per emoji, paid Telegram Stars.
- **Context**: date, edited flag, author signature, forwarded-from source, the post it replies to, and the channel's title and subscriber count.

### At a glance

| | This Actor |
|---|---|
| Date range | ✅ exact: jumps straight to the end of your range and stops reading at its start |
| Only new posts since the last run | ✅ built in, nothing skipped, nothing twice |
| Keyword filter with alerts to Slack, Discord, webhook or e-mail | ✅ built in, no extra integration needed |
| Channel that cannot be read (group, bot, private, misspelled) | ✅ named in the run status, with the reason in the log |
| Price | ✅ **$0.50 per 1,000 posts**, no start fee; media and posts filtered out cost nothing extra |

### Why use it?

- **Exact date ranges, fast.** Set *Posted from* and *Posted until* and the Actor finds the right spot in the channel in a few requests, even in channels with hundreds of thousands of posts. Reading stops as soon as older posts begin, so you only pay for posts in the range.
- **Monitoring that never misses a post.** With *Only new posts*, each run continues exactly after the last post it delivered. If a run stops early (spending limit, Telegram not answering), the next run picks up from there.
- **Keyword alerts built in.** Add keywords, a Slack, Discord, webhook or e-mail target, and a schedule. Each alert lists the new matching posts with a link, and an alert that could not be delivered is sent again with the next run.
- **Clear answers.** If an entry is a group, a bot, a personal account, an invite link or a channel that does not exist, the run says so instead of returning nothing.
- **Light and reliable.** The Actor reads Telegram's public web preview directly. It needs no proxy, retries hiccups by itself, and ends a run cleanly if Telegram stops answering, so no time or credit is spent waiting.
- **Fits your workflow.** Schedule it, export to JSON, CSV, Excel or Google Sheets, or call it from Make, Zapier or the API.

### Who uses it

- **Crypto and trading teams** following signal, news and project channels.
- **Brand and reputation monitoring**: get told when your company, product or domain is mentioned.
- **Researchers, journalists and OSINT analysts** archiving channels and analysing reach and topics.
- **Marketing teams** comparing competitors' channels: posting frequency, views and reactions.
- **AI and data teams** collecting text for search, classification or RAG.

### How to use it

1. Enter one or more **channels**: `durov`, `@durov`, `https://t.me/durov` or a link to any post of the channel.
2. Optionally set **Posted from** / **Posted until** (a date or a relative time such as `7 days`) and **Keywords**.
3. Set **Max posts per channel** and click **Start**.
4. Download the posts from the **Output** tab, or read them through the API.

**To monitor channels:** switch on **Only new posts**, optionally add keywords and a Slack, Discord, webhook or e-mail target, save the input as a **task**, and give the task a **schedule** (for example every hour). The first run returns the latest posts as usual and marks the starting point, without alerts. Every later run returns, and alerts about, only posts published since then. Give the monitor a task or a *Monitor name* so you can change keywords and alert targets later without starting over.

### How much does it cost to scrape Telegram channels?

Pay per event: **$0.50 per 1,000 posts** returned ($0.0005 per post). Apify platform usage is included, there is no start fee, and posts that your date range or keywords filter out are not charged. E-mail alerts are sent by Apify's own mail Actor, which adds about $0.001 of platform usage per e-mail; Slack, Discord and webhook alerts are free.

| What you do | Price |
|---|---|
| Last 100 posts of 10 channels | $0.50 |
| A year of a busy news channel (about 30,000 posts) | $15 |
| Hourly keyword monitoring of 20 channels with 50 matches a day | about $0.75 per month |

Free Apify plan users get $5 of credit every month, which is 10,000 posts.

### Input

| Field | What it does |
|---|---|
| `channels` | Channel usernames or t.me links. |
| `maxPostsPerChannel` | Posts returned per channel, newest first. In monitoring mode: new posts per run, oldest first; any others follow with the next run. |
| `dateFrom`, `dateTo` | Only posts published in this period (UTC). A day (`2026-10-01`), a full time (`2026-10-01T08:00:00Z`) or a relative time (`7 days`, `12 hours`). |
| `keywords` | Only posts that contain at least one of them, in the text, linked addresses, link preview, file names or poll. Case does not matter; `bitcoin` also finds `Bitcoins`. Put a keyword in quotes (`"AI"`) to match the exact word only. Without *Posted from*, a keyword search stops after looking through about 10,000 posts of a channel; monitoring runs read every new post. |
| `excludeKeywords` | Skip posts that contain any of these. |
| `onlyNewPosts`, `monitorName` | Monitoring: return only posts published since the previous run. |
| `slackWebhookUrl`, `discordWebhookUrl`, `webhookUrl`, `notifyEmail` | Where to send alerts about new posts. E-mail alerts go to the e-mail address of your Apify account. |
| `proxyConfiguration` | Usually not needed: the Actor reads Telegram directly. A proxy set here is used for every request. |

Example:

```json
{
  "channels": ["cointelegraph", "https://t.me/durov"],
  "keywords": ["bitcoin", "\"ETF\""],
  "onlyNewPosts": true,
  "slackWebhookUrl": "https://hooks.slack.com/services/…"
}
```

### Output

One item per post:

```json
{
  "channel": "cointelegraph",
  "channelTitle": "Cointelegraph",
  "channelSubscribers": 329000,
  "postId": 72796,
  "url": "https://t.me/cointelegraph/72796",
  "date": "2026-10-22T05:49:52Z",
  "edited": false,
  "author": null,
  "type": "photo",
  "text": "🚨 UPDATE: Zcash sets its Network Upgrade 7 to go live on mainnet at block 3,543,405, expected around Nov. 5.\n\nNews | Markets | YouTube",
  "views": 4300,
  "reactions": [
    { "emoji": "❤", "customEmojiId": null, "count": 25 },
    { "emoji": "🔥", "customEmojiId": null, "count": 11 }
  ],
  "paidStars": null,
  "media": [
    { "type": "photo", "url": "https://cdn5.telesco.pe/file/TSr3mz….jpg", "postUrl": "https://t.me/cointelegraph/72796" }
  ],
  "linkPreview": null,
  "poll": null,
  "forwardedFrom": null,
  "replyTo": null,
  "links": ["https://cointelegraph.com/", "https://cointelegraph.com/category/markets", "https://www.youtube.com/@cointelegraph"],
  "hashtags": [],
  "mentions": [],
  "albumPostIds": null,
  "scrapedAt": "2026-10-22T10:42:18Z"
}
```

`type` is `text`, `photo`, `video`, `album`, `document`, `audio`, `poll` or `other`. With keywords, each post also has `matchedKeywords`. Link previews come as `{url, siteName, title, description, imageUrl}`, polls as `{question, type, voters, options: [{text, percent}]}`, replies as `{url, postId, author, text}`.

The webhook alert is a JSON POST with `monitor`, `newPostsCount`, `runUrl` and `newPosts`: the main fields of up to 1,000 posts per alert, with the first 2,000 characters of each text. The full items are always in the run's dataset. More than 100 new posts are sent in several posts, numbered by `part` and `parts`.

### Use it through the API

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("layerwiselabs/telegram-channel-scraper").call(run_input={
    "channels": ["durov"],
    "dateFrom": "30 days",
    "maxPostsPerChannel": 500,
})
for post in client.dataset(run.default_dataset_id).iterate_items():
    print(post["date"], post["views"], post["text"][:80])
```

AI agents can call the Actor through the [Apify MCP server](https://mcp.apify.com) as a tool, for example "what did these five crypto channels post about Solana this week?".

### FAQ

#### Which channels can it read?

Every public channel whose web preview is on, which is the default: the same posts anyone sees at `t.me/s/<channel>` without logging in. Groups, private channels and invite links (`t.me/+…`) need a Telegram account, so the run names them as not readable and carries on with the other channels.

#### How does monitoring work?

With *Only new posts* on, the Actor remembers the last post it delivered for each channel, separately for each task or *Monitor name*. Every later run reads the channel from that post onwards and returns what is new, oldest first. In a task, or with a *Monitor name*, you can change keywords or alert targets at any time and the monitor carries on from the same post. Runs without either keep a separate memory for each combination of keywords and alert targets, so they never mix. If a run of the same monitor is still reading a channel when the next run starts, the new run leaves that channel to it, so no post is reported twice.

#### How exact are the view counts?

They are the numbers Telegram shows: exact below 1,000, rounded above (`5.83M` becomes `5830000`).

#### Do media links stay valid?

Photo and video links point to Telegram's CDN and work right after the run. Telegram renews them from time to time, so download the files you want to keep soon after the run; `url` of the post always leads back to it.

#### What happens if Telegram does not answer?

Short hiccups are retried. If Telegram stops answering altogether, the run ends cleanly after a few tries, keeps everything delivered so far, and says which channels to run again. A monitor simply continues where it stopped.

#### Is it legal to scrape Telegram channels?

The Actor reads only posts that channel owners publish openly on the web. Check that your use complies with the laws that apply to you, including data protection rules for any personal data in posts, and with Telegram's terms.

#### Something does not work

Open an issue in the **Issues** tab with the input you used, and we will look into it.

# Changelog

This Actor's version history is a separate document: https://apify.com/layerwiselabs/telegram-channel-scraper/changelog.md

# Actor input Schema

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

Public Telegram channels to read. Each line is a username (durov or @durov) or a link (https://t.me/durov, https://t.me/s/durov or a link to one of its posts).

## `maxPostsPerChannel` (type: `integer`):

How many posts to return per channel, newest first. With 'Only new posts', each run returns at most this many new posts per channel, oldest first; any others follow with the next run.

## `dateFrom` (type: `string`):

Only posts published on or after this day (UTC), or within a relative time such as '7 days'. Reading stops as soon as older posts begin, so you only pay for posts in the range.

## `dateTo` (type: `string`):

Only posts published on or before this day (UTC), or before a relative time such as '1 month'. The Actor jumps straight to that date, also in channels with years of posts.

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

Only posts that contain at least one of these words or phrases, in the text, linked addresses, link preview, file names or poll. Case does not matter, and a keyword also finds longer words that start with it (bitcoin finds Bitcoins). Put a keyword in quotes ("AI") to match the exact word only. Without Posted from, a search stops after looking through about 10,000 posts of a channel; monitoring runs read every new post. Posts without a match are not charged.

## `excludeKeywords` (type: `array`):

Skip posts that contain any of these words or phrases (same rules as Keywords).

## `onlyNewPosts` (type: `boolean`):

Remembers the last post of each channel and returns only posts published since the previous run. The first run returns the latest posts as usual and marks the starting point. Schedule the Actor (for example every hour) to follow channels, together with Keywords for keyword alerts.

## `monitorName` (type: `string`):

Names this monitor in alert titles and keeps its memory separate from other monitors of the same channels. Saved tasks get their own memory automatically.

## `slackWebhookUrl` (type: `string`):

Posts new posts to a Slack channel (Incoming Webhook URL). Needs 'Only new posts'.

## `discordWebhookUrl` (type: `string`):

Posts new posts to a Discord channel. Needs 'Only new posts'.

## `webhookUrl` (type: `string`):

Sends the new posts as JSON in a POST request, for example to Make, Zapier or n8n. Needs 'Only new posts'.

## `notifyEmail` (type: `string`):

Sends new posts by e-mail through the apify/send-mail Actor (about $0.001 of platform usage per e-mail). Use the e-mail address of your Apify account. Needs 'Only new posts'.

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

Usually not needed: the Actor reads Telegram directly. A proxy set here is used for every request.

## Actor input object example

```json
{
  "channels": [
    "durov"
  ],
  "maxPostsPerChannel": 20,
  "onlyNewPosts": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `posts` (type: `string`):

One item per post: channel, date, text, views, reactions, media and link.

# 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"
    ],
    "maxPostsPerChannel": 20,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("layerwiselabs/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"],
    "maxPostsPerChannel": 20,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("layerwiselabs/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"
  ],
  "maxPostsPerChannel": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call layerwiselabs/telegram-channel-scraper --silent --output-dataset

```

## MCP server setup

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