# Telegram Channel Scraper (`parseforge/telegram-channel-scraper`) Actor

Archive messages, media, reactions, and metadata from any public Telegram channel - 35 fields per message, no phone or API key required.

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

## Pricing

from $11.25 / 1,000 result items

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

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

## 📨 Telegram Channel Scraper

> 🚀 **Archive entire Telegram channels in seconds.** Pull messages, photos, videos, link previews, reactions, view counts, and channel stats from any public channel. No login, no MTProto, no API key.

> 🕒 **Last updated:** 2026-05-09 · **📊 35 fields** per record · **No auth required** · **Pagination back to message #1** · **Multi-channel batches**

Telegram is one of the largest open broadcast networks on the internet, with public channels covering crypto markets, breaking news, government communications, fan communities, and developer announcements. The platform's web preview at `t.me/s/{channel}` exposes a full archive of any channel that has enabled public preview, but it is paginated, HTML-rendered, and rate-sensitive. Pulling a clean dataset out of it by hand means stitching dozens of pages, parsing fragile DOM, and handling every media type Telegram supports.

This actor handles all of that. Point it at one channel or a hundred, set a maximum, and it walks the public preview newest-first, parses every supported message type (text, photo, video, voice, document, sticker, poll, location, forwarded, reply, service), normalizes view counts and reaction tallies, and ships **35 structured fields** per message. Every record includes the source channel's title, description, subscriber count, and verified status, so single records stand on their own without needing a join. Channels that do not expose a public preview are flagged with an `error` record rather than failing the whole run.

| 👥 Target Audience | 🎯 Primary Use Cases |
| --- | --- |
| Crypto researchers tracking project announcements | Build longitudinal datasets of token launch posts and community sentiment |
| Compliance and risk teams archiving public chatter | Snapshot regulated entities' public messaging for retention requirements |
| Investigative journalists documenting sources | Capture an immutable copy of public channel posts before they are edited |
| OSINT and threat-intel analysts | Monitor activity, view counts, and reaction signals at scale |
| Academic researchers studying online communities | Collect reproducible corpora of public channel discourse |

---

### 📋 What the Telegram Channel Scraper does

- 📡 **Multi-channel input.** Accepts channel usernames, `@handles`, or full `https://t.me/...` URLs. Each channel is paginated independently with its own per-channel cap.
- 🧾 **Full message body.** Returns both plain text and Telegram's original HTML, including emoji, formatting, and outbound `<a>` links.
- 🖼️ **Every media type.** Photos, videos (including round videos), voice notes, documents, stickers, polls, locations, plus link preview cards.
- 🔁 **Forwards and replies.** Captures the original channel name and link for forwards, the parent message for replies, and the snippet of the message being replied to.
- 📈 **Engagement signals.** View counts and full reaction tallies (including paid Star reactions) parsed into clean integers (no `1.2K` strings).
- 🗓️ **Date-bounded archival.** Optional `fromDate` / `toDate` filters stop pagination at the right point so you do not pay to scrape outside the window.

Each record carries `channelTitle`, `channelDescription`, `channelSubscribers`, and `channelVerified` from the channel's profile page so a single message can be analyzed without joining a separate channels table. Reaction blocks include both the unicode emoji (when standard) and the Telegram custom-emoji ID for branded reactions, and paid Star reactions are flagged with `isPaid: true`.

> 💡 **Why it matters:** Telegram's MTProto API requires a registered application, a phone number, and a session that can be flagged or banned. The public preview is anonymous and rate-friendly. This actor turns it into a clean dataset without any of that overhead.

---

### 🎬 Full Demo

🚧 Coming soon: a 3-minute walkthrough showing how to scrape multiple channels, filter by date, and route results to a Google Sheet via integrations.

---

### ⚙️ Input

<table>
<tr><th>Field</th><th>Type</th><th>Required</th><th>Description</th></tr>
<tr><td><code>channels</code></td><td>array of strings</td><td>yes</td><td>Channel usernames, <code>@handles</code>, or <code>https://t.me/...</code> URLs. Channel must have public preview enabled.</td></tr>
<tr><td><code>maxItems</code></td><td>integer</td><td>no</td><td>Total cap across all channels. Free plan: 10. Paid plan: up to 1,000,000.</td></tr>
<tr><td><code>maxItemsPerChannel</code></td><td>integer</td><td>no</td><td>Per-channel cap. Useful when scraping many channels but you only want recent activity from each.</td></tr>
<tr><td><code>fromDate</code></td><td>date string</td><td>no</td><td>ISO 8601 date. Pagination stops once the page's oldest message is older than this.</td></tr>
<tr><td><code>toDate</code></td><td>date string</td><td>no</td><td>ISO 8601 date. Messages newer than this are skipped.</td></tr>
<tr><td><code>messageTypes</code></td><td>array</td><td>no</td><td>Restrict to selected types: text, photo, video, voice, document, sticker, poll, location, service, forwarded, reply.</td></tr>
<tr><td><code>onlyWithMedia</code></td><td>boolean</td><td>no</td><td>Skip text-only messages.</td></tr>
<tr><td><code>includeChannelMetadata</code></td><td>boolean</td><td>no</td><td>Attach channel title, description, subscriber count, and verified flag to every record. Default <code>true</code>.</td></tr>
<tr><td><code>includeReactions</code></td><td>boolean</td><td>no</td><td>Include the reactions array. Default <code>true</code>.</td></tr>
<tr><td><code>includeLinkPreview</code></td><td>boolean</td><td>no</td><td>Include link preview metadata when present. Default <code>true</code>.</td></tr>
<tr><td><code>outputFormat</code></td><td>string</td><td>no</td><td><code>text</code>, <code>html</code>, or <code>both</code>. Controls whether the message body returns plain text, original Telegram HTML, or both.</td></tr>
<tr><td><code>proxyConfiguration</code></td><td>object</td><td>no</td><td>Standard Apify proxy configuration object.</td></tr>
</table>

Example: scrape the latest 100 posts from one channel.

```json
{
    "channels": ["durov"],
    "maxItems": 100
}
````

Example: scrape three channels, last 30 days, photos and videos only.

```json
{
    "channels": ["cointelegraph", "crypto", "tginfo"],
    "maxItems": 5000,
    "maxItemsPerChannel": 2000,
    "fromDate": "2026-04-09",
    "messageTypes": ["photo", "video"]
}
```

> ⚠️ **Good to Know:** Only channels with a public web preview are scrapeable. Private channels and groups, and channels whose owners have disabled the preview, return an error record. Telegram's public preview is anonymous; we do not authenticate, do not impersonate a user, and do not access any non-public data.

***

### 📊 Output

Each record represents one message and carries channel-level fields for joinless analysis.

#### 🧾 Schema

| Field | Type | Example |
| --- | --- | --- |
| 🖼️ `imageUrl` | string | `https://cdn4.telesco.pe/file/K9wOaBteN...` |
| 📛 `channel` | string | `cointelegraph` |
| 🔗 `channelUrl` | string | `https://t.me/cointelegraph` |
| 🏷️ `channelTitle` | string | `Cointelegraph` |
| 📝 `channelDescription` | string | `The Future of Money. Trusted crypto & Web3 media since 2013.` |
| ✅ `channelVerified` | boolean | `true` |
| 👥 `channelSubscribers` | integer | `374535` |
| 🆔 `messageId` | integer | `69568` |
| 🔗 `url` | string | `https://t.me/cointelegraph/69568` |
| 📅 `date` | string | `2026-05-08T18:16:01+00:00` |
| ✏️ `edited` | boolean | `false` |
| 👤 `author` | string | `Cointelegraph` |
| 💬 `text` | string | `🔥 LATEST: $TON now ranks as the highest yielding...` |
| 🧱 `htmlText` | string | `<b>🔥 LATEST: </b>$TON now ranks as...` |
| 👁️ `views` | integer | `4670` |
| 💰 `isPaid` | boolean | `false` |
| 🏷️ `type` | string | `photo` |
| ↩️ `forwardedFrom` | string | `Pavel Durov` |
| 👤 `forwardedFromAuthor` | string | `Pavel Durov` |
| 🔗 `forwardedFromUrl` | string | `https://t.me/durov/503` |
| 🔁 `replyTo` | string | `tginfo/4282` |
| 🔗 `replyToUrl` | string | `https://t.me/tginfo/4282` |
| 👤 `replyToAuthor` | string | `Telegram Info` |
| 💬 `replyToText` | string | `Telegram разместил облигации на $1.7 млрд` |
| 🖼️ `photos` | array | `[{url, aspectRatio}]` |
| 🎬 `videos` | array | `[{url, thumbnailUrl, duration, durationSeconds}]` |
| 🎙️ `voice` | object | `{url, duration, durationSeconds}` |
| 📎 `documents` | array | `[{url, title, extra}]` |
| 🌟 `sticker` | object | `{url}` |
| 📊 `poll` | object | `{question, type}` |
| 📍 `location` | object | `{url}` |
| 🪟 `linkPreview` | object | `{url, siteName, title, description, image}` |
| 🎉 `reactions` | array | `[{emoji, isPaid, count}]` |
| 🔢 `totalReactions` | integer | `55` |
| 🕒 `scrapedAt` | string | `2026-05-09T00:23:38.901Z` |

#### 📦 Sample records

<details>
<summary><b>Typical post</b> - photo with caption and reactions from a verified channel</summary>

```json
{
    "imageUrl": "https://cdn4.telesco.pe/file/K9wOaBteNCdwxsPVSRTG9ZnKL28cvIJtuFowOMnQSffX2b1E5Iphwg6LRhm1EMCF5qR_UAs2.jpg",
    "channel": "cointelegraph",
    "channelUrl": "https://t.me/cointelegraph",
    "channelTitle": "Cointelegraph",
    "channelDescription": "The Future of Money. Trusted crypto & Web3 media since 2013.",
    "channelVerified": true,
    "channelSubscribers": 374535,
    "messageId": 69568,
    "url": "https://t.me/cointelegraph/69568",
    "date": "2026-05-08T18:16:01+00:00",
    "edited": false,
    "author": "Cointelegraph",
    "text": "🔥 LATEST: $TON now ranks as the highest yielding staking asset among the top 50 cryptocurrencies by annual returns.\n\nNews | Markets | YouTube",
    "views": 4670,
    "isPaid": false,
    "type": "photo",
    "photos": [
        { "url": "https://cdn4.telesco.pe/file/K9wOaBteN...jpg", "aspectRatio": 1.22 }
    ],
    "videos": [],
    "voice": null,
    "documents": [],
    "linkPreview": null,
    "reactions": [
        { "emoji": "⭐", "isPaid": true, "count": 1 },
        { "emoji": "❤", "isPaid": false, "count": 27 },
        { "emoji": "🔥", "isPaid": false, "count": 10 },
        { "emoji": "👎", "isPaid": false, "count": 6 }
    ],
    "totalReactions": 55,
    "scrapedAt": "2026-05-09T00:23:38.901Z"
}
```

</details>

<details>
<summary><b>Edge case</b> - forwarded video with multi-channel provenance</summary>

```json
{
    "imageUrl": "https://cdn4.telesco.pe/file/LyUSf7LfsPJfG5KBOvqrjm3FPSW1Ibskd4Uw1LGie6lxfKlELJWwPmbrOD5LiGZey4LroVuzu.jpg",
    "channel": "crypto",
    "channelTitle": "@crypto",
    "channelSubscribers": 145666,
    "messageId": 3726,
    "url": "https://t.me/crypto/3726",
    "date": "2026-05-06T18:14:44+00:00",
    "author": "@crypto",
    "text": "🏁 TON leads Layer-1 blockchains in finality time. \n\n🔗 Sources: https://telegra.ph/Comparison-of-Layer-1-blockchains-by-finalization-time-05-01",
    "views": 5700,
    "type": "video+forwarded",
    "forwardedFrom": "Pavel Durov",
    "forwardedFromAuthor": "Pavel Durov",
    "videos": [
        {
            "url": "https://cdn4.telesco.pe/file/85102421eb.mp4?token=oUKttOUMo12vIGxv...",
            "thumbnailUrl": "https://cdn4.telesco.pe/file/LyUSf7LfsPJfG5KBOvqrjm3FPSW1...",
            "duration": "0:29",
            "durationSeconds": 29
        }
    ],
    "reactions": [
        { "emoji": "❤", "isPaid": false, "count": 18 },
        { "emoji": "🔥", "isPaid": false, "count": 7 },
        { "emoji": "👍", "isPaid": false, "count": 4 }
    ],
    "totalReactions": 29,
    "scrapedAt": "2026-05-09T00:23:36.214Z"
}
```

</details>

<details>
<summary><b>Sparse / service message</b> - pinned-photo notification with no body</summary>

```json
{
    "imageUrl": null,
    "channel": "crypto",
    "channelTitle": "@crypto",
    "channelSubscribers": 145666,
    "messageId": 3722,
    "url": "https://t.me/crypto/3722",
    "date": "2026-05-04T14:30:14+00:00",
    "author": "@crypto",
    "text": "@crypto pinned a photo",
    "views": null,
    "type": "service",
    "photos": [],
    "videos": [],
    "voice": null,
    "documents": [],
    "linkPreview": null,
    "reactions": [],
    "totalReactions": 0,
    "scrapedAt": "2026-05-09T00:23:35.352Z"
}
```

</details>

***

### ✨ Why choose this Actor

| | Capability |
| --- | --- |
| 🪪 | **No authentication.** No phone number, no MTProto, no app registration. Anonymous scraping of public previews only. |
| 🧱 | **Schema stability.** 35 documented fields, every one named in the output schema, with consistent typing across runs. |
| 🎬 | **Full media coverage.** Photos, videos, round videos, voice notes, documents, stickers, polls, locations, link previews, paid media flags. |
| 🔁 | **Provenance preserved.** Forwards keep the original channel name and link; replies keep the parent ID, author, and snippet. |
| 📅 | **Date-bounded pagination.** `fromDate` stops the crawl at the right point so big channels do not run forever. |
| 📈 | **Numeric engagement.** `1.2K` and `2.6M` parsed to `1200` and `2600000`; reactions summed into `totalReactions`. |
| 🛰️ | **Apify Proxy ready.** Works direct or through Apify residential / datacenter proxy groups for hardened runs. |

> 📊 In sample crawls across `durov`, `cointelegraph`, `crypto`, and `tginfo`, the actor pulled 50 messages in 4 seconds with zero retries.

***

### 📈 How it compares to alternatives

| Approach | Cost | Coverage | Refresh | Filters | Setup |
| --- | --- | --- | --- | --- | --- |
| ⭐ **Telegram Channel Scraper** *(this Actor)* | Pay per usage | Any public channel with web preview | On-demand | channels, dates, types, media | Paste channels and click run |
| MTProto API clients | Free, but requires phone + session | Full Telegram surface (private chats too) | Real-time | Custom code | App registration, phone, session management |
| Browser automation against Telegram Web | High (browser cost) | Anything you can see logged in | Real-time | Custom code | Headless setup, login, anti-bot handling |
| Generic web crawlers | Low | Whatever HTML they parse | Periodic | Limited | DOM selectors break each Telegram update |
| Manual copy and paste | Free | A handful of messages | Whenever you bother | None | Free time |

This actor sits between "free but operationally heavy" (MTProto) and "shallow web crawlers": authenticated-quality data, anonymous-grade simplicity.

***

### 🚀 How to use

1. ✨ **Sign up.** Create an Apify account at [console.apify.com/sign-up](https://console.apify.com/sign-up?fpr=vmoqkp). Free tier covers 10 messages so you can preview the output before upgrading.
2. 📋 **Open the actor.** Find Telegram Channel Scraper in the [ParseForge collection](https://apify.com/parseforge) and click Try for free.
3. 🎯 **Pick channels.** Paste channel usernames or `t.me/...` URLs into the Telegram Channels field. Add as many as you like.
4. 🎚️ **Tune limits and filters.** Set `maxItems`, `maxItemsPerChannel`, optional date window, and message types. Defaults pull the latest 10 messages per channel.
5. 💾 **Run and download.** Click Start. Stream results to JSON, CSV, Excel, RSS, or pipe directly into Google Sheets, S3, or your warehouse via Apify integrations.

> ⏱️ **Total time:** under 60 seconds from sign-up to first dataset row.

***

### 💼 Business use cases

<table>
<tr>
<td width="50%">

#### 🪙 Crypto research desks

- Track token announcements from project channels
- Detect coordinated promotion via reaction spike anomalies
- Build sentiment datasets across the top crypto channels
- Capture pump-and-dump signals before they are deleted

</td>
<td width="50%">

#### 📰 Newsrooms and media monitoring

- Archive primary-source channels (officials, agencies, NGOs)
- Document edits and message deletions over time
- Snapshot breaking news threads for citation
- Build searchable Telegram archives by topic

</td>
</tr>
<tr>
<td width="50%">

#### 🛡️ Compliance and regulated industries

- Retain public messaging from supervised entities
- Monitor regulated communities for policy violations
- Generate audit trails of public corporate communications
- Feed risk-rating models with engagement signals

</td>
<td width="50%">

#### 🔍 OSINT and threat intel

- Track adversary channel activity at scale
- Map cross-channel forward graphs to identify networks
- Score channel growth and engagement programmatically
- Deliver structured Telegram feeds to SIEM and TIP tools

</td>
</tr>
</table>

***

### 🌟 Beyond business use cases

Data like this powers more than commercial workflows. The same structured records support research, education, civic projects, and personal initiatives.

<table>
<tr>
<td width="50%">

#### 🎓 Research and academia

- Empirical datasets for papers, thesis work, and coursework
- Longitudinal studies tracking changes across snapshots
- Reproducible research with cited, versioned data pulls
- Classroom exercises on data analysis and ethical scraping

</td>
<td width="50%">

#### 🎨 Personal and creative

- Side projects, portfolio demos, and indie app launches
- Data visualizations, dashboards, and infographics
- Content research for bloggers, YouTubers, and podcasters
- Hobbyist collections and personal trackers

</td>
</tr>
<tr>
<td width="50%">

#### 🤝 Non-profit and civic

- Transparency reporting and accountability projects
- Advocacy campaigns backed by public-interest data
- Community-run databases for local issues
- Investigative journalism on public records

</td>
<td width="50%">

#### 🧪 Experimentation

- Prototype AI and machine-learning pipelines with real data
- Validate product-market hypotheses before engineering spend
- Train small domain-specific models on niche corpora
- Test dashboard concepts with live input

</td>
</tr>
</table>

***

### 🔌 Automating Telegram Channel Scraper

Run the scraper from your own code or pipelines using the Apify API or SDKs.

- [**Node.js client**](https://docs.apify.com/sdk/js) for triggering runs and streaming dataset items.
- [**Python client**](https://docs.apify.com/sdk/python) for notebooks, ETL jobs, and ML pipelines.
- [**Apify API reference**](https://docs.apify.com/api/v2) for raw HTTP integration in any language.

For recurring archival jobs, use Apify Schedules to run the actor on a cadence (hourly, daily, weekly) and write the dataset to your destination. Each scheduled run captures the messages added since the previous run, so storage stays bounded.

***

### ❓ Frequently Asked Questions

<details>
<summary>📡 <b>Which Telegram channels can this scrape?</b></summary>

Any channel whose owner has enabled the public web preview at `t.me/s/{channel}`. That is the case for the vast majority of public channels. Private channels, groups, and channels with the preview disabled return an `error` record.

</details>

<details>
<summary>🔐 <b>Do I need a phone number, app ID, or MTProto session?</b></summary>

No. The actor only reads anonymous public preview pages. There is no Telegram authentication, no API key, and no session to keep alive.

</details>

<details>
<summary>📜 <b>How far back can it go?</b></summary>

The public preview supports paginating back to message #1 of any channel that has it enabled. With `maxItemsPerChannel` you can cap how deep you go; with `fromDate` you can stop at a specific point in time.

</details>

<details>
<summary>🎬 <b>Does it return media files or just URLs?</b></summary>

URLs only. Photos, videos, voice notes, and documents are returned as direct CDN links from `cdn4.telesco.pe`. Downloading the binaries is left to your pipeline so you only pay for what you actually keep.

</details>

<details>
<summary>🧮 <b>How are reaction counts and views parsed?</b></summary>

Telegram displays compact numbers like `1.2K` and `2.6M`. The actor parses them to integers (`1200`, `2600000`) so you can sort, sum, and filter without string handling.

</details>

<details>
<summary>↩️ <b>What about forwarded messages and replies?</b></summary>

Forwards include `forwardedFrom` (channel name), `forwardedFromAuthor` (signed author), and `forwardedFromUrl` (link to the original) when available. Replies include `replyTo` (`{channel}/{messageId}`), `replyToUrl`, `replyToAuthor`, and a snippet of the parent message in `replyToText`.

</details>

<details>
<summary>💰 <b>Can I use the data commercially?</b></summary>

The actor extracts publicly available content. Whether your downstream usage is permitted depends on Telegram's terms, the source channel's content rights, and applicable copyright and data-protection law in your jurisdiction. Consult counsel for any commercial redistribution.

</details>

<details>
<summary>💳 <b>Do I need a paid Apify plan?</b></summary>

The free tier lets you preview 10 messages so you can validate the output. For larger archives, any paid Apify plan unlocks runs up to 1,000,000 messages. See [Apify pricing](https://apify.com/pricing).

</details>

<details>
<summary>⚠️ <b>What happens when a run fails midway?</b></summary>

Records are pushed to the dataset progressively, so anything successfully scraped before the failure is preserved. Re-running the actor with the same input continues from the latest channel data; for incremental archival, schedule the actor and dedupe by `url`.

</details>

<details>
<summary>⚖️ <b>Is scraping Telegram public previews legal?</b></summary>

The public preview is published by Telegram for anyone with a browser to read. Scraping public, non-personal data is generally permitted in most jurisdictions, but laws differ and this is not legal advice. Review the source channel's content, your local data-protection regime, and Telegram's terms before commercial use.

</details>

<details>
<summary>🚀 <b>Can I scrape many channels in one run?</b></summary>

Yes. Pass an array of channels and the actor processes them sequentially with per-channel and total caps. For very large jobs, scale horizontally by running multiple instances with disjoint channel lists.

</details>

<details>
<summary>🔌 <b>How do I integrate this with Make, Zapier, n8n, or Google Sheets?</b></summary>

Apify ships native integrations with Make, Zapier, n8n, Airbyte, Keboola, and Google Sheets. Pick your destination on the Integrations tab of the actor page; Apify handles the dataset-to-destination mapping.

</details>

***

### 🔌 Integrate with any app

- [**Zapier**](https://apify.com/integrations/zapier) - trigger downstream automations from each new dataset row.
- [**Make**](https://apify.com/integrations/make) - visual workflow builder for routing scraped messages.
- [**n8n**](https://apify.com/integrations/n8n) - self-hosted automation for sensitive Telegram archives.
- [**Google Sheets**](https://apify.com/integrations/google-sheets) - one-click export of the dataset to a sheet.
- [**Airbyte**](https://apify.com/integrations/airbyte) - ELT pipeline into Snowflake, BigQuery, Redshift, Postgres.
- [**Apify API**](https://docs.apify.com/api/v2) - direct HTTP integration in any language.

***

### 🔗 Recommended Actors

- [**📨 Reddit Posts Scraper**](https://apify.com/parseforge/reddit-posts-scraper) - companion archive tool for Reddit communities.
- [**🐦 X.com (Twitter) Post Scraper**](https://apify.com/parseforge/x-com-scraper) - the Twitter equivalent of this actor, no auth required.
- [**📸 Instagram Posts Scraper**](https://apify.com/parseforge/instagram-posts-scraper) - structured Instagram post archives.
- [**🎬 YouTube Scraper**](https://apify.com/parseforge/youtube-scraper) - channel and video metadata at scale.
- [**💬 Youtube Comments Scraper**](https://apify.com/parseforge/youtube-comments-scraper) - comment threads with replies and AI sentiment.

> 💡 **Pro Tip:** browse the complete [ParseForge collection](https://apify.com/parseforge) for more social, marketplace, and public-records scrapers.

***

**🆘 Need Help?**

[**Open our contact form**](https://tally.so/r/BzdKgA) and we will respond within one business day.

***

> ⚖️ **Disclaimer:** This actor only accesses public Telegram channel previews exposed by Telegram itself. It does not authenticate, impersonate users, or access private chats, groups, or content. Users are responsible for compliance with Telegram's terms of service and applicable law in their jurisdiction.

# Actor input Schema

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

List of public Telegram channels to scrape. Accepts channel usernames (e.g. `durov`), `@usernames`, or full URLs (`https://t.me/durov` or `https://t.me/s/durov`). The channel must have a public preview enabled.

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

Total maximum number of messages across all channels. Free users: limited to 10 items (preview). Paid users: optional, max 1,000,000.

## `maxItemsPerChannel` (type: `integer`):

Cap on messages scraped from any single channel. Useful when scraping many channels but you only want recent messages from each. Leave empty for no per-channel cap.

## `fromDate` (type: `string`):

Only return messages posted on or after this date (ISO 8601, e.g. `2025-01-01`). Leave empty to include the oldest available messages.

## `toDate` (type: `string`):

Only return messages posted on or before this date (ISO 8601, e.g. `2026-12-31`). Leave empty to include up to the most recent message.

## `messageTypes` (type: `array`):

Restrict to specific message types. Leave empty to include all types.

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

Skip text-only messages. Returns only messages that include at least one photo, video, voice note, document, sticker, or animated GIF.

## `includeChannelMetadata` (type: `boolean`):

Include channel title, description, subscriber count, and verified flag on every message record. Adds one extra request per channel.

## `includeReactions` (type: `boolean`):

Include the reactions array (emoji and counts) on each message. Disable to keep records lighter.

## `includeLinkPreview` (type: `boolean`):

Include link preview metadata (URL, site name, title, description, image) when a message contains a preview card.

## `outputFormat` (type: `string`):

How to render the message body. `text` strips formatting; `html` keeps Telegram's HTML; `both` returns both fields.

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

Apify Proxy configuration. Defaults to Apify's residential proxy group; Telegram preview pages are usually accessible from datacenter IPs too.

## Actor input object example

```json
{
  "channels": [
    "durov",
    "telegram"
  ],
  "maxItems": 10,
  "onlyWithMedia": false,
  "includeChannelMetadata": true,
  "includeReactions": true,
  "includeLinkPreview": true,
  "outputFormat": "both",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": []
  }
}
```

# Actor output Schema

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

Table view with the most useful message fields (channel, message ID, date, text, type, views, reactions).

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

Complete dataset with every field, including media arrays and reactions.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

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

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "channels": [
        "durov",
        "telegram"
    ],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("parseforge/telegram-channel-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "channels": [
        "durov",
        "telegram",
    ],
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("parseforge/telegram-channel-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "channels": [
    "durov",
    "telegram"
  ],
  "maxItems": 10
}' |
apify call parseforge/telegram-channel-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=parseforge/telegram-channel-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Telegram Channel Scraper",
        "description": "Archive messages, media, reactions, and metadata from any public Telegram channel - 35 fields per message, no phone or API key required.",
        "version": "0.1",
        "x-build-id": "Fy1P0wHlKXi3afF3M"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/parseforge~telegram-channel-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-parseforge-telegram-channel-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/parseforge~telegram-channel-scraper/runs": {
            "post": {
                "operationId": "runs-sync-parseforge-telegram-channel-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/parseforge~telegram-channel-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-parseforge-telegram-channel-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "channels"
                ],
                "properties": {
                    "channels": {
                        "title": "Telegram Channels",
                        "minItems": 1,
                        "type": "array",
                        "description": "List of public Telegram channels to scrape. Accepts channel usernames (e.g. `durov`), `@usernames`, or full URLs (`https://t.me/durov` or `https://t.me/s/durov`). The channel must have a public preview enabled.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxItems": {
                        "title": "Max Items",
                        "minimum": 1,
                        "maximum": 1000000,
                        "type": "integer",
                        "description": "Total maximum number of messages across all channels. Free users: limited to 10 items (preview). Paid users: optional, max 1,000,000."
                    },
                    "maxItemsPerChannel": {
                        "title": "Max Items Per Channel",
                        "minimum": 1,
                        "maximum": 1000000,
                        "type": "integer",
                        "description": "Cap on messages scraped from any single channel. Useful when scraping many channels but you only want recent messages from each. Leave empty for no per-channel cap."
                    },
                    "fromDate": {
                        "title": "From Date",
                        "type": "string",
                        "description": "Only return messages posted on or after this date (ISO 8601, e.g. `2025-01-01`). Leave empty to include the oldest available messages."
                    },
                    "toDate": {
                        "title": "To Date",
                        "type": "string",
                        "description": "Only return messages posted on or before this date (ISO 8601, e.g. `2026-12-31`). Leave empty to include up to the most recent message."
                    },
                    "messageTypes": {
                        "title": "Message Types",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Restrict to specific message types. Leave empty to include all types.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "text",
                                "photo",
                                "video",
                                "voice",
                                "document",
                                "sticker",
                                "poll",
                                "location",
                                "service",
                                "forwarded",
                                "reply"
                            ],
                            "enumTitles": [
                                "Text only",
                                "Photo",
                                "Video",
                                "Voice",
                                "Document",
                                "Sticker / animated",
                                "Poll",
                                "Location",
                                "Service / pinned",
                                "Forwarded",
                                "Reply"
                            ]
                        }
                    },
                    "onlyWithMedia": {
                        "title": "Only Messages With Media",
                        "type": "boolean",
                        "description": "Skip text-only messages. Returns only messages that include at least one photo, video, voice note, document, sticker, or animated GIF.",
                        "default": false
                    },
                    "includeChannelMetadata": {
                        "title": "Include Channel Metadata",
                        "type": "boolean",
                        "description": "Include channel title, description, subscriber count, and verified flag on every message record. Adds one extra request per channel.",
                        "default": true
                    },
                    "includeReactions": {
                        "title": "Include Reactions",
                        "type": "boolean",
                        "description": "Include the reactions array (emoji and counts) on each message. Disable to keep records lighter.",
                        "default": true
                    },
                    "includeLinkPreview": {
                        "title": "Include Link Preview",
                        "type": "boolean",
                        "description": "Include link preview metadata (URL, site name, title, description, image) when a message contains a preview card.",
                        "default": true
                    },
                    "outputFormat": {
                        "title": "Text Output Format",
                        "enum": [
                            "text",
                            "html",
                            "both"
                        ],
                        "type": "string",
                        "description": "How to render the message body. `text` strips formatting; `html` keeps Telegram's HTML; `both` returns both fields.",
                        "default": "both"
                    },
                    "proxyConfiguration": {
                        "title": "Proxy Configuration",
                        "type": "object",
                        "description": "Apify Proxy configuration. Defaults to Apify's residential proxy group; Telegram preview pages are usually accessible from datacenter IPs too.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": []
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
