# Telegram Scraper: Channels, Keyword Alerts, No Login (`chimey_forearm/telegram-channel-scraper`) Actor

Telegram channel scraper with keyword search: export public channel posts, views, reactions, photos, videos, polls and subscriber counts. Only new posts on scheduled runs. No login or API key. $0.40 per 1,000 posts. Export data, run via API, schedule and monitor runs, or integrate with other tools.

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

## Pricing

from $0.40 / 1,000 results

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 do?

> **Telegram scraper, Telegram channel scraper and Telegram keyword search scraper in one.** Watch many public channels for your keywords and, on scheduled runs, get only the posts that are new. No login, no API key. Channels it can't read come back as error rows with the reason, never as a silent empty run.

![Telegram Scraper output table: channel records and posts with date, views, text, reactions, photos and videos](https://api.apify.com/v2/key-value-stores/ZA74NSNlX7nM76ZW5/records/telegram-output.png)

| What you can extract | Features & integrations |
|---|---|
| 📝 **Post text**: full message text and hashtags | **Keyword search**: many channels and words in one run |
| 👁️ **Date & views**: publish time, view count, edited flag | **Date window**: start and end dates, jumps straight to the month |
| ❤️ **Reactions**: each reaction and its count | **Only new posts**: per-channel bookmark for scheduled runs |
| 🖼️ **Media links**: photo and video URLs | **Scheduling**: run it hourly, daily or weekly with Apify schedules |
| 📊 **Polls & link previews**: poll options and preview title/URL | **Export anywhere**: JSON, CSV, Excel, XML or HTML from the dataset |
| 🔁 **Forwards**: the channel a post was forwarded from | **API & SDKs**: Apify REST API plus JavaScript and Python clients |
| 📢 **Channel info**: title, description, subscriber count | **Webhooks & integrations**: Zapier, Make, Slack, Google Drive and more |
| 🔑 **Matched keywords**: which of your words each post hit | **AI agents (MCP)**: call it from Claude or other agents via Apify's MCP server |

**Try it free in 1 click:** open this [ready-made example](https://apify.com/chimey_forearm/telegram-channel-scraper/examples/telegram-keyword-alerts-for-crypto-channels) and press Start. Apify's free plan includes $5 of usage every month, no credit card needed. The Input example below returned 12 records and costs about $0.005 at list price.

- **Telegram channel scraper**: export posts from any **public Telegram channel** (`durov`, `@durov` or `https://t.me/durov`) to JSON, CSV or Excel.
- **Telegram keyword search and monitor**: watch many channels for your words; only matching posts are saved (and charged), each tagged with `matchedKeywords`.
- **Only new Telegram posts on a schedule**: `onlyNewPosts` keeps a bookmark per channel, so each scheduled run returns only posts published since the last one.
- **Telegram posts by date range**: start and end dates; it jumps straight to that month instead of paging through years of newer posts.
- **Telegram views, reactions and media**: view counts, reaction counts, photo and video URLs, polls, link previews, forwards, hashtags.
- **Telegram channel stats**: title, description, subscriber count, verified flag.
- **An alternative to the Telegram API**: no Telegram API key, no phone number login and no Telegram account needed. It reads Telegram's public web preview (`t.me/s/…`) with plain HTTP requests, no headless browser, in 256 MB.

#### What makes it different

- **Keyword monitor across many channels.** Give it channels and words; only posts that mention them are saved and charged, each tagged with `matchedKeywords`.
- **Only new posts, automatically.** Turn on `onlyNewPosts` and it keeps a bookmark per channel (and per keyword list) in your own key-value store. In our test, the first run found 38 matching posts across 3 channels and the next scheduled run returned 0 duplicates.
- **Date window that jumps.** Set a start and an end date and it jumps straight to that month (binary search over post IDs) instead of paging through years of newer posts.

### What data can Telegram Channel Scraper extract?

| | | |
|---|---|---|
| 📢 `channel`: channel username | 🆔 `postId`: post number | 🔗 `url`: link to the post |
| 📅 `date`: publish time (UTC) | 👁️ `views`: view count | ✏️ `edited`: edited flag |
| 📝 `text`: post text | ✍️ `author`: author signature | ❤️ `reactions`: emoji and count |
| 🖼️ `photos`: photo URLs (whole album) | 🎬 `videos`: video `url`, `thumbnailUrl`, `duration` | 📊 `poll`: question, options with %, voters |
| 📰 `linkPreview`: url, site, title, description | 📎 `document`: file title and size | 🔁 `forwardedFrom` / `forwardedFromUrl`: original channel |
| ↩️ `replyToPostId` / `replyToUrl`: replied-to post | #️⃣ `hashtags` and `links` in the text | 🔑 `matchedKeywords`: your words it hit |
| 👥 `subscribers`: subscriber count (channel record) | 🏷️ `title` / `description`: channel info | ✅ `verified`: verified channel (channel record) |

Every record has a `type`: `post`, `channel` or `error`.

### How to use Telegram Channel Scraper in 5 steps

1. Create a free [Apify account](https://console.apify.com/sign-up).
2. Open [Telegram Channel Scraper](https://apify.com/chimey_forearm/telegram-channel-scraper).
3. Add your input: one or more public channels, and optionally keywords, a start and end date, or **Only new posts since last run**.
4. Click **Start**. A 100-post run usually finishes in under a minute.
5. Download the results as JSON, CSV or Excel from the **Output** tab, or pull them with the API.

Prefer a ready-made setup? Open a public example task, such as [Telegram keyword alerts for crypto channels](https://apify.com/chimey_forearm/telegram-channel-scraper/examples/telegram-keyword-alerts-for-crypto-channels) or [Scrape the latest posts from a Telegram channel](https://apify.com/chimey_forearm/telegram-channel-scraper/examples/scrape-the-latest-posts-from-a-telegram-channel).

### Input

Paste this into the **Input** tab (JSON view) and click **Start**. We ran exactly this on Oct 19, 2026: it returned 12 records (2 channel records and 10 matching posts).

```json
{
  "channels": [
    "durov",
    "cointelegraph"
  ],
  "keywords": [
    "bitcoin",
    "telegram"
  ],
  "maxPostsPerChannel": 5,
  "includeChannelInfo": true
}
```

| Field | Description |
|---|---|
| `channels` | Usernames (`durov`), handles (`@durov`) or links (`https://t.me/durov`) |
| `maxPostsPerChannel` | How many of the newest posts to save per channel (default 100) |
| `keywords` | Optional. Only save posts whose text, link preview, poll or file name contains any of these words (case-insensitive) |
| `onlyPostsNewerThan` | Optional start date, e.g. `2026-01-01` (UTC) |
| `onlyPostsUntil` | Optional end date (inclusive), e.g. `2026-03-31` (UTC) |
| `onlyNewPosts` | Only return posts newer than the last run's newest post, per channel (default false) |
| `stateStoreName` | Named key-value store that keeps those bookmarks (default `telegram-scraper-state`) |
| `includeChannelInfo` | Adds one channel record per channel (default true) |

#### More tested inputs

**Compare subscriber counts and recent posts across channels**

```json
{
  "channels": ["durov", "telegram", "cointelegraph"],
  "maxPostsPerChannel": 10,
  "includeChannelInfo": true
}
```

**Every post that mentions a keyword in a date range** (March 2025, Bitcoin or ETF; you only pay for matching posts)

```json
{
  "channels": ["cointelegraph"],
  "keywords": ["bitcoin", "ETF"],
  "onlyPostsNewerThan": "2025-03-01",
  "onlyPostsUntil": "2025-03-31",
  "maxPostsPerChannel": 20
}
```

**Monitor channels on a schedule and get only new posts.** Save this as a task and schedule it (for example hourly). The first run returns the latest posts; every later run returns only posts published since the previous run.

```json
{
  "channels": ["durov", "telegram"],
  "onlyNewPosts": true,
  "stateStoreName": "my-telegram-monitor",
  "maxPostsPerChannel": 50,
  "includeChannelInfo": false
}
```

### Output

A real post record from the run above (photo URL shortened):

```json
{
  "type": "post",
  "channel": "cointelegraph",
  "postId": 72748,
  "url": "https://t.me/cointelegraph/72748",
  "date": "2026-10-20T00:03:28+00:00",
  "edited": false,
  "author": null,
  "text": "🔥 NOW: BlackRock files for the iShares Bitcoin Managed Protection ETF under the ticker $PBIT, a “buffer” ETF trading some upside for downside protection.\n\nNews | Markets | YouTube",
  "views": 1450,
  "forwardedFrom": null,
  "forwardedFromUrl": null,
  "replyToUrl": null,
  "replyToPostId": null,
  "isAlbum": false,
  "photos": [
    "https://cdn5.telesco.pe/file/iJOsXmAC5xoFjqj….jpg"
  ],
  "videos": [],
  "videoCount": 0,
  "hasDocument": false,
  "document": null,
  "hasPoll": false,
  "poll": null,
  "links": [
    "https://cointelegraph.com/",
    "https://cointelegraph.com/category/markets",
    "https://www.youtube.com/@cointelegraph"
  ],
  "hashtags": [],
  "reactions": [
    {
      "emoji": "👎",
      "count": 8
    },
    {
      "emoji": "🔥",
      "count": 3
    },
    {
      "emoji": "❤",
      "count": 1
    }
  ],
  "linkPreview": null,
  "scrapedAt": "2026-10-20T01:40:47.254Z",
  "matchedKeywords": [
    "bitcoin"
  ]
}
```

And the channel record from the same run (avatar URL shortened):

```json
{
  "type": "channel",
  "channel": "durov",
  "url": "https://t.me/durov",
  "title": "Pavel Durov",
  "description": "Founder of Telegram.",
  "avatarUrl": "https://cdn4.telesco.pe/file/HjebGBCgiTEDyu1….jpg",
  "verified": true,
  "subscribers": 10300000,
  "photos": 102,
  "videos": 47,
  "links": 200,
  "scrapedAt": "2026-10-20T01:40:46.604Z"
}
```

Real rows from an earlier run with the default input (text shortened):

| channel | postId | date | views | text |
|---|---|---|---|---|
| durov | 552 | 2026-10-11 | 1050000 | ✨ Designers × AI 🆕 The mockup era is over. Today’s AI tools … |
| durov | 551 | 2026-10-10 | 1330000 | 💸 If your wallet doesn’t look like this, don’t even bother s… |
| durov | 548 | 2026-09-11 | 3400000 | 🤝 Telegram has become the sponsor of Codeforces — the larges… |

You can download the dataset as JSON, CSV, Excel, XML or HTML.

### How can I use the data?

- **Crypto, news and brand monitoring**: keyword alerts across many channels, only new posts on each scheduled run.
- **Market and competitor research**: compare subscribers, posting rhythm, views and reactions across channels.
- **LLM and RAG datasets**: clean post text with dates, links and hashtags.
- **Engagement tracking**: see how views and reactions change over time.
- **Sentiment analysis**: export posts from a date window into a spreadsheet or pipeline.

### More Actors from the same developer

| Actor | What it does |
|---|---|
| [Substack Scraper](https://apify.com/chimey_forearm/substack-to-markdown) | Substack newsletters to clean Markdown, plus podcast transcripts |
| [Greenhouse & Workday Jobs Scraper](https://apify.com/chimey_forearm/ats-jobs-scraper) | Jobs from 8 career-site platforms with visa sponsorship and clearance flags |
| [App Store & Google Play Reviews Scraper](https://apify.com/chimey_forearm/app-reviews-scraper) | Reviews from both stores in one run, only new reviews on schedules |
| [Website to Markdown Crawler](https://apify.com/chimey_forearm/sitemap-to-markdown) | Any website to Markdown for RAG, with incremental sync and llms.txt |
| [Government Bids & RFP Scraper](https://apify.com/chimey_forearm/opengov-bids-scraper) | Open bids and RFPs from 500+ US city and county portals on OpenGov |
| [State Bids Scraper](https://apify.com/chimey_forearm/state-bids-scraper) | Open bids from COMMBUYS, BidBuy, NJSTART, OregonBuys and NevadaEPro |
| [PERM Green Card Sponsors](https://apify.com/chimey_forearm/perm-green-card-sponsors) | Companies that sponsor green cards, from official DOL PERM data |

### Error items

The run doesn't stop for one bad channel. Instead it saves an error record with `type: "error"`, `channel`, `url`, `error` and (for the first two codes) `errorMessage`:

| `error` | When | `errorMessage` |
|---|---|---|
| `INVALID_CHANNEL` | The input isn't a valid username (letters, digits, underscores) or t.me link; `url` is null | "Not a valid Telegram channel username (letters, digits, underscores) or t.me link." |
| `NOT_A_PUBLIC_CHANNEL` | The channel doesn't exist, is private, or has its web preview turned off | "Channel not found, private, or has web preview disabled." |
| `FETCH_FAILED` | A page couldn't be loaded (network errors, rate limits and server errors are tried up to 4 times first); `url` is the page that failed | none |

Real error records from a test run with `"channels": ["durov", "not a channel!", "thischanneldoesnotexist_zz9q"]`:

```json
{
  "type": "error",
  "channel": "not a channel!",
  "url": null,
  "error": "INVALID_CHANNEL",
  "errorMessage": "Not a valid Telegram channel username (letters, digits, underscores) or t.me link."
}
{
  "type": "error",
  "channel": "thischanneldoesnotexist_zz9q",
  "url": "https://t.me/thischanneldoesnotexist_zz9q",
  "error": "NOT_A_PUBLIC_CHANNEL",
  "errorMessage": "Channel not found, private, or has web preview disabled."
}
```

Error records are saved to the dataset, so they count as results. If no channel in the input is valid, each bad entry gets an `INVALID_CHANNEL` record and the run ends with a clear status message. If a date isn't in YYYY-MM-DD form, or the start date isn't before the end date, the run ends right away with a status message and no records. Either way the run shows Succeeded, so a typo never turns into a failed run. When your spending limit is reached, the run stops and says so in the log.

### Limitations

- Public channels only. Private channels and groups aren't visible without logging in.
- Data comes from Telegram's public web preview (`t.me/s/…`). Channels that turn the preview off can't be scraped.
- Large videos have no file URL in the public preview (`url` is null); you still get the thumbnail, duration and post URL. Photo and video links are Telegram CDN links that expire after a while, so download files soon after the run.
- Some reactions come back with an empty `emoji` and only a `count` (seen on durov's channel in our Oct 19, 2026 run).
- The keyword filter reads every post back to your start date, so on very large channels add **Only posts newer than** to keep runs short. It matches the exact text (case-insensitive), not word forms.
- With **Only new posts**, a run returns at most **Max posts per channel** new posts per channel; if more were published since the last run, the oldest of them are skipped. Set the limit above what a channel posts between runs.
- Comments, and the edit history of posts, aren't in the public preview.

### FAQ

#### How much does it cost?

Pay per event: **$0.40 per 1,000 results** ($0.0004 per post, channel or error record saved), plus $0.00005 per run start. With keywords, you only pay for matching posts. The run stops on its own when it hits your spending limit. See the [Pricing tab](https://apify.com/chimey_forearm/telegram-channel-scraper/pricing).

#### Can I connect it to Make, Zapier, Google Sheets or Slack?

Yes. Use Apify's integrations for Make, Zapier, n8n, Google Sheets, Google Drive and Slack, or a webhook that fires when a run finishes. Pair it with a schedule and **Only new posts** for a hands-off Telegram feed.

#### Can I run it through the API?

Yes, with the Apify REST API or the official clients. Node.js (`npm install apify-client`):

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('chimey_forearm/telegram-channel-scraper').call({
    channels: ['durov', 'cointelegraph'],
    keywords: ['bitcoin', 'telegram'],
    maxPostsPerChannel: 5,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

Python (`pip install apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("chimey_forearm/telegram-channel-scraper").call(run_input={
    "channels": ["durov", "cointelegraph"],
    "keywords": ["bitcoin", "telegram"],
    "maxPostsPerChannel": 5,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

#### Can AI agents use it (MCP)?

Yes. Connect Claude, Cursor or another MCP client to [Apify's MCP server](https://mcp.apify.com) and add `chimey_forearm/telegram-channel-scraper` as a tool, so the agent can scrape Telegram channels on demand.

#### Is it legal to scrape Telegram?

This Actor only reads publicly available pages of public channels, with no login. Posts can still contain personal data, which laws such as the GDPR protect, so only collect what you have a legitimate reason to use. You're responsible for using the data in line with Telegram's terms and the privacy laws that apply to you. If unsure, ask a lawyer.

#### Where do I report a bug or ask for a feature?

Open an issue in the **Issues** tab; I usually reply within a day.

If it saved you time, a quick review on the Store helps a solo developer keep improving it. Bugs or ideas? Open an Issue.

# Actor input Schema

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

Public Telegram channels: usernames (durov), @handles, or links (https://t.me/durov).

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

Newest posts first. Stops when this many posts are saved for each channel.

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

Optional. Only save posts whose text, link preview, poll or file name contains at least one of these words or phrases (case-insensitive). The scraper still reads the whole channel back to your start date, but you only pay for matching posts. Set 'Only posts newer than' to keep runs short on big channels. Each saved post lists its matchedKeywords.

## `onlyPostsNewerThan` (type: `string`):

Optional start date (YYYY-MM-DD, UTC). Older posts are skipped and scraping stops once it reaches them.

## `onlyPostsUntil` (type: `string`):

Optional end date (YYYY-MM-DD, UTC), inclusive. Newer posts are skipped. The scraper jumps straight to this date, so getting 2024 posts from a huge channel doesn't mean paging through everything since.

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

For scheduled runs: remembers the newest post ID per channel (and per keyword list) in a named key-value store, and next time only returns posts published after it. The first run returns posts as usual. If a run is stopped early, that channel's bookmark isn't moved, so you can get repeats but never gaps.

## `stateStoreName` (type: `string`):

Name of the key-value store that keeps the 'only new posts' bookmarks. Use a different name per schedule or project to keep them apart.

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

Add one record per channel with title, description and subscriber count.

## Actor input object example

```json
{
  "channels": [
    "durov"
  ],
  "maxPostsPerChannel": 100,
  "onlyNewPosts": false,
  "stateStoreName": "telegram-scraper-state",
  "includeChannelInfo": true
}
```

# Actor output Schema

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

No description

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

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

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

```

## MCP server setup

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