Telegram Bulk Lookup: Channel Scraper, Member Count, Posts · Apify
Telegram Profile Scraper: Channel, Group, Bot & User Info avatar

Telegram Profile Scraper: Channel, Group, Bot & User Info

Pricing

from $1.15 / 1,000 profiles

Go to Apify Store
Telegram Profile Scraper: Channel, Group, Bot & User Info

Telegram Profile Scraper: Channel, Group, Bot & User Info

Telegram scraper for profiles in bulk: from usernames or t.me links, each telegram channel, group, bot or user with the exact subscriber or member count, title, bio, photo, verified, numeric id, newest post. Optional channel posts with views, comments and keyword search. No login. Misses free.

Pricing

from $1.15 / 1,000 profiles

Rating

0.0

(0)

Developer

Hyperbach

Hyperbach

Maintained by Community

Actor stats

0

Bookmarked

11

Total users

8

Monthly active users

4 days ago

Last modified

Features

Limited permissions

Share

Telegram channel, group, bot and user profiles from a list of usernames or t.me links: the exact subscriber or member count as Telegram writes it, the type, title, description, photo, verified mark, numeric id and newest post — one row per entity, and a free row that says why for a name that does not exist. Add the newest posts on request, newest first, with views as shown, reactions (paid Stars included), media, link previews, polls, buttons and comments; the creation date and the linked discussion group; and date windows and in-channel search. No login, no Telegram account, no API key, proxies handled for you.

From $2.25 per 1,000 rows (profile) on the Free plan, $1.90 on Starter; every row and add-on is priced under Pricing below. The default input returns about 3 rows for about $0.00675. A value that names nothing is a free row that says why.

A Telegram profile page in a browser: an invented channel, Tidewater Radio Club, with a verified mark, 48 213 subscribers and a one-line description. Beside it, the row this Actor returns for the profile, with count, count_type and count_text highlighted: the exact subscriber count as a number, what it counts and the line as the page writes it, then the rounded figure, the entity type, the verified mark and the description.

Why this Telegram profile scraper

  • Exact counts, labelled. The profile page writes the exact count ("10 493 438 subscribers"); the channel preview rounds it ("10.5M"). Every row carries the exact count with count_type and the line as written, next to the rounded subscribers_shown. Groups get members and members online, bots their monthly users.
  • The right type, and honest misses. Every row says channel, group, bot or user. Telegram answers a missing username with a normal-looking page — and answers a rate-limited reader with the same page. Each "not found" here was read on two different exits before it was written, and costs nothing. On our 100-name test list: 60 channels, 10 groups, 8 users and 22 missing names, the same split as a separate read of the source.
  • Newest posts first. Telegram's web preview lists posts oldest first; in our test of the lane, 9 rival runs returned the oldest posts of the page as "the latest". Here posts come newest first and walk back as far as you ask, with views exactly as shown and flagged when rounded (no "2" for 2.09M), reactions with paid Stars, media links, link previews, polls, buttons, forwards and replies. Ready-made: Telegram channel photos and videos: links from the newest posts.
  • Facts other public-page tools do not give. The numeric id of every public channel (and of public groups), in Telegram's and in the Bot API's form; the creation date from the channel's first post ("Channel created"); the linked discussion group; comments of each post. Ready-made: Vet Telegram channels: creation date, id, views per post.
  • Built for lists. Usernames, @handles, profile, preview, post and invite links in one list; the same entity given three ways is one row.
  • Light and fast. No browser and no Telegram account: one small page per profile. 100 names in about a minute; misses and rows for values that are not usernames are free.

Who it's for

  • Marketers and growth teams — vet channels and groups before a placement: exact subscribers or members, posting rate, views and reactions of the newest posts, verified mark.
  • Researchers and analysts — a list of channels with their newest posts, dates, views as shown and reactions, or a date window of a channel's history, in one row shape.
  • Developers and agents — typed fields, one row per input in input order, a free labelled row for every miss, and a run summary to check a pipeline against.

Quick start

Profiles of a channel, a bot and a group

{
"usernames": [
"durov",
"BotFather",
"https://t.me/tginfochat"
]
}

The 20 newest posts of each channel

{
"usernames": [
"durov",
"telegram"
],
"maxPostsPerChannel": 20
}

Posts of a date window, with comments

{
"usernames": [
"tginfo"
],
"postsNewerThan": "2026-09-01",
"postsOlderThan": "2026-10-01",
"maxCommentsPerPost": 10
}

Deep profile: creation date, ids, linked discussion group

{
"usernames": [
"durov",
"tginfo",
"tginfochat"
],
"deepProfile": true
}

Output

One profile row per entity you named (or a free row saying why there is none) and, when you ask for posts, one post row per post (row_type says which):

fieldmeaning
row_typeprofile = one per unique input (the entity's record, or a free row saying why there is none); post = one per post of a channel.
inputThe value as you gave it (the first form, when the same entity was given several ways). On post rows: the channel's input.
input_indexThe input's 1-based position in your list.
inputs_mergedLater values of your list that named the same entity (@durov and its link after durov); read once, one row.
profile_statusok = a public channel, group, bot or user (charged). Free rows: not_found (no public entity has the name — read on two exits, because Telegram serves a missing name and a rate-limited reader the same page), invalid (not a Telegram username or link), failed (Telegram answered something else; read again later).
status_detailWhy a row has no record, in words (null on ok rows).
scraped_atWhen the row was read (UTC).
usernameThe public username, as Telegram writes it (null for an invite link).
entity_typechannel, group, bot or user, read from the page: the count line (subscribers, members, monthly users), then the title and the button.
titleThe channel's, group's or bot's title, or the user's name.
descriptionThe description or bio, line breaks and emoji kept.
profile_urlThe profile's public page (t.me/<username>).
avatar_urlThe profile photo on Telegram's CDN (a signed link that changes on each read; null when there is no photo).
verifiedTelegram's verified mark.
warning_labelTelegram's own warning label on the profile, as its page shows it next to the title (FAKE, SCAM); null when there is none. It is never part of title.
invite_linkThe invite link you gave, for a group or channel read through one.
countThe entity's headline count, exact as Telegram writes it on the profile page: subscribers of a channel, members of a group, monthly users of a bot (null for a user).
count_typeWhat count counts: subscribers, members or monthly_users.
count_textThe count line exactly as the page shows it ("10 493 438 subscribers", "5 365 members, 1 163 online").
counts_precisionexact when count is the page's exact figure.
subscribersA channel's subscribers, exact.
subscribers_shownThe subscriber count as the channel's preview rounds it ("10.5M").
membersA group's members, exact.
members_onlineA group's members online at the moment of the read.
monthly_usersA bot's monthly users, exact.
chat_idThe numeric id of a channel (from its public posts) or of a public group (deepProfile, from its first message), in Telegram's own form (1006503122). Null for bots and users: no logged-out page shows theirs.
bot_api_idThe same id in the Bot API's form (-100 followed by chat_id).
has_previewThe channel shows its posts on the web (its /s/ preview); only such channels have post rows.
preview_urlThe channel's web preview.
photos_countPhotos the channel posted, from its preview (rounded above 999, as counters_shown says).
videos_countVideos the channel posted (rounded above 999).
files_countFiles the channel posted (rounded above 999; 0 when the preview shows no files counter).
links_countLinks the channel posted (rounded above 999).
counters_shownThe preview's counters exactly as written (subscribers "10.5M", photos "1.38K", …).
counters_precisionexact when every counter is written in full, rounded when one is written rounded ("1.38K" above 999).
latest_post_idThe channel's newest post (the last one on its preview: the preview lists posts oldest first).
latest_post_atWhen the newest post was published (UTC).
latest_post_urlThe newest post's link.
created_atdeepProfile: when the channel or group was created, or the earliest date the page shows (see created_at_source).
created_at_sourcechannel_created = post 1, Telegram's "Channel created" message (exact); first_post = post 1 is an ordinary post; oldest_post = post 1 is gone, the oldest post left (the channel existed by then); first_message = a group's first message (the group existed by then); post_1_embed = a channel without a public preview: the date of its post 1 in Telegram's embed widget, which does not show whether post 1 is the "Channel created" message (the channel existed by then).
linked_chat_idThe id of a channel's linked discussion group (deepProfile or comments), from the comments widget; on post rows, the group the comments came from.
engagement_postsHow many of the newest posts (the preview's first page, service messages left out) the engagement fields are computed over.
avg_viewsAverage views of those posts, as the page shows them (rounded above 999).
median_viewsMedian views of those posts.
avg_reactionsAverage reactions per post (all emoji and paid Stars together).
view_rateMedian views ÷ subscribers. On post rows: the post's views ÷ the channel's subscribers.
engagement_rateAverage reactions ÷ average views.
posts_per_weekPosting rate over the span of those posts.
dominant_scriptThe writing system most letters of the description and the newest posts are in (Latin, Cyrillic, Arabic, Han, …); links and handles left out.
posts_requestedPosts asked for this channel (maxPostsPerChannel, or 100 when a post filter set it).
posts_deliveredPost rows this run delivered for the channel.
posts_noteWhy a channel delivered fewer posts than asked (no older post, no public preview, Telegram's search ended, the newest an earlier run delivered, maxItems or your charge limit reached), and how comments were read.
deep_notedeepProfile: what could not be read and why — a bot's or a user's id and creation date (Telegram's web pages do not show them; they need a Telegram login, which this Actor does not use), a group whose first message is gone, a channel whose post 1 is gone (created_at is then a bound), a channel without a public preview (its id and date come from its post 1's embed; no linked group), an invite link.
markdownincludeMarkdown: the profile and its delivered posts as Markdown.
run_tagYour runTag, on every row.
channel_titleOn post rows: the channel's title.
channel_subscribersOn post rows: the channel's exact subscriber count at the time of the run.
post_idThe post's number in its channel. Deduplicate on username + post_id.
post_urlThe post's public link.
published_atWhen the post was published (UTC).
is_editedThe post carries Telegram's "edited" mark.
author_signatureThe author's signature, when the channel signs its posts.
textThe post's text, line breaks and emoji kept.
text_lengthCharacters in text.
hashtagsHashtags of the post.
mentions@usernames the post mentions.
linksLinks in the post's text.
viewsViews as the page shows them, as a number (2.09M → 2090000); views_precision says when it is rounded. Telegram shows exact views only to its apps.
views_shownViews exactly as written ("2.09M").
views_precisionexact (under 1,000) or rounded.
reactionsEach reaction: emoji (or the custom emoji's id), count, paid for Telegram Stars, the count as written and its precision.
reactions_totalAll reactions of the post together.
reactions_precisionrounded when a reaction count is written rounded on the page ("21.4K"), so reactions_total and paid_stars are sums of rounded values; exact otherwise.
paid_starsThe paid Star reactions of the post.
forwarded_fromThe name of the chat a forwarded post came from.
forwarded_from_urlThe original post's link, when public.
reply_to_post_idThe post this one replies to.
mediaPhotos (every photo of an album), videos (with duration), GIFs (gif: a looping clip, no duration), round videos, voice notes, music files (title, performer), documents (name, size) and stickers, with their CDN links (signed, valid for a while). A video too big for Telegram's web page has its thumbnail and duration, too_big: true and no file link (open the post in the app).
media_typesThe kinds of media in the post.
media_not_supportedTrue when Telegram's web page does not show the post's media ("Please open Telegram to view this post"): open the post in the app.
link_previewThe link preview: URL, site, title, description, image.
pollA poll: question, type, voters (and as written, with its precision: "71.7K" is rounded), options with their share in percent.
buttonsInline buttons under the post: row, text, URL.
matched_searchYour postsSearch, on the posts it found.
comments_countHow many comments the post has (the widget's own count).
comments_statusok, not_available (Telegram's "Discussion is not available": no public comments for the post), or not_asked (the channel's newest 5 posts had no discussion, so older posts were not asked; see posts_note).
commentsmaxCommentsPerPost: the comments: author name, handle (when public), text or media (a sticker, photo or video), date, the comment it replies to and reactions.

Example record:

{
"row_type": "profile",
"input": "durov",
"input_index": 1,
"inputs_merged": [
"@durov",
"https://t.me/durov"
],
"profile_status": "ok",
"status_detail": null,
"scraped_at": "2026-10-06T20:16:43Z",
"username": "durov",
"entity_type": "channel",
"title": "Pavel Durov",
"description": "Founder of Telegram.",
"profile_url": "https://t.me/durov",
"avatar_url": "https://cdn4.telesco.pe/file/M-TyKlOPLmDf65MjCoCy6WQAAGHv6kEmgSsdHU-98ome4oWbTEAAdsuraeQEFiRHGYWIUdPJKRaT73TGs6QuHxgyF6ELLDS6PE4se9WXx_WYQhf5X4F2XD6TY6CxLUtmn8OWc58w_oT25iNx30RAk6tVioIfIwAsc8m0htRA1pHh3jA6Y6t0Xtjrh6tLu-vBy7F_RmNql9LDoerXArtXkH_UK-BJY7fkel3g8TshvwhElfyOxkVO74VaxMA_HHFf1IBfvLD9wsrsmwjQ8RPbf3jLfw5p-1CaCIuZRyyPAicwDZS4Qqxz3kCPCbCo5V-kNvxg8VU8FH-KnyymhAoVqQ.jpg",
"verified": true,
"warning_label": null,
"invite_link": null,
"count": 10491495,
"count_type": "subscribers",
"count_text": "10 491 495 subscribers",
"counts_precision": "exact",
"subscribers": 10491495,
"subscribers_shown": "10.5M",
"members": null,
"members_online": null,
"monthly_users": null,
"chat_id": 1006503122,
"bot_api_id": -1001006503122,
"has_preview": true,
"preview_url": "https://t.me/s/durov",
"photos_count": 102,
"videos_count": 46,
"files_count": 0,
"links_count": 200,
"counters_shown": {
"subscribers": "10.5M",
"photos": "102",
"videos": "46",
"links": "200"
},
"counters_precision": "exact",
"latest_post_id": 548,
"latest_post_at": "2026-09-11T16:04:02Z",
"latest_post_url": "https://t.me/durov/548",
"created_at": "2015-10-28T18:20:58Z",
"created_at_source": "channel_created",
"linked_chat_id": null,
"engagement_posts": 20,
"avg_views": 5529500.0,
"median_views": 4390000.0,
"avg_reactions": 132263.4,
"view_rate": 0.4184,
"engagement_rate": 0.02392,
"posts_per_week": 1.51,
"dominant_script": "Latin",
"posts_requested": 2,
"posts_delivered": 2,
"posts_note": null,
"deep_note": null,
"markdown": "# Pavel Durov (@durov)\n\nchannel · 10,491,495 subscribers · verified\n\nFounder of Telegram.\n\nid 1006503122 · created 2015-10-28 · latest post 2026-09-11\n\n## Posts\n\n- [2026-09-11](https://t.me/durov/548) · 2.1M views: 🤝 Telegram has become the sponsor of Codeforces — the largest competitive programming platform in the world. ⚡CodeForces organizes over 100 coding contests every year and has 4 million contestants signed up. 🌱 Since 2010, I've supported Codeforces through the companies I sta…\n- [2026-09-06](https://t.me/durov/547) · 2.99M views: 💸 In just one month, Telegram has awarded over $2,222,000 to some of the brightest minds on our planet. 🎨 This week alone we distributed $222,000 among the winners of our two latest competitions — the Design Contest and the Digital Freedom Contest. On top of that, over the p…\n",
"run_tag": null,
"channel_title": null,
"channel_subscribers": null,
"post_id": null,
"post_url": null,
"published_at": null,
"is_edited": null,
"author_signature": null,
"text": null,
"text_length": null,
"hashtags": null,
"mentions": null,
"links": null,
"views": null,
"views_shown": null,
"views_precision": null,
"reactions": null,
"reactions_total": null,
"reactions_precision": null,
"paid_stars": null,
"forwarded_from": null,
"forwarded_from_url": null,
"reply_to_post_id": null,
"media": null,
"media_types": null,
"media_not_supported": null,
"link_preview": null,
"poll": null,
"buttons": null,
"matched_search": null,
"comments_count": null,
"comments_status": null,
"comments": null
}

Pricing

Pay only for the rows a run delivers, with no start fee and no platform usage billed to you. Prices fall with your Apify plan.

per 1,000FreeStarterScaleBusiness
Profile (profile)$2.25$1.90$1.55$1.15
Post (post)$1.50$1.275$1.05$0.75
Comment on a post row (comment)+$0.50+$0.425+$0.35+$0.25

A profile is $2.25 per 1,000 entities found on the Free plan and $1.15 on Business; a post $1.50 per 1,000 on Free. The deep profile (creation date, group id, linked discussion group) is part of the profile price. + comments are charged per comment delivered on a post row with maxCommentsPerPost. Free: the row for a name that does not exist (read on two exits), a value that is not a Telegram username or link, a page Telegram did not serve, and a run that failed before its first row. maxItems is exact; before the first request the log says the most the run can cost at your plan's prices. Enterprise plans have their own rates — the Actor's Pricing tab shows the price for your plan.

Usage patterns

Input configuration

fieldtypedefaultwhat it does
usernamesarray[]Telegram channels, groups, bots and users, one per line, in any form: durov, @durov, https://t.me/durov, t.me/s/durov, telegram.me/durov, a post link (t.me/durov/548 reads the channel) or an invite link (t.me/+AbC…, t.me/joinchat/…). One row per entity: the same entity given twice is read once. A value that is not a Telegram username or link comes back as a free row that says why.
maxPostsPerChannelinteger0How many of each channel's posts to deliver as post rows, newest first; 0 = the profile row only (it still carries the newest post's id and date). Only channels with a public preview have posts on the web; groups, bots and users have none. With a post filter (dates, search or comments) and 0 here, up to 100 posts per channel are read.
postsNewerThanstring""Only posts published on or after this date: 2026-09-01, or a span back from today such as 30 days, 2 weeks, 6 months (UTC). With Posts per channel at 0, up to 100 posts per channel are read.
postsOlderThanstring""Only posts published before this date (same forms as Posts from). The Actor jumps to that point of the channel by post id instead of reading every newer post.
postsSearchstring""Only posts that Telegram's own channel search finds for this text (a word, a phrase or a #hashtag), newest first. Telegram's search is shallow on large channels: the row says how many posts it returned.
maxCommentsPerPostinteger0Comments to add to each post row (comments: author, handle, text, date, reactions), from the channel's linked discussion group; 0 = none. A channel without public comments says so on each post (comments_status). Charged per comment delivered.
deepProfilebooleanfalseOne or two more requests per channel or group: the creation date (a channel's first post, Telegram's "Channel created" message; a group's first message), the numeric id of a public group, and a channel's linked discussion group (its id). Each fact says where it came from (created_at_source).
includeMarkdownbooleanfalseAdd a markdown text to each profile row: the profile and its delivered posts as Markdown, for a language model's context or a note.
maxItemsinteger0The most profile and post rows this run delivers (and charges), together. 0 = no limit. Free rows (not found, not a username) do not count.
runTagstring""A label copied onto every row (run_tag), to tell runs apart in a shared dataset.
feedbackstringA note to the people who maintain this Actor: what you needed and did not get. For example a missing field, a wrong or empty result, or the Actor you switch from or to, and why. The run does not read it: the rows and the charges stay the same. A person reads every note.

Errors

A run does not fail because of your input. When an input cannot be used — a date that is not a date, an id in the wrong form, two settings that contradict each other — the run ends Succeeded, charges nothing, and says what to change:

  • the status message starts with INPUT REJECTED;
  • the dataset holds one row, {"error": true, "code": "…", "message": "…"}, and no results;
  • the key-value store record ERROR holds the same object.

From code, check error on the first row before reading results.

A search that matches nothing is not an error: the dataset is empty and nothing is charged. A run that ends Failed is a fault on our side, never your input; it charges nothing, and we are alerted.

FAQ

Why is a name "not found" here when I can open it in the app?

The row says what the public web page shows. A user who hides their username from the web, a private group or channel, or a name used only inside the app has no public page. Every miss was read on two exits, so it is not a rate limit.

Are the views exact?

Telegram shows exact views only inside its apps; the public pages round them above 999 ("2.09M"). views is that value as a number and views_precision says rounded; views_shown keeps the text. The subscriber and member counts on the profile row are exact.

Can I get bot commands, a user's id, last seen or premium status?

No. Telegram serves those only to a logged-in account, and this Actor does not log in. The numeric id is given for public channels and groups, where the public pages carry it.

What is charged?

A profile row of an entity that was found, a post row, and each comment on a post row. Rows for names that do not exist, values that are not usernames, pages Telegram did not serve, and a run that failed before its first row are free; a run that stops early (a timeout, an abort) is charged for the rows it delivered. maxItems caps profile and post rows together. The prices are in the Pricing section above.

Does it read private channels or join groups?

No. It reads what Telegram shows to anyone on the web: profile pages, the public preview of channels, the public comments widget. An invite link gives the title and member count its page shows.

Can an AI agent use it (MCP)?

Yes. Apify's MCP server (https://mcp.apify.com) offers Store Actors as tools to Claude, Cursor and other MCP clients: add this Actor and the agent sends usernames and gets the rows back. The synchronous API (run-sync-get-dataset-items) does the same in one HTTP call.

Integration

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('hyperbach/telegram-profile-scraper').call({"usernames": ["durov", "BotFather", "https://t.me/tginfochat"]});
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Python

from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('hyperbach/telegram-profile-scraper').call(run_input={'usernames': ['durov', 'BotFather', 'https://t.me/tginfochat']})
items = client.dataset(run['defaultDatasetId']).list_items().items

CLI

$apify call hyperbach/telegram-profile-scraper --input '{"usernames": ["durov", "BotFather", "https://t.me/tginfochat"]}'

REST

curl -X POST "https://api.apify.com/v2/acts/hyperbach~telegram-profile-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H 'Content-Type: application/json' -d '{"usernames": ["durov", "BotFather", "https://t.me/tginfochat"]}'

AI agents and MCP

Apify's MCP server offers this Actor as a tool to Claude, Cursor, VS Code and any other MCP client. Connect https://mcp.apify.com?tools=hyperbach/telegram-profile-scraper and ask, for example: "Get the profiles of the Telegram channel durov, the bot BotFather and the group tginfochat". The agent fills the input from the table above and reads the rows from the run's dataset. The input names are the ones in the table above. An agent or a person can add feedback to any run and say what was needed and not delivered: a missing field, a wrong or empty result, the Actor switched from or to, and why. The run returns the same rows at the same price, and a person reads every note.

n8n, Make and Zapier

The Apify node in n8n, the Apify app in Make and the Apify integration in Zapier run this Actor on a schedule or from a trigger and read its dataset. A webhook on the run's end (Integrations on the Actor page) sends the rows on to your own endpoint. Nothing to install on our side.

Support

Disagree with a charge? Write to apify@hyperbach.com with the run ID. We will ask Apify to compensate you, and the charge comes back to your Apify account as platform credit.

Did it do the job? A short review on the Store, at any rating, helps the next buyer choose.

See also

  • YouTube Channel Search Scraper — the YouTube channels a keyword finds, with subscribers, the exact video and view counts and the country.
  • Threads Scraper — Threads profiles with the exact follower count, their posts and replies with view counts, and keyword and tag search, without a login.
  • Substack Scraper — the posts of a Substack newsletter with the full text of free posts, the date, the paywall flag and the likes.
  • Weibo Scraper — Weibo posts, profiles, search, comments and the hot-search boards, without a login.
  • Pinterest Search Scraper — the pins of a Pinterest search, with the link each pin points to, the image and the pinner.
  • Spotify Scraper — the tracks of a Spotify playlist or album and an artist's top tracks and releases, with play counts.

This page is generated from the Actor's schemas and a live sample — it cannot describe a field the Actor does not have.