# Telegram Keyword Search Scraper - Messages by Keyword (`parseforge/telegram-keyword-search-scraper`) Actor

Search public Telegram channels by keyword. Get every matching message with views, reactions, media and channel stats. Export CSV, Excel, JSON or XML.

- **URL**: https://apify.com/parseforge/telegram-keyword-search-scraper.md
- **Developed by:** [ParseForge](https://apify.com/parseforge) (community)
- **Categories:** Social media, Lead generation, News
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.75 / 1,000 telegram messages

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

![ParseForge Banner](https://raw.githubusercontent.com/ParseForge/apify-assets/main/banner-v4.webp)

## 🔎 Telegram Keyword Search Scraper

> 🚀 **Search public Telegram channels by keyword and export every matching message in seconds.** In our test, two keywords returned 1,000 matching messages from 22 channels in 97 seconds, each with views, reactions, media and channel stats. No Telegram account, no API key, no phone number.

This Actor works in two steps. First it discovers public Telegram channels that talk about your keyword, using a web search restricted to t.me (about 20 relevant channels per keyword). Then it runs Telegram's own search inside every one of those channels, plus any channels you add yourself, and returns the messages Telegram says match. Every row is a real message that matches your keyword, with the matched word highlighted in `matchedTerms`, not just the newest post of a page that happened to mention it.

Every row has 36 fields: the message (text, date, views, total reactions and the per-emoji breakdown, type, author signature, edited flag, forward source, reply link, link preview, links, hashtags, photo, video and document lists), the channel (title, username, numeric ID, subscribers, verified badge, bio, avatar) and how it was found (keyword, discovery or your list, Telegram search or history scan). Telegram's search returns the newest 22 matches per channel and keyword; switch on **Deep search** to also scan each channel's history and reach older matches.

| 🎯 Target Audience | 💡 Primary Use Cases |
|---|---|
| Brand and reputation teams | Find every Telegram post that mentions your brand, product or executives |
| Crypto and fintech analysts | Track tickers, projects and airdrops across the channels that move the market |
| OSINT and threat intelligence | Monitor keywords, leaks and campaigns across public channels |
| Journalists and researchers | Trace how a story or claim spreads between Telegram channels |
| Recruiters and job boards | Collect job posts for a role or skill from remote-work channels |
| Marketing and growth teams | Discover the channels where your topic lives and measure their reach |

### 📋 What the Telegram Keyword Search Scraper does

1. Takes one or more keywords, phrases (`"spot etf"` in quotes for the exact phrase) or hashtags (`#airdrop`).
2. Discovers public channels that talk about each keyword, through a web search restricted to t.me, in the language and country you choose, optionally limited to recently active pages.
3. Adds the channels you list yourself (`cointelegraph`, `@durov` or `https://t.me/s/telegram`), or searches only those when discovery is off.
4. Runs Telegram's own search inside every channel and keeps the messages it returns, newest first, with the matched words.
5. With **Deep search**, also reads each channel's history and matches your keyword on older messages, up to the scan depth you set.
6. Applies your filters (date window, minimum views, media only, exact words only) and writes one row per message, deduplicated across keywords and channels.
7. Skips bots, private chats and names that do not exist, and says so in the log.

> 💡 **Why it matters:** Telegram has no public global search, and most "keyword" scrapers only return whatever post happens to sit on a page Google indexed. This Actor asks Telegram itself which messages match, channel by channel, so the export is the conversation about your keyword and nothing else.

### 🎬 Full Demo (🚧 Coming soon)

### 📊 Output

Each dataset row is one public Telegram message. 36 columns per row.

| Field | Type | Description |
|---|---|---|
| 🖼 `imageUrl` | string | First photo or video thumbnail of the message, or the channel avatar |
| 📢 `channelTitle` | string | Channel display name |
| 🔗 `url` | string | Direct link to the message |
| 🆔 `messageId` | integer | Message number inside the channel |
| 👤 `channel` | string | Channel username |
| 🔢 `channelId` | string | Telegram's numeric channel ID |
| 🔎 `keyword` | string | Keyword that found the message (`N/A` for plain channel exports) |
| 💬 `text` | string | Full message text, emoji included |
| 📅 `date` | string | Publication date and time, ISO 8601 UTC |
| 👁 `views` | integer | View count |
| ❤️ `totalReactions` | integer | Sum of all reactions |
| 🧩 `messageType` | string | `text`, `photo`, `video`, `document`, `voice`, `poll`, `link`, or a combination such as `photo+video` |
| 📎 `hasMedia` | string | `Yes` when the message carries a photo, video, document or voice note |
| ✍️ `author` | string | Author signature, when the channel signs its posts |
| ✏️ `edited` | string | `Yes` when the message was edited |
| ↪️ `forwardedFrom` | string | Source channel or user of a forwarded message |
| 🔗 `forwardedFromUrl` | string | Link to the original message |
| 💭 `replyToUrl` | string | Link to the message this one replies to |
| 🌐 `linkPreviewUrl` | string | URL of the link preview card |
| 📰 `linkPreviewTitle` | string | Title of the link preview card |
| 🔗 `channelUrl` | string | Channel link |
| 👥 `channelSubscribers` | integer | Channel subscribers |
| ✅ `channelVerified` | string | `Yes` when Telegram shows the verified badge |
| 📝 `channelDescription` | string | Channel bio |
| 🖼 `channelAvatarUrl` | string | Channel avatar |
| 🛰 `discoveredVia` | string | `Channel discovery` or `Your channel list` |
| 🎯 `matchSource` | string | `Telegram search`, `History scan` (deep search) or `Channel history` (no keyword) |
| 🔦 `matchedTerms` | array | Words Telegram highlighted as the match |
| 😍 `reactions` | array | Each reaction emoji with its count |
| #️⃣ `hashtags` | array | Hashtags in the text |
| 🔗 `links` | array | Links in the text |
| 📷 `photoUrls` | array | Photo URLs |
| 🎬 `videoUrls` | array | Video file URLs |
| 📄 `documents` | array | Attached file names with size |
| 🕒 `scrapedAt` | string | When the row was collected |
| ❌ `error` | string | Error message, `null` on a normal row |

Empty text values read `N/A` and empty lists are `[]`, so no column is ever `null` except `error`.

#### Real sample records

```json
{
  "imageUrl": "https://cdn1.telesco.pe/file/F9FPaAldijI4S7i5Fp9MA6HV_XKBCq3fyEVJaYNqfy8qmtTzC505eLMdulFRtWJsXJ3fVUGzlbg3FlUjIVhpIU_qLY3YTWxf-vr2P03PuAmj5L1yAHlTV6qwo-0aF9iyC-L9Q0bJg7pqMsjeJpRH7qR901AKXuZhe_ollTM6l68PUwqq2NRa-J02ABLuiLRbvYw171fUPmmW7ZOxKPfO_iAuvfNGoF3BnbQbckDEPz_nElhGz-QJNt4pPWKH1uPqix_pmFVEKeRocliZgrOrFO4h8pc3gCes5GCdJTAD6HwIpooiII2FrcTVzp4wMsktg4KaqfaTtsxa0jPU0AyuHw.jpg",
  "channelTitle": "Bitcoin",
  "url": "https://t.me/bitcoin/20413",
  "messageId": 20413,
  "channel": "bitcoin",
  "channelId": "1193342710",
  "keyword": "bitcoin",
  "text": "JUST IN: 🟠 $172 billion WisdomTree says Bitcoin \"is working exactly as intended\" 👀\n\n\"Bitcoin was built for economic uncertainty...it has traded through a war, an oil shock and a rate rise, and rallied 46% since July.\" 🚀\n\nSource: https://x.com/BitcoinMagazine/status/2103542531892080716",
  "date": "2026-09-25T19:19:59+00:00",
  "views": 1270,
  "totalReactions": 18,
  "messageType": "photo",
  "hasMedia": "Yes",
  "author": "N/A",
  "edited": "No",
  "forwardedFrom": "N/A",
  "forwardedFromUrl": "N/A",
  "replyToUrl": "N/A",
  "linkPreviewUrl": "N/A",
  "linkPreviewTitle": "N/A",
  "channelUrl": "https://t.me/bitcoin",
  "channelSubscribers": 185000,
  "channelVerified": "No",
  "channelDescription": "This is the top Telegram channel for #Bitcoin news and information. Inject the orange coin directly into your mind! 🍊",
  "channelAvatarUrl": "https://cdn5.telesco.pe/file/KpRmCAmF2Vw7RHbkqY9KfPQDYk_9oQagc-FEb8fiejw6hiTl0I9iiJVxx5pHujtridbFawvatOHLVuk0ZooqQJeYRZrB7ZDHlebk3-2PFRJpwHzTPRvNz0mPwNXV-dWiJw4jSE8RmmGr1k4ZcfTSJWP3rBxVQLx5X9jiKjDr3-kqfbYfXac2DX9Ve1SR8D3RvdJBkDC8SaY8KF6IUiG9h-yFzQ5yo_HaNqUOhouhpXfjzpMzJOXPWdaI3GDkhLIo9SpBNdmUBm25beQvjB_N3uBGP4UWuHZJw-H6rhgd93ivftFHaDXBc4J7CcsgI8pMT_JkwYRgRJ5IxbwTrepuNg.jpg",
  "discoveredVia": "Channel discovery",
  "matchSource": "Telegram search",
  "matchedTerms": [
    "Bitcoin"
  ],
  "reactions": [
    {
      "emoji": "❤",
      "count": 12
    },
    {
      "emoji": "⚡",
      "count": 4
    },
    {
      "emoji": "👍",
      "count": 2
    }
  ],
  "hashtags": [],
  "links": [
    "https://x.com/BitcoinMagazine/status/2103542531892080716"
  ],
  "photoUrls": [
    "https://cdn1.telesco.pe/file/F9FPaAldijI4S7i5Fp9MA6HV_XKBCq3fyEVJaYNqfy8qmtTzC505eLMdulFRtWJsXJ3fVUGzlbg3FlUjIVhpIU_qLY3YTWxf-vr2P03PuAmj5L1yAHlTV6qwo-0aF9iyC-L9Q0bJg7pqMsjeJpRH7qR901AKXuZhe_ollTM6l68PUwqq2NRa-J02ABLuiLRbvYw171fUPmmW7ZOxKPfO_iAuvfNGoF3BnbQbckDEPz_nElhGz-QJNt4pPWKH1uPqix_pmFVEKeRocliZgrOrFO4h8pc3gCes5GCdJTAD6HwIpooiII2FrcTVzp4wMsktg4KaqfaTtsxa0jPU0AyuHw.jpg"
  ],
  "videoUrls": [],
  "documents": [],
  "scrapedAt": "2026-09-25T20:40:04.957Z",
  "error": null
}
```

```json
{
  "imageUrl": "https://cdn4.telesco.pe/file/ghLsCiBwEglq67UuTAZ3UBDDSByaYTpaal4nnGujRSb_5P65COVV6fNiBQrDfOHh28MKcxeiRdxUo_U_OdgTq325TSEx2EjknJFsoPmBzSpkCbBcR_A6ZQ3A4-FC0JUL81NFx_Xy52wVKN0m-4u7BvfwkYxHgS4GFWLngOEhzsTlThnqQLCP2NFVI3smnKQz8-urbV5HNVy8_5W9vZDb1TyVnkCJHQlnqEYyTkTy0vCUaenY39fQ58CuAwZm7HVs3g4EgsK0hT46pKqVagBg0X0bwHOA8JHpYdgoBHWquWM_18XHR4ELzGYXnZK3ZX8l9eWZ2XrkszUcBdHz3AKssw.jpg",
  "channelTitle": "CNBCTV18.com",
  "url": "https://t.me/cnbc_tv18/48193",
  "messageId": 48193,
  "channel": "cnbc_tv18",
  "channelId": "1239146675",
  "keyword": "bitcoin",
  "text": "Bitcoin near $86,000 as crypto rally gains momentum: What investors should know\n\nhttps://www.cnbctv18.com/market/cryptocurrency/bitcoin-holds-near-sollar-86000-institutional-demand-supports-crypto-rally-19996357.htm",
  "date": "2026-09-23T06:31:56+00:00",
  "views": 1690,
  "totalReactions": 1,
  "messageType": "link",
  "hasMedia": "No",
  "author": "N/A",
  "edited": "No",
  "forwardedFrom": "N/A",
  "forwardedFromUrl": "N/A",
  "replyToUrl": "N/A",
  "linkPreviewUrl": "https://cnbctv18.com/market/cryptocurrency/bitcoin-holds-near-sollar-86000-institutional-demand-supports-crypto-rally-19996357.htm",
  "linkPreviewTitle": "Bitcoin near $86,000 as crypto rally gains momentum: What investors should know - CNBC TV18",
  "channelUrl": "https://t.me/cnbc_tv18",
  "channelSubscribers": 77500,
  "channelVerified": "Yes",
  "channelDescription": "The official Telegram channel for CNBCTV18.com\nYouTube: https://www.youtube.com/user/CNBCTV18\nFacebook: https://www.facebook.com/cnbctv18india\nTwitter: https://twitter.com/CNBCTV18News",
  "channelAvatarUrl": "https://cdn5.telesco.pe/file/IOgc8Tm4uKh2Z2fpEVaZFZQuTfwBL48MfiBvkoWWLXBx8Ax8hDvfefrCvf0njn7eJDo6K_89VKRUmZVlobNMX5lqOoAUUmAleUclmJEUcV2b7pBw-7sbvc9Yv03chmd6tPIPaAVUpn8ZnZ5lIByG8AOX7Lpn54lwEczwl2kJc6GwknkaaOjjce2Whowjqx1FHwnGkJfRC4iyxKFSuQIapkzoqpDmgAvruKAcEEp3liRGpaiEXh0zTL4Xr1g_dSSm2FyCjkLfz0kEK0N5xNErDNeWwNpn3i5QBONDQocoimUuaD9kSgBriaZKWQU5tPoBmfWVqzt2YuHnCFwQCpVFjQ.jpg",
  "discoveredVia": "Channel discovery",
  "matchSource": "Telegram search",
  "matchedTerms": [
    "Bitcoin"
  ],
  "reactions": [
    {
      "emoji": "❤",
      "count": 1
    }
  ],
  "hashtags": [],
  "links": [
    "https://www.cnbctv18.com/market/cryptocurrency/bitcoin-holds-near-sollar-86000-institutional-demand-supports-crypto-rally-19996357.htm"
  ],
  "photoUrls": [],
  "videoUrls": [],
  "documents": [],
  "scrapedAt": "2026-09-25T20:40:05.337Z",
  "error": null
}
```

```json
{
  "imageUrl": "https://cdn4.telesco.pe/file/B9_Eqv2-8xFXWYuOgleaTDrldrd4aXiKjwaCR4Clof5Obl4QratFcFlXAf50VExEvkB7YIR8gi3gyla6E4clrLdmIzTtx--pnGjscPw3Og893x0SEUOREwvTYZo4xnp2Pld_Y8sNzE65aJMOhI30ysIjpUGU1jKSQJT--bq-K7fJgBBtNzVrqyE2AgpsqJ4Vm2tlNKjKoPsqujKt9jcZeOiKqqcpgZtC5NoPOtzWhAiACiZd5OFO-MJasC9xHw9D6ZSSpV65Ou3LKAGSN5a7W5oJGd6Q_y-m34Qx1hWiWBqiYCp6PfRfE1RN-E5P--2aRzSoFI5c7rBE9gAMg0kbdQ.jpg",
  "channelTitle": "Glassnode",
  "url": "https://t.me/glassnode/1982",
  "messageId": 1982,
  "channel": "glassnode",
  "channelId": "1370726192",
  "keyword": "bitcoin",
  "text": "Only 9 of the top 50 altcoins have beaten $BTC since its all-time high.\n\nZEC leads by a wide margin, up 14x against Bitcoin.\n\nHYPE, XMR and NEAR follow at 2–3x.",
  "date": "2026-09-24T08:00:50+00:00",
  "views": 2980,
  "totalReactions": 18,
  "messageType": "photo",
  "hasMedia": "Yes",
  "author": "N/A",
  "edited": "No",
  "forwardedFrom": "N/A",
  "forwardedFromUrl": "N/A",
  "replyToUrl": "N/A",
  "linkPreviewUrl": "N/A",
  "linkPreviewTitle": "N/A",
  "channelUrl": "https://t.me/glassnode",
  "channelSubscribers": 44200,
  "channelVerified": "No",
  "channelDescription": "Institutional Data and Market Intelligence for Digital Assets.\n\nhttps://studio.glassnode.com/",
  "channelAvatarUrl": "https://cdn4.telesco.pe/file/sI7A6aDSO37y6FgIEHiRT7BLkpTm3FhMXGK9cVxNjSM7DgvqbImeyOKvkAOw0ArCFFbcBf4tQgo3Is-7paVR2RTLpXXA5fMdDJTNjoC6dZS6ny9_ulPFEgfJAjV5MhJgGzIA3i_h3OE7IAeyV15U6PJk_39zkzzpGz4VJ_HZyv75v5fCEkiS2BOkCBO2ObSHr6q1gHsQq2LJ84NdqDnt4t3mfEaG6yBT3GLDcvSz13B74LsjEX1n66RgjK8lkgQUguLuxocYrOtIOrtmeiiDq1xdf3DT6BeUBs4XUCTkbJZsg2PBLzs9bawxeXmXW9_5P0cjnsBJLunY5khm9db8OA.jpg",
  "discoveredVia": "Channel discovery",
  "matchSource": "Telegram search",
  "matchedTerms": [
    "Bitcoin"
  ],
  "reactions": [
    {
      "emoji": "❤",
      "count": 14
    },
    {
      "emoji": "✍",
      "count": 3
    },
    {
      "emoji": "👎",
      "count": 1
    }
  ],
  "hashtags": [],
  "links": [],
  "photoUrls": [
    "https://cdn4.telesco.pe/file/B9_Eqv2-8xFXWYuOgleaTDrldrd4aXiKjwaCR4Clof5Obl4QratFcFlXAf50VExEvkB7YIR8gi3gyla6E4clrLdmIzTtx--pnGjscPw3Og893x0SEUOREwvTYZo4xnp2Pld_Y8sNzE65aJMOhI30ysIjpUGU1jKSQJT--bq-K7fJgBBtNzVrqyE2AgpsqJ4Vm2tlNKjKoPsqujKt9jcZeOiKqqcpgZtC5NoPOtzWhAiACiZd5OFO-MJasC9xHw9D6ZSSpV65Ou3LKAGSN5a7W5oJGd6Q_y-m34Qx1hWiWBqiYCp6PfRfE1RN-E5P--2aRzSoFI5c7rBE9gAMg0kbdQ.jpg"
  ],
  "videoUrls": [],
  "documents": [],
  "scrapedAt": "2026-09-25T20:40:05.080Z",
  "error": null
}
```

### ✨ Why choose this Actor

- **Real keyword matches.** Every row comes from Telegram's own search inside the channel, with the matched words in `matchedTerms`. No "newest post on a page that once mentioned your keyword".
- **Discovery and your own list together.** About 20 relevant channels found per keyword (for `remote jobs`: remotejobss, workewco, legitremotejobs, remotedevjobs and more), plus any channels you already follow.
- **Deep search for older messages.** Telegram's search stops at the newest 22 matches per channel. Deep search keeps reading the channel's history and matches your keyword on every older message, as far back as you set.
- **Exact phrases and exact words.** Put a keyword in quotes for the exact phrase. Switch on **Exact words only** when you do not want Telegram's word-form matching (staking also finds stake and unstaked).
- **Channel context on every row.** Subscribers, verified badge, bio, avatar and Telegram's numeric channel ID next to each message, ready for reach and influence scoring.
- **Engagement you can sort by.** Views, total reactions and the per-emoji breakdown, with a minimum-views filter to keep only posts that travelled.
- **Media and links extracted.** Photo and video URLs, document names with sizes, link preview cards, links and hashtags in their own columns.
- **One Actor, no child runs.** Discovery and search happen inside the same run; nothing else is started on your account.
- **Fast and light.** Plain HTTP, no browser: 1,000 messages in about a minute and a half in our test.

### 📈 How it compares to alternatives

| | This Actor | Google-hit keyword scrapers | Searching by hand in the Telegram app |
|---|---|---|---|
| Requires a Telegram account or API key | No | No | Yes |
| Every returned message matches the keyword | Yes, Telegram's own search | No, newest post of each indexed page | Yes |
| Channels searched per keyword | About 20 discovered + your list | One page per search result | One channel at a time |
| Messages per channel and keyword | 22 newest, more with deep search | 1 | Scroll |
| Exact phrase and exact-word modes | Yes | No | Partly |
| Channel subscribers, verified badge, bio on every row | Yes | Partly | Look them up |
| Per-emoji reactions, media, links, hashtags | Yes | Partly | Copy by hand |
| Extra child runs billed to you | None | A separate search Actor run | None |

The Actor sees what any visitor to a channel's public web preview at t.me/s sees. Private channels, private groups, and chats without a public preview (bots and personal accounts) are not reachable. Telegram's search returns at most the 22 newest matches per channel and keyword; deep search goes further back by reading history, which takes one page load per 20 messages. Channel discovery relies on the channels a web search engine has indexed, so very small or brand-new channels may not be found; add them to **Channels to search** instead.

### 🚀 How to use

1. Create a free Apify account. New accounts include $5 of free platform credit, which is plenty to try this out: [console.apify.com/sign-up](https://console.apify.com/sign-up?fpr=vmoqkp)
2. Open the Actor and go to the Input tab.
3. Type your **Keywords**, one per line. Use quotes for an exact phrase and `#` for a hashtag.
4. Set **Max Items** to the total number of messages you want.
5. Leave **Discover channels automatically** on, add channels you already know, or switch discovery off to search only your list.
6. Pick **Deep search** if you need matches older than the newest 22 per channel, and add a date window, minimum views or other filters.
7. Click **Start**, then open the **Dataset** tab and download as CSV, Excel, JSON or XML, or pull it from the API.

```json
{
  "keywords": ["\"spot etf\"", "halving"],
  "channels": ["cointelegraph", "@glassnode"],
  "maxItems": 500,
  "searchDepth": "deep",
  "afterDate": "6 months"
}
```

### 💼 Business use cases

#### Brand and product monitoring

Search your brand, product names and executives every day. `channelSubscribers` and `views` show which mentions reached an audience, and `forwardedFrom` shows where a post started before it spread.

#### Crypto market intelligence

Follow tickers, token names and airdrop campaigns across the channels that trade on them. Views and reactions per message give an early read on hype, and `date` lets you line mentions up with price moves.

#### Threat intelligence and OSINT

Watch keywords such as your domain, product names, leak terms or campaign hashtags across public channels. Deep search with a date window gives a full timeline, and `channelId` stays stable even when a channel renames itself.

#### Recruiting and job aggregation

Search a role or skill ("react developer", "remote jobs") and collect job posts from the channels that publish them, with links, hashtags and posting dates ready for a job board or a sourcing sheet.

### 🔌 Automating Telegram Keyword Search Scraper

- **Make** and **Zapier**: run the Actor on a schedule and send new matching messages to a sheet, CRM or help desk.
- **Slack**: post every new mention of your brand with more than 1,000 views to a channel, using the minimum-views filter.
- **Airbyte**: sync datasets into Snowflake, BigQuery or Postgres to keep a history of mentions and channel reach.
- **GitHub**: schedule runs from Actions and keep versioned snapshots of the conversation about a topic.
- **Google Drive**: drop a CSV or Google Sheet into a shared folder after every run.
- **API and webhooks**: every run emits a dataset ID; subscribe to the run succeeded webhook and process the messages wherever you need them.

### 🌟 Beyond business use cases

- **Research**: study how news, rumours and narratives move through Telegram, by language and by channel size.
- **Personal**: follow a hobby, a local topic or a project across every public channel that talks about it, without joining them.
- **Non-profit**: document public calls, claims and campaigns on Telegram with direct links and timestamps.
- **Experimentation**: a clean, multilingual dataset of short texts with engagement numbers is a good playground for classification and trend models.

### 🤖 Ask an AI assistant about this scraper

Paste this into ChatGPT, Claude or any assistant to get help designing your run:

> I am using the ParseForge Telegram Keyword Search Scraper on Apify. It takes keywords (quoted phrases and hashtags allowed), discovers public Telegram channels about each keyword and runs Telegram's own search inside each one, plus any channels I list. It returns one row per matching message with 36 fields, including url, channel, channelTitle, channelId, keyword, text, date, views, totalReactions, reactions, messageType, forwardedFrom, linkPreviewUrl, links, hashtags, photoUrls, videoUrls, channelSubscribers, channelVerified, matchedTerms and matchSource. It can search deeper into channel history, filter by date window, minimum views and media, and require exact words. Help me design a run to answer this question: \[your question here].

### ❓ Frequently Asked Questions

**🔐 Do I need a Telegram account, phone number or API key?**
No. The Actor reads the public web preview that Telegram serves to anyone at t.me/s. You never supply credentials.

**🔎 Does every result really contain my keyword?**
Every result is a message Telegram's own search returns for your keyword in that channel. Telegram matches word forms (staking also finds stake and unstaked) and link text, so in our tests about one message in six did not show every word literally. Switch on **Exact words only** to keep only messages whose visible text contains every word, or quote the keyword for an exact phrase.

**📚 How many messages can I get per keyword?**
Telegram's search returns the 22 newest matches per channel and keyword, and discovery finds about 20 channels per keyword, so a typical keyword yields a few hundred messages. **Deep search** reads each channel's history and returns older matches too, up to **Max messages scanned per channel**.

**🛰 How are channels discovered?**
Through a web search restricted to t.me, in the language and country you pick, and optionally limited to pages active in the last day, week, month or year. Only channels whose search result mentions your keyword are kept. Small or new channels that are not indexed yet will not be found; list them in **Channels to search**.

**📋 Can I search only my own channels?**
Yes. Add them to **Channels to search** and switch **Discover channels automatically** off.

**📭 Can I export a channel without a keyword?**
Yes. Leave **Keywords** empty and list channels: the Actor exports their latest messages, newest first, up to **Max results per channel**.

**📅 How does the date filter work?**
Use a date (YYYY-MM-DD) or a relative value such as `7 days`, `3 months` or `1 year`. It applies to the message date. With deep search, the history scan stops as soon as it passes the start of your window.

**🔒 Can it read private channels or groups?**
No. Only public channels with a web preview. Private channels, private groups, bots and personal accounts are skipped and named in the log.

**🌍 Do I need a proxy?**
No for normal use. Telegram's public pages answered every request in our tests without one, from a home IP and from Apify's cloud. The proxy setting is there for very large runs.

**🖼 Do I get the media files?**
You get the photo and video URLs Telegram serves, document names and sizes, and the link preview card. The file URLs are temporary Telegram CDN links, so download them soon after the run if you need copies.

**📥 What export formats are supported?**
CSV, Excel, JSON, XML, plus direct API access and integrations with Make, Zapier, Airbyte, Slack, Google Drive and more.

**⚖️ Is this legal?**
The Actor collects messages that channel owners publish to everyone. Messages can contain names and personal data, so you remain responsible for how you use the data, including privacy law such as GDPR and CCPA, and Telegram's terms.

### 🔌 Integrate with any app

Every run writes to an Apify dataset reachable through a REST API, so the output drops into whatever you already use. Native integrations cover Make, Zapier, Airbyte, Slack, Google Drive, GitHub, Google Sheets and webhooks, and the API covers everything else.

### 🔗 Recommended Actors

- [Telegram Channel Scraper](https://apify.com/parseforge/telegram-channel-scraper) - full message history of the channels you find here.
- [Reddit Scraper & Search API: Posts, Users, Subreddits](https://apify.com/parseforge/reddit-posts-scraper) - the same keyword research on Reddit.
- [X / Twitter Scraper - 42 Fields Per Post](https://apify.com/parseforge/x-com-scraper) - posts and engagement from X.
- [Google News Scraper](https://apify.com/parseforge/google-news-scraper) - news coverage of the same keywords.
- [Threads Scraper - Public Posts by Username](https://apify.com/parseforge/threads-search-scraper) - public posts from Threads.

> 💡 **Pro Tip:** browse the complete [ParseForge collection](https://apify.com/parseforge).

**🆘 Need Help?** [Open our contact form](https://tally.so/r/BzdKgA)

> **⚠️ Disclaimer:** independent tool, not affiliated with Telegram; only publicly available data.

# Actor input Schema

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

Words, phrases or #hashtags to search for. Each keyword is searched separately. Every returned message contains the keyword.

## `maxItems` (type: `integer`):

Free users: Limited to 10 items (preview). Paid users: Optional, max 1,000,000

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

Find public Telegram channels that mention each keyword (through a web search restricted to t.me) and search inside each of them.

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

Public channel usernames or links to search inside, for example `cointelegraph`, `@durov` or `https://t.me/s/telegram`. Searched for every keyword, on top of the discovered channels.

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

How many discovered channels to search for each keyword. Discovery usually finds 20 to 30 relevant channels per keyword.

## `discoveryLanguage` (type: `string`):

Language used to discover channels. It biases which channels are found; it does not translate messages.

## `discoveryCountry` (type: `string`):

Country used to discover channels. It biases which channels are found; it does not filter channels by location.

## `discoveryTimeRange` (type: `string`):

Only discover channels whose pages were indexed with activity in this period. Use it to favour channels that are active right now.

## `searchDepth` (type: `string`):

Fast uses Telegram's built-in search only (newest 22 matches per channel and keyword). Deep also scans each channel's history and returns older matches, up to the scan limit below.

## `maxResultsPerChannel` (type: `integer`):

Maximum matching messages returned from one channel for one keyword.

## `maxMessagesScannedPerChannel` (type: `integer`):

How far back deep search reads each channel's history, in messages. 1,000 messages is about 50 page loads per channel.

## `afterDate` (type: `string`):

Only messages published on or after this date. Pick a date or type a relative value such as `7 days`, `2 weeks`, `3 months` or `1 year`.

## `beforeDate` (type: `string`):

Only messages published before this date.

## `strictMatch` (type: `boolean`):

Telegram's search also matches word forms (staking finds stake and unstaked) and link text. Switch this on to keep only messages whose visible text contains every word of the keyword. Wrap a keyword in quotes to require the exact phrase.

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

Only messages with at least this many views.

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

Only messages that carry a photo, video, document or voice note.

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

Proxy used to load Telegram pages. Channel discovery always uses Apify's Google SERP proxy.

## Actor input object example

```json
{
  "keywords": [
    "bitcoin"
  ],
  "maxItems": 10,
  "discoverChannels": true,
  "maxChannelsPerKeyword": 20,
  "discoveryLanguage": "en",
  "discoveryCountry": "us",
  "discoveryTimeRange": "any",
  "searchDepth": "fast",
  "maxResultsPerChannel": 100,
  "maxMessagesScannedPerChannel": 1000,
  "strictMatch": false,
  "onlyWithMedia": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `overview` (type: `string`):

Key fields

## `fullData` (type: `string`):

Complete dataset with all 36 fields

# 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"
    ],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("parseforge/telegram-keyword-search-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"],
    "maxItems": 10,
}

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,parseforge/telegram-keyword-search-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/4OhN7iFEP6cKsigk3/builds/VDe570fA7LBmSgGh1/openapi.json
