# Telegram Voice Transcriber (`smolevich90/telegram-voice-transcriber`) Actor

Transcribe voice messages, video notes and videos from public Telegram channels into searchable text.

- **URL**: https://apify.com/smolevich90/telegram-voice-transcriber.md
- **Developed by:** [Stanislav Shupilkin](https://apify.com/smolevich90) (community)
- **Categories:** Social media, AI
- **Stats:** 1 total users, 0 monthly users, 83.3% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $8.00 / 1,000 audio minute transcribeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## Telegram Voice Transcriber

**Turn the audio half of Telegram into searchable text.** Point this Actor at any public Telegram channel and it returns every voice message, video note (circle) and video as clean, readable text — so the content your keyword alerts, brand monitors and OSINT tooling silently skip finally shows up in your data.

No Telegram account, no phone number, no API keys, no browser. Channel names in, transcripts out. It reads Telegram's own public web preview and transcribes with Whisper Large v3 Turbo, which handles 90+ languages and auto-detects each one.

### What you can do with Telegram transcripts

- **Brand and reputation monitoring** — competitors, agencies and niche communities announce prices, complaints and partnerships in 40-second voice notes that no text scraper can see. Search the transcripts for your brand, your competitors, or your product category.
- **Lead generation** — channels where people post "looking for X" as a voice message are invisible to text search. Transcribe them and filter for buying intent.
- **Sentiment and narrative tracking** — feed transcripts to your LLM or sentiment model with the post date, the channel and the view count already attached.
- **OSINT and news monitoring** — field reports, eyewitness circles and off-the-record commentary get published as audio precisely because audio does not get indexed. Now it does.
- **Content repurposing** — turn a channel's voice diary into blog drafts, newsletters or subtitles.

### Output fields

One dataset row is one piece of media. Every row carries:

| Field | Type | What it is |
|---|---|---|
| `channel` | string | Channel username the message came from |
| `message_id` | integer | Telegram message id |
| `date` | string | When it was posted, ISO 8601 UTC |
| `message_url` | string | Direct `t.me` link to the message |
| `media_type` | string | `voice`, `round_video`, `video`, or `null` for a text-only post |
| `duration_sec` | integer | Length of the audio in seconds |
| `text` | string | The transcript — the whole point |
| `language` | string | Language Whisper detected (`Russian`, `English`, …) |
| `views` | string | View count as Telegram shows it (`4.53K`) |
| `post_text` | string | The caption written next to the media (present when `includePostText` is on) |
| `error` | string | Present **only** on a row whose media could not be transcribed, with the reason — the run keeps going and this row is not charged |

### Example output

```json
{
  "channel": "BuroBobkova",
  "message_id": 785,
  "date": "2026-08-30T12:11:34+00:00",
  "message_url": "https://t.me/BuroBobkova/785",
  "media_type": "round_video",
  "duration_sec": 44,
  "text": "Вообще, в целом, если абстрагироваться от всего того, всей той скетичности, которая меня ждет, этот отпуск будет везде с какой запоминающейся, потому что в таких условиях так далеко я еще не ходил…",
  "language": "Russian",
  "views": "4.53K",
  "post_text": ""
}
```

Export it as JSON, CSV, Excel or XML, or pull it straight from the Apify API into your own pipeline.

### How to transcribe a Telegram channel

1. Paste one or more public channels into **Telegram channels** — `@durov`, `t.me/durov` and `https://t.me/durov` all point at the same channel and all work.
2. Pick what to transcribe under **What to transcribe**: voice messages, video notes (circles), regular videos, or any combination.
3. Optionally set a date range and how deep into the channel history to go.
4. Run it. Results stream into the dataset as they are transcribed, so the first transcripts arrive within seconds.

### Input options

| Field | What it does | Default |
|---|---|---|
| `channels` | Public channels to scan (`@name`, `t.me/name` or a full link) | required |
| `mediaTypes` | Which media to transcribe: `voice`, `round_video`, `video` | all three |
| `maxMessagesPerChannel` | How many recent messages to look at per channel | 50 |
| `dateFrom` / `dateTo` | Only messages inside this date range | no limit |
| `language` | ISO-639-1 hint (`en`, `ru`, `de`, …) | auto-detect |
| `includePostText` | Add the caption written next to the media to every row | true |
| `includeTextOnlyPosts` | Also output regular text posts (free — nothing is transcribed) | false |
| `maxAudioDurationSeconds` | Skip anything longer, so one 4-hour recording can't eat the budget | 3600 |
| `maxPagesPerChannel` | How many preview pages (~16–20 messages each) to page through | 20 |

### Pricing: pay per event

You are charged for results, not for runtime:

| Event | Price |
|---|---|
| `message-transcribed` — one transcribed message | $0.001 |
| `audio-minute` — one minute of audio, rounded up per file | $0.008 |

A 40-second voice message costs $0.009. A hundred of them cost about $0.90. Messages that fail to download, media that exceeds your duration cap, and text-only posts are **not** charged.

If you set a maximum spend on the run, the Actor stops as soon as your limit is reached and finishes successfully with everything transcribed up to that point — you keep the partial dataset and pay nothing extra.

### How it works

- **It reads the public web preview**, `https://t.me/s/<channel>` — the same page Telegram serves to a logged-out browser. No account, no phone number, no Telegram API, no headless browser. That is why only public channels are reachable.
- **Media is downloaded and stripped, not rehosted.** For a video note or a video, the picture track is thrown away with ffmpeg before anything is sent to speech recognition — a 6 MB circle becomes ~130 KB of audio — so runs stay fast and cheap.
- **Long recordings are chunked and stitched.** Anything long is split into 15-minute segments, transcribed in order, and joined back into one continuous transcript, so a two-hour audio post comes back as a single `text`.
- **Recognition is Whisper Large v3 Turbo**, multilingual and self-switching — Russian, Ukrainian, English, German, Spanish, Turkish, Arabic and 80+ more. The detected language is reported in every row. Transient provider errors are retried; a message that still fails is written out with an `error` and skipped, never crashing the run.

### Limits worth knowing before you run it

- **Public channels only.** Private channels, groups and DMs are not reachable without a Telegram account, and this Actor deliberately does not use one.
- **Audio sent as a file attachment cannot be transcribed.** Telegram's public web preview shows those as a name and a size, with no downloadable link. Voice messages, video notes and videos are all fine.
- **Voice messages are rarer in channels than in chats.** Many channels post none at all — keep `round_video` and `video` enabled to capture a channel's full spoken content.
- **A channel that is missing, private or briefly unreachable is skipped, not fatal.** The run logs a warning, moves on to the next channel and finishes successfully with whatever it did collect.
- **Media links on Telegram's CDN are signed and expire**, so everything is downloaded during the same run.

# Actor input Schema

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

Public channels to scan. Use @name, t.me/name or a full https://t.me/name link. Private channels and groups are not supported.

## `mediaTypes` (type: `array`):

voice = voice messages, round\_video = video notes (circles), video = regular videos posted in the channel.

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

How many recent messages to look at in each channel before stopping.

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

Only messages posted on or after this date, e.g. 2026-08-01. Leave empty for no lower bound.

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

Only messages posted on or before this date. Leave empty for no upper bound.

## `language` (type: `string`):

ISO-639-1 code (en, ru, de, ...). Leave empty to auto-detect — the transcriber is multilingual.

## `includePostText` (type: `boolean`):

Add the text written next to the media to every dataset row.

## `includeTextOnlyPosts` (type: `boolean`):

Output rows for regular posts that have no audio. These rows are free — nothing is transcribed.

## `maxAudioDurationSeconds` (type: `integer`):

Safety cap so one 4-hour recording does not eat the whole budget.

## `maxPagesPerChannel` (type: `integer`):

Each page holds roughly 16-20 messages. Raise it to dig deeper into the channel history.

## Actor input object example

```json
{
  "channels": [
    "@BuroBobkova"
  ],
  "mediaTypes": [
    "voice",
    "round_video",
    "video"
  ],
  "maxMessagesPerChannel": 5,
  "includePostText": true,
  "includeTextOnlyPosts": false,
  "maxAudioDurationSeconds": 300,
  "maxPagesPerChannel": 20
}
```

# Actor output Schema

## `transcripts` (type: `string`):

Transcribed messages from the requested Telegram channels.

# 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": [
        "@BuroBobkova"
    ],
    "maxMessagesPerChannel": 5,
    "maxAudioDurationSeconds": 300
};

// Run the Actor and wait for it to finish
const run = await client.actor("smolevich90/telegram-voice-transcriber").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": ["@BuroBobkova"],
    "maxMessagesPerChannel": 5,
    "maxAudioDurationSeconds": 300,
}

# Run the Actor and wait for it to finish
run = client.actor("smolevich90/telegram-voice-transcriber").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "channels": [
    "@BuroBobkova"
  ],
  "maxMessagesPerChannel": 5,
  "maxAudioDurationSeconds": 300
}' |
apify call smolevich90/telegram-voice-transcriber --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,smolevich90/telegram-voice-transcriber"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/nbJ9mxfwZXgQgQfXp/builds/4tdjtNpZmPRRyZxd9/openapi.json
