# Telegram API — public channel posts, views, reactions, media, in-channel search, single posts, comments and channel stats (exact subscriber count), no login

> Channel card for a public Telegram username: title, @username, description (+ its links), photo URL, verified badge, the EXACT subscriber count as Telegram prints it on t.me/<channel> (e.g. 10 146 005, where the preview only says 10.1M), and the preview's media counters (photos, videos, files, links). If the username is a group the card carries members and online counts; a user or bot is recognised too (`type`), with `preview_available: false`.
> ReefAPI engine `telegram` · 5 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/telegram/v1/<action>` with a JSON body.
- **Auth:** header `x-api-key: <YOUR_REEFAPI_KEY>` — create one free (1,000 credits, no card): https://reefapi.com/signup
- **Response (every call):** `{ ok: boolean, data: ..., meta: { record_count, credits, ... }, error: { code, message } }` — branch on `ok`. Failed calls are free except verified SHEIN NOT_FOUND on product/detail and price (4 credits).
- **One key + one shared credit pool** across every ReefAPI API. Per-call credits are listed on each endpoint below.
- **Use it from an AI agent (MCP):** connect `https://api.reefapi.com/mcp` (remote streamable-http). Clients that add connectors by URL, such as ChatGPT and the Claude app, connect with OAuth 2.1 (the user pastes their key once on a ReefAPI page; discovery at `/.well-known/oauth-protected-resource/mcp`). Config files send the key as `Authorization: Bearer <key>`. `?key=<key>` in the URL also works as a last-resort fallback.

## Endpoints

### POST https://api.reefapi.com/telegram/v1/channel — 3 credits
Channel card for a public Telegram username: title, @username, description (+ its links), photo URL, verified badge, the EXACT subscriber count as Telegram prints it on t.me/<channel> (e.g. 10 146 005, where the preview only says 10.1M), and the preview's media counters (photos, videos, files, links). If the username is a group the card carries members and online counts; a user or bot is recognised too (`type`), with `preview_available: false`.

**Parameters:**
- `channel` (string, required) — Public channel: its @username (with or without @) or a t.me link (https://t.me/durov, https://t.me/s/durov). Private invite links (t.me/+...) have no public preview and are rejected.

**Returns:** channel{username, type (channel|group|user|bot), title, description, description_links[], photo_url, verified, scam, subscribers (exact, channels), subscribers_display (the preview's rounded figure), members, online (groups), counters{photos, videos, files, links}, url, preview_url, preview_available, region_withheld, viewer_region}

**Example request body:**
```json
{
  "channel": "telegram"
}
```

### POST https://api.reefapi.com/telegram/v1/posts — 2 credits
One page of a public channel's posts as Telegram's web preview serves it (about 20 posts; an album counts as one), newest first. Page back with `before` (the `next_before` of the previous answer) or forward with `after`. Each post: id, URL, date, edited flag, author signature, text with its links / hashtags / mentions / cashtags, views, reactions (emoji or custom-emoji id, paid Stars, count), forwarded-from, reply-to, media (photos, videos with duration, documents, audio, voice, stickers, locations; album items with their own post ids), link preview, poll, inline URL buttons. The channel card (rounded subscriber count + media counters) comes with every page.

**Parameters:**
- `channel` (string, required) — Public channel: its @username (with or without @) or a t.me link (https://t.me/durov, https://t.me/s/durov). Private invite links (t.me/+...) have no public preview and are rejected.
- `before` (integer, optional) — Return the page of posts older than this post id (use `next_before` from the previous answer).
- `after` (integer, optional) — Return the page of posts newer than this post id (walks forward in time). Not together with `before`.

**Returns:** channel{username, title, description, photo_url, verified, subscribers_approx, subscribers_display, counters{}} + posts[]{post_id, url, channel, channel_id, date, edited, author_signature, text, links[], hashtags[], mentions[], cashtags[], views, views_display, views_is_exact, reactions[]{emoji, custom_emoji_id, paid, count, count_display, count_is_exact}, reactions_total, paid_stars, is_forwarded, forwarded_from{name, url, username, post_id, author}, reply_to{post_id, url, author, text, thumbnail}, media[]{type (photo|video|round_video|document|audio|voice|sticker|location), url, thumbnail, post_id, duration, duration_seconds, title, size, unavailable_reason}, link_preview{url, site_name, title, description, image, video}, poll{question, type, options[]{text, percent}, voters, voters_display}, inline_buttons[]{text, url}, is_service} + next_before, has_more, newer_after, region_withheld, viewer_region

**Example request body:**
```json
{
  "channel": "durov"
}
```

### POST https://api.reefapi.com/telegram/v1/search — 2 credits
Telegram's own search inside one public channel (`q`; a `#hashtag` finds that hashtag). Same post rows as `posts`, newest first: 20 on the first page and the rest on the page `next_before` points to. Telegram's channel search stops at the 22 newest matching posts (measured on 4 queries in 4 channels: 20 + 2, then no more page, and older `before` values return nothing) and publishes no total; to reach older matches, walk `posts`.

**Parameters:**
- `channel` (string, required) — Public channel: its @username (with or without @) or a t.me link (https://t.me/durov, https://t.me/s/durov). Private invite links (t.me/+...) have no public preview and are rejected.
- `query` (string, required) — Words to find in the channel's posts, or a #hashtag.
- `before` (integer, optional) — Older page: the `next_before` of the previous answer.

**Returns:** posts[] (same row as `posts`) + query, next_before, has_more, total_is_exact (always false: no total), results_cap (22, Telegram's search depth), region_withheld, viewer_region

**Example request body:**
```json
{
  "channel": "telegram",
  "query": "update"
}
```

### POST https://api.reefapi.com/telegram/v1/post — 1 credit
One post by its t.me URL (https://t.me/durov/531) or channel + post_id: the same row as `posts` plus the channel's verified flag. A deleted or never-existing post is NOT_FOUND.

**Parameters:**
- `url` (string, optional) — Post link https://t.me/<channel>/<post_id>. Provide url, or channel + post_id.
- `channel` (string, optional) — Channel @username (with post_id).
- `post_id` (integer, optional) — Post number inside the channel.

**Returns:** post{post_id, url, channel, channel_id, date, edited, text, links[], hashtags[], views, views_display, reactions[], is_forwarded, forwarded_from, reply_to, media[], link_preview, poll, inline_buttons[], channel_title, channel_verified} + region_withheld, viewer_region

**Example request body:**
```json
{
  "url": "https://t.me/durov/300"
}
```

### POST https://api.reefapi.com/telegram/v1/comments — 2 credits
Public comments under a channel post (the channel's linked discussion, as Telegram's comments widget shows it): newest `limit` comments, then older ones with `cursor` = the previous answer's `next_cursor`. Each comment: id, date, author name / @username / link / photo, text, links, reply-to (comment id, author, quoted text), reactions, media. Posts whose channel has no public discussion answer `comments_available: false` with 0 rows.

**Parameters:**
- `url` (string, optional) — Post link https://t.me/<channel>/<post_id>. Provide url, or channel + post_id.
- `channel` (string, optional) — Channel @username (with post_id).
- `post_id` (integer, optional) — Post number inside the channel.
- `limit` (integer, optional, default 20) — How many of the newest comments the first page returns (1-100; Telegram's widget caps at 100). Older pages (`cursor`) come in the widget's own page size.
- `cursor` (string, optional) — Opaque `next_cursor` from the previous comments answer, to read older comments.

**Returns:** comments_available, comments_total (the widget's own count), comments[]{comment_id, date, author_name, author_username, author_url, author_photo, text, links[], hashtags[], mentions[], reply_to_comment_id, reply_to{author, text}, reactions[], reactions_total, media[], edited} (oldest to newest, as the widget lists them) + next_cursor, has_more, unavailable_message

**Example request body:**
```json
{
  "url": "https://t.me/tginfo/4400"
}
```

## At scale
- **Volume:** 5M+ requests a day, measured at 60 requests a second across the fleet with no
  central bottleneck. Per-key limits are raised for high-volume accounts; volume pricing on request.
- **Missing a source:** tell us a site we do not cover and it becomes an engine. A customer asked
  for bestprice.gr on 21 Sep 2026 and it was in the catalog on 22 Sep.
- **Support:** 2 minute median time from a question in the live chat to the first answer. Setup
  help included, no support tier to buy.
- **One key, one credit pool** across every API. No per-site plans, no separate subscriptions.

## More
- Try it live, no code: https://reefapi.com/playground?engine=telegram
- Human docs page: https://reefapi.com/docs/telegram
- Overview page: https://reefapi.com/telegram-api
- Every ReefAPI API in one file (for your AI): https://reefapi.com/llms-full.txt
