Telegram Channel Scraper πŸ“¨ Messages, No Bot Token avatar

Telegram Channel Scraper πŸ“¨ Messages, No Bot Token

Pricing

from $1.43 / 1,000 message returneds

Go to Apify Store
Telegram Channel Scraper πŸ“¨ Messages, No Bot Token

Telegram Channel Scraper πŸ“¨ Messages, No Bot Token

Scrape messages from any public Telegram channel. Pass channel names or t.me links; get message text, view count, date, message ID, photo and video flags and a direct link as JSON or CSV. No API key, bot token or phone number. Since date filter keeps runs cheap.

Pricing

from $1.43 / 1,000 message returneds

Rating

0.0

(0)

Developer

Yaniv van der Stigchel

Yaniv van der Stigchel

Maintained by Community

Actor stats

1

Bookmarked

2

Total users

1

Monthly active users

4 hours ago

Last modified

Share

Telegram Channel Scraper β€” no API key, no bot token

Export messages from any public Telegram channel. Text, view counts, timestamps, direct links and media flags. No bot token, no phone number, no login.

Scrape public Telegram channels

  • Export Telegram channel messages to JSON or CSV
  • Download a Telegram channel's post history
  • Monitor a Telegram channel for new messages
  • Get Telegram post view counts and engagement
  • Archive a public Telegram channel

Pass several channels at once. Every row is tagged with its source channel.

Incremental mode β€” cheap scheduled runs

Set since to the date of your last run and the scraper stops as soon as it reaches older messages. A daily monitoring job costs a fraction of a full back-scrape, because it only returns what is new.

What you get per message

Message text (HTML stripped, entities decoded), view count as a number, ISO timestamp, message id, direct t.me link, and flags for photo, video and forwarded content.

Honest failure reporting

Private channels, deleted channels and misspelled names return a row with reason: "channel-unavailable" β€” and cost you nothing. You are only charged for messages actually delivered.

Input

FieldRequiredDescription
channelsyesNames, @handles, or t.me URLs
maxMessagesPerChannelnoNewest first. Default 200. Your cost ceiling.
sincenoISO date. Only messages after it.
proxynoOptional β€” not needed for typical runs

Example input

{
"channels": ["@telegram", "durov"],
"maxMessagesPerChannel": 500,
"since": "2026-08-01"
}

Output

Every row has the same fields whether it succeeded or failed, so you can select columns without branching. Failed rows are never charged.

FieldTypeDescription
successbooleanTrue when this row carries data. Failed rows are never charged.
sourceChannelstringThe channel input this row came from.
messageUrlstringPublic t.me link to the message.
messageIdintegerSequential message number within the channel.
textstringThe message body as published.
publishedAtstringISO 8601 timestamp of publication.
viewCountintegerViews at the time of the run. Null when Telegram does not expose it.
hasPhotobooleanTrue when the message includes a photo.
hasVideobooleanTrue when the message includes a video.
isForwardedbooleanTrue when the message was forwarded from elsewhere.
errorCodestringMachine-readable failure reason. Null on success.
errorMessagestringHuman-readable explanation of the failure. Null on success.

Example β€” success

{
"success": true,
"sourceChannel": "durov",
"messageUrl": "https://t.me/durov/526",
"messageId": 526,
"text": "Telegram now supports gifting Premium subscriptions to any user.",
"publishedAt": "2026-08-14T09:12:04+00:00",
"viewCount": 1284000,
"hasPhoto": true,
"hasVideo": false,
"isForwarded": false,
"errorCode": null,
"errorMessage": null
}

Example β€” failure

A failure carries the same fields, so nothing downstream has to branch.

{
"success": false,
"sourceChannel": "private_example_channel",
"messageUrl": null,
"messageId": null,
"text": null,
"publishedAt": null,
"viewCount": null,
"hasPhoto": null,
"hasVideo": null,
"isForwarded": null,
"errorCode": "channel-unavailable",
"errorMessage": "No public Telegram channel exists at this name, or it is private."
}

Error codes

  • channel-unavailable
  • unparseable-channel
  • no-messages-found
  • error

Use it for

  • Telegram channel messages β€” full text history from public channels
  • Telegram channel archive β€” a durable copy of a public channel
  • Public Telegram channel monitoring β€” scheduled runs with a since filter
  • Telegram backup β€” a durable local copy of a public channel's history
  • OSINT, news tracking and market monitoring
  • Research corpora and training datasets

Use it from an AI agent (MCP)

This Actor is callable as a tool through the Apify MCP server, so Claude, ChatGPT, Cursor and VS Code can run it directly.

Add the server to your MCP client:

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com",
"headers": {
"Authorization": "Bearer <YOUR_APIFY_TOKEN>"
}
}
}
}

Then ask for what you want in plain language β€” for example β€œget the recent messages from this public Telegram channel” β€” and the agent calls cleanfeed/telegram-channel-archive-scraper with the right input. Every output field is described in the dataset schema, so the agent knows what it is getting back before it runs anything.

Call it from code

Python

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("cleanfeed/telegram-channel-archive-scraper").call(run_input={
"channels": ["durov"],
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
if item["success"]:
print(item)

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('cleanfeed/telegram-channel-archive-scraper').call({
channels: ["durov"],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((i) => i.success));

cURL

curl -X POST "https://api.apify.com/v2/acts/cleanfeed~telegram-channel-archive-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
-H 'Content-Type: application/json' \
-d '{"channels": ["durov"]}'
If you needUse
Posts from public Bluesky accountsBluesky Posts Scraper
Posts from public Threads profilesThreads Posts Scraper

Limitations

  • Public channels only. Private channels, groups and direct messages are not accessible and never will be by this route.
  • No bot token or phone number is used, so there is no account to get restricted.
  • viewCount is null when Telegram does not publish it for a message.
  • Use the since filter for scheduled runs so each run only collects and charges for what is new.

FAQ

Do I need a bot token or phone number?

Neither. Public channel pages are read directly, so there is no API key, no bot and no account to get restricted.

Can I read private channels or groups?

No. Only public channels are accessible.

What channel formats work?

A channel name such as durov, an @durov handle, or a t.me/... link.

How do I keep scheduled runs cheap?

Set since to an ISO date. Each run then collects and charges only for messages published after it.

Why is viewCount sometimes null?

Telegram does not publish a view count for every message. The field is null rather than guessed.

Notes

Only public channels and publicly visible content. No bot token, no user account, no private groups, no personal data beyond what the channel publishes.