# Telegram Scraper (`crawl_craft/telegram-scraper`) Actor

Tracking Telegram channels by scrolling misses posts and numbers. Scrape public channels in bulk: messages, views, reactions, media, links, polls, comments, subscriber counts and engagement stats, with keyword and date filters. No login needed.

- **URL**: https://apify.com/crawl_craft/telegram-scraper.md
- **Developed by:** [Crawl Craft](https://apify.com/crawl_craft) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.40 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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

### What is Telegram Scraper?

Telegram Scraper is an Apify Actor that collects public channel data from Telegram: messages, views, reactions, media links, comments and subscriber counts. Paste usernames or t.me links, press Start, and download one structured row per message. No Telegram account and no API key are needed.

- **Bulk input:** Add many usernames, channel links, post links or search links, and this Telegram public channel scraper works through them in one run.
- **Message-level detail:** Each row from this Telegram message scraper carries text, date, views, reactions, forwards, replies, media, links and polls.
- **Channel profiles:** Telegram channel statistics such as average views, engagement rate and top hashtags can be added to every channel.
- **Filters:** Narrow the results by date, message ID, keywords, content type, views, reactions and forwards.
- **Monitoring:** Return only the messages that are new since your previous run.

To start, click **Try for free**, paste a channel username and press **Start**.

### What data can you extract from Telegram?

You can export Telegram channel data in JSON, CSV or Excel from three tables: Messages, Channels and Comments. Pick the Telegram channel analytics fields you need, or keep them all. The field names below come from the dataset views of each table.

#### Messages table

The default dataset holds one row per message. Every row from this Telegram channel extractor has the same core fields, and the Output tab groups the fields into Overview, Engagement, Content, Media, Links and polls, and Compact tables. Each message is split into separate fields for text, date, links and media, which is what people usually expect from a Telegram channel parser.

| Field | View | Description |
|---|---|---|
| `channel.username` | Overview | Username of the channel the message belongs to |
| `id` | Overview | Message ID within the channel |
| `date` | Overview | Message date and time in ISO format |
| `text` | Overview | Plain text of the message |
| `views` | Overview | View count as a number |
| `reactionsTotal` | Overview | Total of all reaction counts |
| `contentTypes` | Overview | Content types found in the message, such as text, photo, video, poll or link preview |
| `url` | Overview | Link to the message on t.me |
| `viewsText` | Engagement | View count as Telegram shows it |
| `paidStars` | Engagement | Total of paid-star reactions |
| `engagementRate` | Engagement | Engagement rate of the message; empty when views are not available |
| `reactions` | Engagement | Reaction breakdown with a type and a count for each entry |
| `forwardedFrom` | Engagement | Source of a forwarded message: name, username, message ID, link and author |
| `replyTo` | Engagement | The message being replied to: message ID, link, author, text and quote |
| `commentsCount` | Engagement | Number of comments; filled when comment collection is on |
| `author` | Content | Author name shown on the message, when present |
| `edited` | Content | True when the message is marked as edited |
| `hasSpoiler` | Content | True when the message contains spoiler text |
| `entities` | Content | Hashtags, mentions, links, emails, phone numbers, crypto addresses and Telegram channels found in the message; added when extraction is on |
| `matchedKeywords` | Content | Keep-keywords that matched; present only when some matched |
| `searchQuery` | Content | Search phrase that found the message; present only for search results |
| `textHtml` | Content | Formatted message HTML; added when Include message HTML is on |
| `media` | Media | Media entries with type, link, thumbnail, duration and file details when Telegram shows them; saved files add `localPath` |
| `albumMessageIds` | Media | IDs of all messages in the same album |
| `mediaNotRendered` | Media | True when the public Telegram pages do not show the media |
| `mediaUnavailableReason` | Media | Reason given for media that is not shown |
| `links` | Links and polls | Links found in the message text |
| `linkPreview` | Links and polls | Link preview: link, site name, title, description, image and video links |
| `poll` | Links and polls | Poll question, options with percentages, voters and poll type |
| `buttons` | Links and polls | Inline buttons with text and link |
| `username` | Compact layout | Channel username with an @ prefix |
| `fullName` | Compact layout | Channel name |
| `followers` | Compact layout | Subscriber count of the channel |
| `bio` | Compact layout | Channel description |
| `url` | Compact layout | Link to the public page of the channel |
| `message.fulldate` | Compact layout | Message date and time in ISO format |
| `message.views` | Compact layout | View count as a number |
| `message.description` | Compact layout | Plain text of the message |
| `message.image` | Compact layout | Link to the first photo of the message |
| `message.video` | Compact layout | Link to the first video, GIF or round video of the message |
| `message.link` | Compact layout | Link to the message |
| `message.reply` | Compact layout | Text of the message being replied to |

#### Channels table

The Channels dataset has one row per channel and holds the profile and the statistics. Subscribers and statistics sit side by side, so you can compare Telegram channel subscribers statistics across many channels at once.

| Field | View | Description |
|---|---|---|
| `username` | Overview | Channel username |
| `title` | Overview | Channel name |
| `status` | Overview | Result of reading the channel: `ok`, `error`, `not_found`, `no_public_preview` or `invalid_input` |
| `subscribers` | Overview | Subscriber count, exact when available and otherwise rounded |
| `verified` | Overview | True when the channel has a verified badge |
| `messagesScraped` | Overview | Number of messages saved for the channel |
| `url` | Overview | Link to the channel |
| `avatarUrl` | Overview | Link to the channel picture |
| `description` | Profile | Channel description |
| `profileType` | Profile | `channel`, `group`, `bot` or `user` |
| `subscribersText` | Profile | Subscriber count as Telegram shows it |
| `subscribersExact` | Profile | True when `subscribers` is an exact count |
| `members` | Profile | Member count of a public group |
| `online` | Profile | Online count of a public group, when shown |
| `scam` | Profile | True when the channel carries a scam label |
| `fake` | Profile | True when the channel carries a fake label |
| `counters` | Profile | Counters from the channel header, keyed by name |
| `descriptionLinks` | Profile | Links in the channel description |
| `statusMessage` | Profile | May explain a missing post or a status other than `ok` |
| `channelId` | Profile | Numeric channel ID |
| `latestMessageId` | Profile | ID of the newest message seen |
| `stats.messagesAnalyzed` | Statistics | Number of messages analysed |
| `stats.postsPerDay` | Statistics | Average posts per day over the analysed period |
| `stats.avgViews` | Statistics | Average views per message |
| `stats.medianViews` | Statistics | Median views per message |
| `stats.maxViews` | Statistics | Highest view count among the analysed messages |
| `stats.avgReactions` | Statistics | Average reactions per message |
| `stats.engagementRate` | Statistics | Engagement rate across the analysed messages |
| `stats.viewsPerSubscriber` | Statistics | Average views relative to the subscriber count |
| `stats.forwardedShare` | Statistics | Share of analysed messages that are forwards, from 0 to 1 |
| `stats.editedShare` | Statistics | Share of analysed messages that were edited, from 0 to 1 |
| `stats.topHashtags` | Statistics | Up to 10 most used hashtags with counts |
| `stats.topDomains` | Statistics | Up to 10 most linked domains with counts |
| `stats.postingWeekdays` | Statistics | Message counts per weekday |

#### Comments table

A Telegram comments scraper is useful only when a channel has a discussion group, because that is where the comments live. The Comments dataset holds one row per collected comment.

| Field | Description |
|---|---|
| `channel` | Username of the channel |
| `postId` | ID of the post the comment belongs to |
| `commentId` | ID of the comment |
| `date` | Comment date and time in ISO format |
| `authorName` | Display name of the commenter |
| `authorUsername` | Username of the commenter, when available |
| `text` | Plain text of the comment |
| `reactions` | Reaction breakdown with a type and a count for each entry |
| `replyToCommentId` | ID of the comment being replied to |
| `url` | Link to the comment |

### Use cases for Telegram data

- **Topic and brand tracking:** Run a Telegram keyword search across the channels you follow and keep only the messages that match your words.
- **Market research:** Collect posts and views from industry channels with a Telegram data scraper and compare them over time.
- **Content archiving:** Keep a searchable archive of text, media links and link previews by scheduling a Telegram posts scraper.
- **Channel benchmarking:** Compare average views, engagement rate and posting frequency across several channels.
- **Contact and link discovery:** Pull hashtags, links, emails, phone numbers and crypto addresses that appear in public message text.
- **Audience feedback:** Read comments and reactions to see how followers respond to a post.
- **Data pipelines:** Send clean JSON rows into databases, dashboards or scripts, which a Telegram data extractor makes easier than copying by hand.

### How to scrape Telegram channel messages

1. Create a free Apify account.
2. Open Telegram Scraper in Apify Console.
3. Add usernames, channel links, post links or search links to **Channels, links or usernames** (`urls`).
4. Set **Max messages per channel** and any filters, such as dates or keywords.
5. Click **Start** and watch rows appear while the run is going.
6. Download the dataset as JSON, CSV or Excel to export Telegram channel posts into your own tools.

These steps are enough to scrape data from Telegram channel pages without writing code. A single run can also scrape Telegram messages from many channels at once.

Post links such as `https://t.me/durov/528` return that single message, a request you may have for a Telegram post scraper.

#### How to run a Telegram keyword search inside channels

Add one or more phrases to **Search inside channels** (`searchQueries`) to collect the messages that match each phrase. You can also paste a search link such as `https://t.me/s/durov?q=ton`, which this Telegram search scraper handles as a ready-made search.

To filter further, use **Keep messages containing** (`includeKeywords`) and **Drop messages containing** (`excludeKeywords`). The mode `keywordMatch` decides whether any or all keep-words must match, `keywordRegex` treats the lists as regular expressions, and `caseSensitive` matches letter case exactly.

#### How to export Telegram channel history by date

Set **Messages newer than** (`dateFrom`) and **Messages older than** (`dateTo`), or use **Messages from the last N days** (`scrapeLastNDays`). Relative values such as `7 days` or `2 weeks` work as well. A Telegram channel history download can also be limited by message ID with `messageIdFrom` and `messageIdTo`.

#### How to set up Telegram channel monitoring

Turn on **Only new messages since last run** (`incrementalMode`) and schedule the Actor in Apify Console. Each run then returns only the messages newer than the newest one seen in your previous run of this mode. For Telegram channel monitoring you can also add a `webhookUrl` to receive a short JSON summary when a run finishes.

#### How to download Telegram channel media

Telegram file links expire, so turn on **Save media files** (`downloadMedia`) to keep them. Choose the types in **Media types to save** (photo, video, GIF, voice message, round video or sticker) and set a size limit with `maxMediaSizeMB`. To download Telegram channel media, open the saved file through the permanent link in `localPath`.

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

Telegram Scraper uses tiered pay-per-event pricing: $2 per 1,000 results on the Free plan, and less on paid plans. Each run also pays a tiny Actor Start event of $0.00005 per run start.

| Apify plan | Price per 1,000 results |
|---|---|
| Free | $2 |
| Bronze | $1.8 |
| Silver | $1.6 |
| Gold / Platinum / Diamond | $1.4 |

One result is one message row. When you turn messages off, one result is one channel profile row. The Channels and Comments tables are not charged separately. For example, on the Free plan 1,000 results cost $2, plus the start event.

Free plan runs return up to 10 results per run. Paid plans have no per-run cap, and a maximum spend limit that you set on a run stops it cleanly when reached. See the Pricing tab for current rates.

### Input

Only `urls` is required. The example below uses values taken from the input schema (pre-filled or default). It is an example, not a captured run.

![Telegram Scraper input form with channel usernames and filters](IMAGE_URL_PLACEHOLDER "telegram-scraper-input-form.png")

```json
{
  "urls": ["durov", "https://t.me/telegram"],
  "collectMessages": true,
  "maxMessagesPerChannel": 10,
  "forwards": "include",
  "outputMode": "messages"
}
```

This Telegram messages scraper returns the newest messages first within each channel. Tip: keep **Max messages per channel** low for a first test run. See the Input tab for every option.

| Input | What it does |
|---|---|
| `urls` | Channel usernames, @handles, channel links, post links or search links |
| `collectMessages` | Turn off to get channel profiles only |
| `maxMessagesPerChannel` | Newest messages to collect from each channel; 0 means no limit |
| `dateFrom`, `dateTo`, `scrapeLastNDays` | Date range for messages |
| `messageIdFrom`, `messageIdTo` | Message ID range |
| `searchQueries` | Phrases to search inside channels |
| `includeKeywords`, `excludeKeywords`, `keywordMatch`, `keywordRegex`, `caseSensitive` | Keyword filters |
| `contentTypes` | Keep only messages with selected content types |
| `minViews`, `minReactions` | Drop messages below these counts |
| `forwards` | `include`, `exclude` or `only` forwarded messages |
| `includeServiceMessages` | Also return notices such as channel created |
| `exactSubscriberCount` | Return the full subscriber number instead of a rounded one |
| `channelStats` | Add channel statistics |
| `extractEntities` | Add hashtags, mentions, links, emails, phone numbers and crypto addresses |
| `includeHtml` | Add the formatted message HTML |
| `collectComments`, `maxCommentsPerPost` | Collect public comments; 0 means all |
| `discoverRelatedChannels`, `discoveryDepth`, `maxDiscoveredChannels` | Also read channels found in forwards, mentions and links |
| `downloadMedia`, `mediaTypesToDownload` (**Media types to save**), `maxMediaSizeMB` | Save media files to the run storage |
| `incrementalMode` | Only messages new since the last run |
| `webhookUrl` | Receives a short JSON summary when the run finishes |
| `outputMode` | `messages` for the detailed layout or `legacy` for the compact layout |
| `proxyConfiguration` | Optional proxy settings |

### Output

The scraped results are shown as a dataset in the **Storage** tab. The table view is for convenience and does not show **all the fields**.

![Telegram Scraper output table with messages and channels](IMAGE_URL_PLACEHOLDER "telegram-scraper-output-table.png")

Use the Output tab for a Telegram channel data download in these formats:

- JSON
- CSV
- Excel

The output has the Messages dataset, a Channels dataset, a Comments dataset when comment collection is on, and saved media files when media saving is on. The Compact result format gives one row per message with profile fields at the top and is chosen with the `outputMode` input. Example output is not shown on this page because no sample output exists for this Actor yet.

### Limitations and error handling

This Telegram channel scraper reads only public channels with visible messages. Private channels, invite links and links that do not point to a channel are rejected, and public groups, bots and user accounts return a channel row with the status `no_public_preview`.

- Free plan runs return up to 10 results per run.
- Comments can be collected only for channels that have a discussion group.
- Related channel discovery follows 1 to 3 levels and stops at your `maxDiscoveredChannels` value.
- Some fields can be empty when Telegram does not show them; if the exact subscriber count is not available, the rounded value is used.
- **Max messages checked per channel** (`maxScanned`) caps how many messages are checked in a channel when filters are very strict; 0 means no limit.
- A media file larger than `maxMediaSizeMB` is skipped and noted in `downloadError`.

Each channel row has a `status`. Message rows can carry a `commentsError` when comments could not be loaded.

| Status | Meaning | What to do |
|---|---|---|
| `ok` | The channel was read | Nothing |
| `error` | The channel page could not be loaded or processed | Run again later |
| `not_found` | The username does not exist or is not public | Check the spelling and that the channel is public |
| `no_public_preview` | A public group, a bot, a user account or a channel whose public page is disabled by its owner | Use a different public channel |
| `invalid_input` | The value in `urls` is not a valid username or link | Fix the value; the reason is in `statusMessage` |

### Integrating Telegram Scraper with other apps

This Telegram scraping tool runs on the Apify platform, so you can schedule runs, start them through the API and read the results in JSON, CSV or Excel. Teams that want a Telegram channel API can start runs with the Apify API and read the dataset items over HTTP. See the API tab for ready-made code snippets.

Use the `webhookUrl` input for a short summary at the end of each run. The [Apify integrations documentation](https://docs.apify.com/platform/integrations) and the [scheduling documentation](https://docs.apify.com/platform/schedules) explain how to connect runs with other tools.

### More Apify Actors by crawl_craft

This Telegram channel data extractor focuses on one source, so the Actors below are other public data Actors by crawl_craft.

| Actor | What it extracts | When to use it |
|---|---|---|
| [Facebook Posts Search Scraper](https://apify.com/crawl_craft/facebook-posts-search-scraper) | Public Facebook posts found by keyword or hashtag, with reactions, comments and shares | Use it when your target is Facebook posts instead of Telegram channels |
| [TikTok Video Scraper](https://apify.com/crawl_craft/tiktok-video-scraper) | TikTok video captions, hashtags, views, likes, comments, shares and author data | Use it when you have TikTok video links |
| [Google Job Scraper](https://apify.com/crawl_craft/google-job-scraper) | Google Jobs listings with company, location, salary and apply links | Use it when you need job listings |

### Is it legal to scrape Telegram?

Telegram Scraper only reads data that channel owners have made publicly available on Telegram and does not access private chats, private channels or accounts. Results can still contain personal data, for example names, usernames or contact details written in public posts and comments. Telegram channel scraping should therefore have a legitimate reason.

Consider GDPR (Regulation (EU) 2016/679) and the terms of the platform, and consult a lawyer if you are unsure. Apify explains the topic in [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/) and [Ethical web scraping](https://blog.apify.com/what-is-ethical-web-scraping-and-how-do-you-do-it/).

### FAQ

#### How much does it cost?

Pricing is tiered pay-per-event: $2 per 1,000 results on the Free plan and less on paid plans (see the table in the pricing section), plus an Actor Start event of $0.00005 per run start. Free plan runs return up to 10 results.

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

No. Because this Telegram web scraper reads public channel pages, you do not need a Telegram account, a login or an API key.

#### How many messages can I get?

Set `maxMessagesPerChannel` to the number you want per channel, or to 0 for no limit. Free plan runs are capped at 10 results. You choose how many posts this Telegram channel posts scraper collects, and the newest messages come first.

#### Can I get the Telegram channel subscriber count?

Yes. Each channel row has `subscribers` and `subscribersText`. With **Exact subscriber count** (`exactSubscriberCount`) on, the Actor returns the full number, such as 10459608, instead of a rounded value such as 10.4M. Asking for the Telegram channel subscriber count may still return a rounded value when the exact one is not available.

#### Can I download photos and videos?

Yes. Every message lists its media entries with type and link, and **Save media files** stores selected types for you. This Telegram channel media scraper supports photos, videos, GIFs, voice messages, round videos and stickers. Teams that look for a Telegram channel downloader should know that only the types you select are saved, up to your size limit.

#### Can I collect comments?

Yes, for channels that have a discussion group. Turn on **Collect comments** (`collectComments`) and set `maxCommentsPerPost`. This Telegram comment scraper adds the comments to each message and to the separate Comments table.

#### Is this different from the Telegram API?

Yes. If you searched for Telegram API channel statistics, note that this Actor needs no API credentials. It reads public pages and calculates statistics from the messages it collects, not owner-only analytics.

#### Can I scrape private channels or groups?

No. Only public channels with visible messages can be read. Public groups, bots and user accounts return a channel row with a status note instead of messages.

#### Is this a Telegram crawler?

It does not crawl all of Telegram, because it reads only the channels you list. With **Discover related channels** on, you get Telegram channel crawler behavior limited to forwards, mentions and links, up to 3 levels deep.

#### Can I use it with the API?

Yes. A Telegram channel message scraper workflow can start this Actor through the Apify API and read the dataset items afterwards. The API tab shows ready-made snippets.

### Your feedback

Found a bug or want a new feature? Open the Issues tab of this Actor on Apify. For custom solutions, write to hello.crawlcraft@gmail.com.

# Actor input Schema

## `urls` (type: `array`):

Public channel usernames (durov), @handles, channel links (https://t.me/telegram), post links (https://t.me/durov/528) or search links (https://t.me/s/durov?q=ton). Add as many as you like.

## `collectMessages` (type: `boolean`):

Turn off to get channel profiles only (title, bio, subscribers, statistics) without messages.

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

Newest messages to collect from each channel. 0 means no limit. Free plan users get up to 10 results per run; paid plans have no limit.

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

Only messages on or after this day. Pick a date, or use a relative value such as 7 days or 2 weeks.

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

Only messages on or before this day (the whole day is included). Same options as the start date.

## `scrapeLastNDays` (type: `integer`):

1 returns only today's messages, 2 yesterday and today, and so on. If a start date is also set, the more recent of the two is used.

## `messageIdFrom` (type: `integer`):

Only messages with this ID or higher.

## `messageIdTo` (type: `integer`):

Only messages with this ID or lower.

## `searchQueries` (type: `array`):

Run Telegram's own channel search for each phrase and collect the matching messages.

## `includeKeywords` (type: `array`):

Keep only messages that contain these words or phrases. Leave empty to keep everything.

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

Drop messages that contain any of these words or phrases.

## `keywordMatch` (type: `string`):

any keeps a message that has at least one of the keep-words; all requires every one of them.

## `keywordRegex` (type: `boolean`):

Treat the keyword lists as regular expressions instead of plain text.

## `caseSensitive` (type: `boolean`):

Match upper and lower case letters exactly.

## `contentTypes` (type: `array`):

Keep only messages that contain at least one of the selected types. Leave empty for all types.

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

Drop messages with fewer views than this.

## `minReactions` (type: `integer`):

Drop messages with fewer total reactions than this.

## `forwards` (type: `string`):

Include forwarded messages, exclude them, or return only forwarded messages.

## `includeServiceMessages` (type: `boolean`):

Also return notices such as channel created or photo updated.

## `exactSubscriberCount` (type: `boolean`):

Return 10459608 instead of 10.4M.

## `channelStats` (type: `boolean`):

Add average views, engagement rate, posting frequency, top hashtags and more to each channel.

## `extractEntities` (type: `boolean`):

Add hashtags, mentions, links, emails, phone numbers and crypto addresses found in each message.

## `includeHtml` (type: `boolean`):

Add the formatted message HTML (bold, links) next to the plain text.

## `collectComments` (type: `boolean`):

Collect public comments of posts in channels that have a discussion group. Comments are added to each message and to a separate Comments table.

## `maxCommentsPerPost` (type: `integer`):

Newest comments to keep for each post. 0 means all.

## `discoverRelatedChannels` (type: `boolean`):

Also scrape channels that appear in forwards, mentions and links of the collected messages.

## `discoveryDepth` (type: `integer`):

How many levels of related channels to follow.

## `maxDiscoveredChannels` (type: `integer`):

Upper limit of extra channels added by discovery.

## `downloadMedia` (type: `boolean`):

Telegram file links expire. Save the selected media types to the run's storage and return a permanent link in localPath.

## `mediaTypesToDownload` (type: `array`):

Which media to save when saving is on.

## `maxMediaSizeMB` (type: `integer`):

Skip files larger than this. 0 means no limit.

## `incrementalMode` (type: `boolean`):

Return only messages newer than the newest one seen in your previous run of this mode. Ideal for scheduled monitoring.

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

Optional address that receives a short JSON summary when the run finishes.

## `outputMode` (type: `string`):

Detailed gives one rich row per message (plus separate Channels and Comments tables). Compact gives one row per message with profile fields at the top.

## `concurrency` (type: `integer`):

Speed setting for the run, from 1 to 32. Higher values finish faster.

## `maxRetries` (type: `integer`):

How many times to try again when something fails before giving up.

## `requestTimeout` (type: `integer`):

Seconds to wait before giving up on a step.

## `maxScanned` (type: `integer`):

Upper limit of messages checked per channel when filters are strict. 0 means no limit.

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

Optional proxy settings. Leave the default unless you want to use your own proxy.

## Actor input object example

```json
{
  "urls": [
    "durov",
    "https://t.me/telegram"
  ],
  "collectMessages": true,
  "maxMessagesPerChannel": 10,
  "searchQueries": [],
  "includeKeywords": [],
  "excludeKeywords": [],
  "keywordMatch": "any",
  "keywordRegex": false,
  "caseSensitive": false,
  "contentTypes": [],
  "minViews": 0,
  "minReactions": 0,
  "forwards": "include",
  "includeServiceMessages": false,
  "exactSubscriberCount": true,
  "channelStats": true,
  "extractEntities": true,
  "includeHtml": false,
  "collectComments": false,
  "maxCommentsPerPost": 10,
  "discoverRelatedChannels": false,
  "discoveryDepth": 1,
  "maxDiscoveredChannels": 20,
  "downloadMedia": false,
  "mediaTypesToDownload": [
    "photo"
  ],
  "maxMediaSizeMB": 20,
  "incrementalMode": false,
  "outputMode": "messages",
  "concurrency": 8,
  "maxRetries": 3,
  "requestTimeout": 40,
  "maxScanned": 20000,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Core data of every message.

## `engagement` (type: `string`):

Views, reactions, forwards and replies.

## `content` (type: `string`):

Full text, author, hashtags, mentions and contacts.

## `media` (type: `string`):

Photos, videos, documents, audio and stickers.

## `links` (type: `string`):

Links, link previews, polls and buttons.

## `compact` (type: `string`):

Rows of the compact result format.

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

Channel profiles and statistics, one row per channel.

## `channelStatistics` (type: `string`):

Average views, engagement rate, posting frequency and top hashtags per channel.

## `comments` (type: `string`):

One row per collected comment (when comment collection is on).

## `mediaFiles` (type: `string`):

Media saved with the Save media files option.

## `runSummary` (type: `string`):

Counts, per-channel status and warnings.

# 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 = {
    "urls": [
        "durov",
        "https://t.me/telegram"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawl_craft/telegram-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 = {
    "urls": [
        "durov",
        "https://t.me/telegram",
    ],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("crawl_craft/telegram-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 '{
  "urls": [
    "durov",
    "https://t.me/telegram"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call crawl_craft/telegram-scraper --silent --output-dataset

```

## MCP server setup

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