# Telegram Keyword Search Scraper, No Login or API Key (`george.the.developer/telegram-keyword-search`) Actor

Telegram keyword search scraper for public channels. Give it keywords and get every matching post with channel, text, date, views and link. No Telegram account, no login, no API key. Finds channels through Google or searches the channels you name. You pay only for posts that contain your keyword.

- **URL**: https://apify.com/george.the.developer/telegram-keyword-search.md
- **Developed by:** [George Kioko](https://apify.com/george.the.developer) (community)
- **Categories:** Social media, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 message founds

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 Keyword Search Scraper

Telegram Keyword Search Scraper is an Apify Actor that finds keyword matches in public Telegram channel posts and returns structured message rows without a Telegram account.

**No login. No cookies. No Telegram API key.** Researchers and lead analysts can use **Telegram keyword search** and **public Telegram post scraping** to collect post text, dates, views and original message links.

Only delivered posts with a numeric message ID and text containing the keyword qualify for the message event. Duplicates within a keyword, nonmatching posts and empty results have no message event charge.

### Pricing

You pay per matching post. Posts that do not contain your keyword are never returned or charged.

| Event | Price | You pay when |
| --- | --- | --- |
| `apify-actor-start` | $0.00005 | The platform records its synthetic start event |
| `message-found` | $0.004 per post | A matching post with a numeric message ID is delivered |

**The price is $4 per 1,000 matching posts.** A run delivering 100 matching posts has $0.40 in message charges plus the platform start event. Local and free runs deliver rows with `charged` set to false. A post matching two different keywords can appear and qualify once for each keyword.

### Search public posts without login

Provide channel handles to search them directly. Set `discoverChannels` to false to skip Google entirely. With discovery enabled, supplied channels are searched first and Google can add other channels within your limits.

```json
{
  "keywords": ["privacy"],
  "channels": ["telegram", "durov"],
  "discoverChannels": false,
  "maxResultsPerKeyword": 20
}
```

### How it works

1. Normalize supplied handles and search each public channel at `https://t.me/s/<channel>?q=<keyword>`.
2. When enabled, discover additional channels with Google through the Apify `GOOGLE_SERP` proxy group. Unusable results are retried with fresh sessions up to four times per keyword.
3. Read older matching posts with the `before` cursor, retaining the keyword and applying `dateFrom` when supplied.
4. Deduplicate posts within each keyword and write only posts whose text contains that keyword, case insensitive.
5. Stop new fetches one minute before the run timeout and flush collected rows. Stop cleanly at the charge limit.

Telegram fetching uses at most three concurrent requests, a 20 second request timeout and one retry for network or server failures. Missing or private channels are skipped. Google failure is logged and never makes discovery fatal.

### What data does it extract?

Each row contains the keyword, channel handle and name, subscriber count as displayed, numeric message ID, message URL, readable text, publication datetime, displayed and parsed views, forwarded source name, text links and media type labels.

`discoveredVia` identifies input or Google discovery. `scrapedAt` records collection time and `charged` distinguishes paid delivery from free delivery. Missing metadata is null. Subscriber counts and views are public display values rather than audited measurements.

### What is NOT returned

- Private groups or private channel posts.
- Member lists, subscriber identities or user contact details.
- Anything Google has not indexed during channel discovery. Supplied public channels can still be searched directly.
- A complete search of every Telegram channel or a guarantee that every matching post is available.
- Media files, downloaded attachments or text extracted from images and videos.
- Posts without a numeric message ID or without the keyword in their text.

### Start a run

1. Enter one or more keywords.
2. Supply public channels or leave channels empty to use Google discovery.
3. Select channel and result limits, then run the Actor.
4. Export the default dataset as JSON, CSV or Excel.

The prefilled input uses `privacy`, `telegram`, `durov` and 20 results per keyword. Discovery remains enabled by default, and supplied channels are searched before discovery. Google proxy access is required only for discovery.

### Input

```json
{
  "keywords": ["privacy"],
  "channels": ["@telegram", "https://t.me/durov"],
  "discoverChannels": true,
  "maxChannelsPerKeyword": 10,
  "maxResultsPerKeyword": 20,
  "dateFrom": "2022-01-01"
}
```

| Field | Type | Default | Meaning |
| --- | --- | --- | --- |
| `keywords` | string array | Required, prefill `privacy` | 1 to 20 literal phrases matched against post text |
| `channels` | string array | Empty, prefill `telegram` and `durov` | Handles, @handles or t.me URLs |
| `discoverChannels` | boolean | true | Add Google discovery, including when channels are supplied |
| `maxChannelsPerKeyword` | integer | 10 | Total distinct channels per keyword, maximum 50 |
| `maxResultsPerKeyword` | integer | 50, prefill 20 | Delivered posts per keyword, maximum 1,000 |
| `dateFrom` | ISO date string | None | Inclusive earliest publication date or datetime |

Repeated handles and repeated keywords are normalized and deduplicated. `maxChannelsPerKeyword` includes supplied channels, which take priority. Limits are upper bounds, and fewer posts may be available.

### Output

The post content below comes from the supplied public Telegram fixture. Collection fields illustrate an offline free run, rather than a verified live Actor run.

```json
{
  "keyword": "privacy",
  "channel": "telegram",
  "channelName": "Telegram News",
  "subscriberCount": "9.4M",
  "messageId": 207,
  "messageUrl": "https://t.me/telegram/207",
  "text": "Messages in all new chats can be set to self-destruct with a global auto-delete timer in Settings > Privacy and Security > Auto-Delete Messages.\n\nNovember Features\n1 • 2 • 3 • 4 • More",
  "datetime": "2022-12-09T08:15:54+00:00",
  "viewCount": "6M",
  "viewCountParsed": 6000000,
  "forwardedFrom": null,
  "links": [
    "https://t.me/telegram/208",
    "https://t.me/telegram/209",
    "https://t.me/telegram/210",
    "https://t.me/telegram/211"
  ],
  "mediaTypes": ["video"],
  "discoveredVia": "input",
  "scrapedAt": "2026-10-04T00:00:00.000Z",
  "charged": false
}
```

### Use from Claude, ChatGPT and any MCP agent

Add this Actor through the Apify MCP server and ask your agent to find public Telegram posts mentioning your keyword.

```text
https://mcp.apify.com/?tools=george.the.developer/telegram-keyword-search
```

From Node.js with the Apify client and an Apify token.

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('george.the.developer/telegram-keyword-search').call({
  keywords: ['privacy'],
  channels: ['telegram', 'durov'],
  discoverChannels: false,
  maxResultsPerKeyword: 20,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

With curl, wait for the run and return dataset rows.

```bash
curl -X POST "https://api.apify.com/v2/acts/george.the.developer~telegram-keyword-search/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"keywords":["privacy"],"channels":["telegram","durov"],"discoverChannels":false,"maxResultsPerKeyword":20}'
```

Apify authentication runs the Actor. No Telegram authentication is needed. These integration examples become available after the owner publishes the Actor.

### Integrations

**Clay.** Use `https://api.apify.com/v2/datasets/DATASET_ID/items?format=json` as an HTTP enrichment source and map `keyword`, `channel`, `text`, `datetime` and `messageUrl` to columns.

**n8n and Make.** Select the Actor in the Apify node or module, supply the input JSON and read its default dataset in the next step.

**Google Sheets.** Export dataset rows as CSV or use the Apify Google Sheets integration.

### Use cases

- **Researchers** search known public channels for policy or technology phrases and retain original post links.
- **Lead analysts** discover indexed public channels mentioning a product category and review matching text.
- **Brand teams** schedule searches of selected channels and track mention dates and public view counts.
- **AI agents** call the MCP tool to collect evidence with original Telegram message URLs.

### FAQ

#### Does this search all Telegram posts?

No. It searches public previews of supplied channels and channels found through Google. Discovery depends on indexing and the Google response layout.

#### Do I need a Telegram account or API key?

No. Telegram pages are public HTTPS requests. Google discovery uses your Apify proxy access, and invoking the Actor through the API requires an Apify token.

#### What happens when Google fails?

The Actor continues with input channels. Discovery failure is logged and returns no additional channels. With no input channels, an unsuccessful discovery can produce an empty dataset.

#### Are duplicates charged twice?

No within a keyword. The same post can appear once for each different keyword it matches, and each delivered keyword match qualifies for its own message event.

#### Can I search only my channels?

Yes. Supply `channels` and set `discoverChannels` to false. No Google request is needed.

#### What happens when no posts match?

The dataset stays empty. There are no message event charges and no diagnostic filler rows. The platform start event remains separate.

#### Are images and videos searched?

No. The keyword must occur in post text. Media type labels are included when the public preview exposes them, but media files are not downloaded or transcribed.

# Actor input Schema

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

Literal keyword phrases matched against post text, case insensitive.

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

Public channel handles, @handles or t.me URLs. Input channels are searched before optional discovery.

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

Also discover channels with Google, including when input channels are supplied. Disable to search only your channels.

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

Maximum distinct channels searched for each keyword, including input channels.

## `maxResultsPerKeyword` (type: `integer`):

Maximum matching posts delivered for each keyword.

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

Optional ISO date or datetime. Only posts at or after this date are returned.

## Actor input object example

```json
{
  "keywords": [
    "privacy"
  ],
  "channels": [
    "telegram",
    "durov"
  ],
  "discoverChannels": true,
  "maxChannelsPerKeyword": 10,
  "maxResultsPerKeyword": 20
}
```

# Actor output Schema

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

One row per keyword and matching public post with message identity, text, metadata and billing flag.

# 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": [
        "privacy"
    ],
    "channels": [
        "telegram",
        "durov"
    ],
    "maxResultsPerKeyword": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("george.the.developer/telegram-keyword-search").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": ["privacy"],
    "channels": [
        "telegram",
        "durov",
    ],
    "maxResultsPerKeyword": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("george.the.developer/telegram-keyword-search").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": [
    "privacy"
  ],
  "channels": [
    "telegram",
    "durov"
  ],
  "maxResultsPerKeyword": 20
}' |
apify call george.the.developer/telegram-keyword-search --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,george.the.developer/telegram-keyword-search"
        }
    }
}
```

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/O0m1ucxyjTGPhfZx0/builds/pdEuCWjeFG7t7s9Mw/openapi.json
