# Telegram Scraper API – Channels & Keyword Search, No Login (`k-data-lab/telegram-channel-scraper`) Actor

Telegram channel scraper and Telegram keyword search API, no login: export public channel messages, search keywords, hashtags and brand mentions, find channels for a topic, pull emails and links for leads, and monitor new posts. 500 messages free monthly.

- **URL**: https://apify.com/k-data-lab/telegram-channel-scraper.md
- **Developed by:** [K-Data Lab](https://apify.com/k-data-lab) (community)
- **Categories:** Social media, Automation, AI
- **Features:** Limited permissions
- **Stats:** 1 total users, 1 monthly users, 96.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.90 / 1,000 keyword matches

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 & Keyword Search API, No Login

**Search public Telegram channels for any keyword or hashtag, export a channel's message history, and collect the contacts channels publish, with no account, phone number or API key.** Give keywords, channels or both. You get one clean row per message with text, date, views, reactions, media, links, emails and channel details.

**Your first run is free.** The prefilled search takes about 10 seconds. Every month the first **100 keyword matches and 500 channel messages are free**, then **$1.20 per 1,000 keyword matches** or **$0.25 per 1,000 channel messages**. The $0.005 run start fee fits easily in the $5 credit of Apify's Free plan.

Real rows from a search for `anthropic` on 4 November 2026:

| Channel | Subscribers | Date | Message | Views | Reactions |
|---|---:|---|---|---:|---:|
| FinancialJuice | 8,375 | 2026-10-30 | Japan asks Anthropic and OpenAI for more access to advanced models - Nikkei | 434 | 1 |
| data_secrets | 95,909 | 2026-10-14 | В Anthropic перестали использовать git, теперь у них собственная система… | 30,800 | 329 |
| data_secrets | 95,909 | 2026-10-26 | ⚡️ Самое главное по IPO Anthropic одним словом | 25,800 | 467 |

#### 🚀 Pick your starting point

| You want | Paste this input |
|---|---|
| Telegram keyword search | `{ "keywords": ["bitcoin etf"], "since": "7 days" }` |
| Telegram channel messages | `{ "channels": ["durov"], "maxMessagesPerChannel": 200 }` |
| Brand mentions on Telegram | `{ "keywords": ["your brand"], "onlyNewMessages": true }` |
| Telegram leads for a topic | `{ "keywords": ["crypto marketing"], "resultType": "channels", "onlyWithContacts": true }` |
| Channel stats and subscribers | `{ "channels": ["durov"], "resultType": "channels" }` |

#### 🔍 What does it do?

- **Keyword search across Telegram.** Type a keyword. We find public channels about it, then run Telegram's own search inside each one.
- **Keyword search in your channels.** Give a watchlist and search only those.
- **Channel history.** Export the messages of any public channel, newest first, with date windows.
- **Channel lookup and finder.** Get title, bio, exact subscriber count and last post date, for channels you name or for a topic.
- **Contacts for leads.** Pull the emails, @handles and links a channel publishes in its bio or posts. Keep only rows that have one with `onlyWithContacts`.
- **Brand and social monitoring.** Turn on `onlyNewMessages`, schedule the run, and each run returns and charges only what's new.
- **Any language.** We tested English, Korean, Russian, German and Portuguese.

#### 💡 Why choose this actor?

| | This actor | Other Telegram keyword and channel scrapers |
|---|---|---|
| Keyword rows | Only messages with a visible match. The words Telegram matched are in `matchedText` | Often the latest post of each channel found, which may not mention your keyword |
| Rows per channel | Up to your limit, from Telegram's own search | Often one per page found |
| Keyword price | **$1.20 / 1,000** | About $2 to $4 / 1,000 |
| History price | **$0.25 / 1,000** | From about $0.32 / 1,000 |
| Free every month | ✅ 500 messages + 100 keyword matches | Usually none |
| Monitoring | ✅ One switch, memory kept for you | Some offer a message-ID cursor you store yourself |
| Old date windows | ✅ Jumps straight to the date | Varies |
| Subscribers | ✅ Exact (10,139,877), not the web's rounded 10.1M | Varies |
| Contacts | ✅ Emails, @handles and links from messages and channel bios | Varies |
| Login | ❌ None, ever | Varies |

Our test runs: 3,000 messages from 2 channels in 64 seconds, 0 retries, 0 duplicates.

#### 📥 Input examples

**Find messages about a topic, anywhere on public Telegram:**

```json
{ "keywords": ["bitcoin etf"], "since": "7 days", "maxMessagesPerChannel": 20 }
```

**Export channel history:**

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

**Search only your watchlist:**

```json
{ "keywords": ["openai", "anthropic"], "channels": ["FinancialJuice", "data_secrets"], "discoverChannels": false, "since": "30 days" }
```

**Brand monitoring on a schedule:**

```json
{ "keywords": ["your brand"], "onlyNewMessages": true, "monitorName": "brand-watch" }
```

**Build a channel list for a topic:**

```json
{ "keywords": ["crypto news"], "resultType": "channels", "minSubscribers": 10000 }
```

**Build a lead list of channels for a topic:**

```json
{ "keywords": ["crypto marketing"], "resultType": "channels", "onlyWithContacts": true, "minSubscribers": 1000 }
```

**Search one hashtag only:**

```json
{ "keywords": ["#ETF"], "exactMatch": true, "since": "7 days" }
```

Channels accept `durov`, `@durov`, `https://t.me/durov`, or a post link such as `https://t.me/telegram/458` for one post. Dates accept `2026-01-31` or `24 hours`, `7 days`, `2 weeks`, `1 month`.

| Input | What it does |
|---|---|
| `keywords` | Words or phrases to find |
| `channels` | Public channels to read or search |
| `discoverChannels` | Find more channels for your keywords (default on) |
| `resultType` | `messages`, or `channels` for one row per channel |
| `maxResults` | Total row limit, shared evenly between keywords (default 1,000) |
| `maxMessagesPerChannel` | Limit per channel, and per keyword (default 100) |
| `maxChannelsPerKeyword` | Channels to find per keyword (default 20, up to 60) |
| `since`, `until` | Date window |
| `onlyNewMessages`, `monitorName` | Monitoring |
| `minViews`, `minSubscribers`, `excludeKeywords`, `exactMatch`, `onlyWithMedia`, `onlyWithContacts` | Filters. Skipped rows aren't charged |
| `country`, `language` | Which channels are found, e.g. `kr` + `ko`. Doesn't change the messages |

#### 📤 Output

```json
{
  "recordType": "message",
  "keyword": "anthropic",
  "source": "discovered",
  "channelUsername": "FinancialJuice",
  "channelTitle": "FinancialJuice",
  "channelSubscribers": 8375,
  "messageId": 144051,
  "url": "https://t.me/FinancialJuice/144051",
  "date": "2026-10-30T15:12:42Z",
  "text": "Japan asks Anthropic and OpenAI for more access to advanced models - Nikkei|FJ",
  "views": 434,
  "reactionsTotal": 1,
  "reactions": [{ "emoji": "🔥", "count": 1, "customEmojiId": null, "isPaid": false }],
  "matchedText": ["Anthropic"],
  "scrapedAt": "2026-11-04T03:20:55Z"
}
```

Also on each row when present: `mediaType`, `photoUrls`, `videoUrls`, `videoThumbnailUrls`, `videoDurationSecs`, `voiceUrl`, `documentName`, `documentSize`, `stickerUrl`, `poll`, `linkPreview`, `links`, `hashtags`, `mentions`, `emails`, `forwardedFrom`, `forwardedFromUrl`, `replyToUrl`, `replyToAuthor`, `replyToText`, `authorSignature`, `isEdited`, `channelVerified`.

Channel rows have `channelDescription`, `channelType`, `hasPublicPreview`, `photosCount`, `videosCount`, `linksCount`, `filesCount`, `latestMessageId`, `lastPostDate` and `avatarUrl`. Download as JSON, CSV, Excel or XML. `RUN_SUMMARY` in the key-value store lists every channel with its status.

#### 💰 Pricing

You pay per result, and only for rows you receive. Bronze prices below; Free plan users pay slightly more, Silver and Gold slightly less. The Pricing tab shows every tier.

| Event | Price | Free each month |
|---|---:|---:|
| Keyword match | $0.0012 | 100 |
| Channel message | $0.00025 | 500 |
| Channel lookup (a channel you name) | $0.0008 | 50 |
| Channel found (for a keyword) | $0.002 | 20 |
| Run start | $0.005 | – |

Examples: 1,000 keyword matches cost $1.205. 10,000 channel messages cost $2.505. A daily brand monitor with 20 new matches a day costs about $0.75 a month after the free 100.

Set a maximum cost per run in the run options and the actor stops cleanly at that limit.

#### 🔁 Monitoring on a schedule

1. Set your keywords or channels, and turn on `onlyNewMessages`.
2. Save it as a task and add a schedule in Apify, hourly or daily.
3. Send results to Slack, Google Sheets, n8n, Make or Zapier with an Apify integration.

We remember the newest message for each channel and keyword, in a storage on your own Apify account. The first run returns everything within your limits. Use a different `monitorName` for each schedule. Set your limits above what you expect between runs: with a low limit, the older new messages are skipped.

#### 🔌 API, n8n, Make

```bash
curl -X POST "https://api.apify.com/v2/acts/k-data-lab~telegram-channel-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"keywords":["bitcoin etf"],"since":"7 days","maxResults":100}'
```

In n8n or Make, use the Apify module with the actor `k-data-lab/telegram-channel-scraper`.

#### 🤖 Use it from AI agents (MCP)

Add it as a tool in Claude, Cursor or any MCP client: `https://mcp.apify.com?tools=actors,k-data-lab/telegram-channel-scraper`.

| Ask your agent | The agent sends |
|---|---|
| What are public Telegram channels saying about this launch this week? | `keywords`, `since: "7 days"`, `maxResults: 50` |
| Get the latest messages from the Telegram channel @durov | `channels`, `maxMessagesPerChannel` |
| Find Telegram channels about AI agents with a contact | `keywords`, `resultType: "channels"`, `onlyWithContacts: true` |
| How many subscribers does this Telegram channel have? | `channels`, `resultType: "channels"` |

Every run writes `RUN_SUMMARY` to the key-value store, with a status for each channel, so an agent can tell an empty result from a wrong name. Use `maxResults: 10` for a cheap test.

#### ❓ FAQ

**Is there a Telegram API for public channels without a phone number?** This actor works as one. Call it over REST or MCP with a channel name or keyword and get JSON back. It reads Telegram's public web pages, so you don't need a phone number, an api_id or a bot token.

**How do I get emails from Telegram channels?** Set `resultType` to `channels` and turn on `onlyWithContacts`. `emails`, `mentions` and `links` hold what the channel published in its bio. On message rows they come from the post. Many channels list only an @handle.

**How do I monitor brand mentions on Telegram?** Set your brand as a keyword, turn on `onlyNewMessages` and schedule the run. Each run returns only new mentions.

**Does it search all of Telegram?** No tool can without being inside the app. We find relevant public channels with web search, then search inside them. Coverage depends on what web search knows, so add channels you already know to `channels`. New or tiny channels may not appear.

**Why are there fewer rows than my limit?** The channels had fewer matches, or your filters skipped them. Check `RUN_SUMMARY.perChannel`.

**Can it read groups or private channels?** No. Public groups and some channels have no web preview, so Telegram only shows their messages inside the app. They appear in `RUN_SUMMARY` as `NO_PUBLIC_PREVIEW`, and aren't charged. Group member lists and private invite links aren't supported, because they need a logged-in account.

**Does it include comments?** Not yet. Open an issue if you need them.

**Why are large view counts rounded?** Telegram shows 80.2K on the web, so `views` is 80200. Counts under 1,000 are exact.

**Do media links last?** Photo and video links are temporary Telegram CDN links. Download files you want to keep soon after the run. Telegram doesn't serve some large videos on the web; `viewableOnlyInTelegram` marks posts with nothing else to show.

**Why does a keyword row not contain my exact word?** Telegram's search matches word forms (update, updates), and some matches are in the link preview. Turn on `exactMatch` for your exact text. Telegram also returns some messages with no visible match; we drop those.

**Is it legal?** The actor reads only what any logged-out visitor can see at t.me/s. It doesn't collect phone numbers or member lists, and it doesn't read personal accounts. Emails and @handles appear only when a channel or post published them. They can still be personal data, so you're responsible for using the results lawfully, including GDPR and anti-spam rules where they apply. This is an unofficial tool, not affiliated with Telegram.

#### 🧰 More from K-Data Lab

**Apps and ads**

- [Google Play Scraper API](https://apify.com/k-data-lab/google-play-scraper): app details and reviews, any country
- [Google Ads Transparency & Ad Library Scraper](https://apify.com/k-data-lab/google-ad-library-scraper): every Google ad a competitor runs

**Amazon**

- [Amazon Seller Central Review Scraper](https://apify.com/k-data-lab/amazon-seller-central-review-scraper): brand reviews and monitoring
- [Amazon ASIN Rating & Review Count Lookup](https://apify.com/k-data-lab/amazon-asin-rating-scraper): ratings, review counts and BSR, no login

**Travel**

- [Agoda Scraper API](https://apify.com/k-data-lab/agoda-scraper): hotel prices, rooms and reviews
- [Airline Award Seat Scraper](https://apify.com/k-data-lab/airline-award-seat-scraper): live miles, taxes and seats left

**Korean data**

- [Korean Music Chart API](https://apify.com/k-data-lab/korean-music-chart-scraper): Melon, Genie, Bugs, FLO and VIBE in one chart
- Korea apartment prices: [KB Land](https://apify.com/k-data-lab/kbland-scraper), [R114](https://apify.com/k-data-lab/r114-scraper)

#### 💬 Feedback

Need a field that's missing, or found a channel that doesn't work? Open an issue on the **Issues** tab. We answer the same day.

Tags: telegram scraper, telegram api, telegram channel scraper, telegram keyword search, telegram hashtag search, telegram messages, telegram monitor, telegram channel finder, telegram contacts, telegram emails, telegram leads, telegram subscribers, t.me scraper, telegram posts, telegram brand monitoring, telegram social listening, crypto signals monitoring, OSINT, no login

# Changelog

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

# Actor input Schema

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

Words, phrases or hashtags to look for in public Telegram messages, e.g. <code>bitcoin</code>, <code>your brand</code> or <code>#ETF</code>. Leave empty to export channel history. With channels below, we search those. Without channels, we first find relevant public channels.

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

Public Telegram channels to export or search: <code>durov</code>, <code>@durov</code> or <code>https://t.me/durov</code>. A post link (<code>https://t.me/durov/300</code>) returns that one post.

## `discoverChannels` (type: `boolean`):

Uses web search to find other public channels about each keyword, then searches inside them. Turn off to search only your channels.

## `resultType` (type: `string`):

Messages returns one row per post. Channels only returns one row per channel with its bio, subscribers, last post date and published contacts: use it to look up channels or build a channel or lead list for a topic.

## `maxResults` (type: `integer`):

The run stops at this many rows. For a cheap first test use 10. 0 means no limit. Your Apify spending limit always applies too.

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

Per channel, and per keyword when you use keywords.

## `maxChannelsPerKeyword` (type: `integer`):

How many public channels to find for each keyword.

## `since` (type: `string`):

Only messages on or after this date. Use <code>2026-01-31</code> or a relative age: <code>24 hours</code>, <code>7 days</code>, <code>2 weeks</code>, <code>1 month</code>.

## `until` (type: `string`):

Only messages on or before this date, same formats.

## `onlyNewMessages` (type: `boolean`):

For scheduled runs. We remember the newest message per channel and keyword, so each run returns and charges only what's new. The first run returns everything within your limits.

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

Keep separate memory for different schedules, e.g. <code>crypto-watch</code>.

## `minViews` (type: `integer`):

Skip messages with fewer views. Skipped messages aren't charged.

## `minSubscribers` (type: `integer`):

Channels only mode: skip smaller channels.

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

Skip messages containing any of these, e.g. <code>giveaway</code>. Not case-sensitive.

## `exactMatch` (type: `boolean`):

Telegram's search also matches word forms (update → updates). Turn on to keep only messages with your exact text.

## `onlyWithMedia` (type: `boolean`):

Skip text-only messages.

## `onlyWithContacts` (type: `boolean`):

For lead lists. Keeps only channels whose bio, or messages whose text, has an email or an @handle other than the channel's own. Skipped rows aren't charged.

## `country` (type: `string`):

Two-letter country code, e.g. <code>kr</code>, <code>de</code>, <code>br</code>. Only affects which channels are found.

## `language` (type: `string`):

Two-letter language code, e.g. <code>ko</code>, <code>de</code>, <code>pt</code>. Only affects which channels are found.

## Actor input object example

```json
{
  "keywords": [
    "bitcoin etf",
    "#ETF"
  ],
  "channels": [
    "durov",
    "https://t.me/telegram"
  ],
  "discoverChannels": true,
  "resultType": "messages",
  "maxResults": 50,
  "maxMessagesPerChannel": 10,
  "maxChannelsPerKeyword": 5,
  "onlyNewMessages": false,
  "monitorName": "default",
  "exactMatch": false,
  "onlyWithMedia": false,
  "onlyWithContacts": false,
  "country": "us",
  "language": "en"
}
```

# Actor output Schema

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

No description

## `channels` (type: `string`):

No description

## `contacts` (type: `string`):

No description

## `all` (type: `string`):

No description

## `summary` (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 = {
    "keywords": [
        "bitcoin"
    ],
    "channels": [
        "cointelegraph"
    ],
    "maxResults": 50,
    "maxMessagesPerChannel": 10,
    "maxChannelsPerKeyword": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("k-data-lab/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 = {
    "keywords": ["bitcoin"],
    "channels": ["cointelegraph"],
    "maxResults": 50,
    "maxMessagesPerChannel": 10,
    "maxChannelsPerKeyword": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("k-data-lab/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 '{
  "keywords": [
    "bitcoin"
  ],
  "channels": [
    "cointelegraph"
  ],
  "maxResults": 50,
  "maxMessagesPerChannel": 10,
  "maxChannelsPerKeyword": 5
}' |
apify call k-data-lab/telegram-channel-scraper --silent --output-dataset

```

## MCP server setup

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