# Telegram Lead Scraper (`maximedupre/telegram-lead-scraper`) Actor

Extract published email addresses, phone numbers, websites, and Telegram handles from public Telegram content. Each lead keeps its normalized value, original form, source link, and confidence.

- **URL**: https://apify.com/maximedupre/telegram-lead-scraper.md
- **Developed by:** [Maxime Dupré](https://apify.com/maximedupre) (community)
- **Categories:** Lead generation, Social media, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$3.60 / 1,000 lead details

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### 🎯 Turn public Telegram content into lead rows

Sales teams, lead researchers, and developers can submit public Telegram targets and get structured lead rows for published email addresses, phone numbers, websites, and Telegram handles. Each row keeps a normalized value, its original published form, source details, and confidence so you can review where the lead came from. The Actor reads public descriptions and posts only. It does not guess contact details or look up private data.

- Build a contact list from public Telegram targets with **[Telegram lead generation](https://apify.com/maximedupre/telegram-lead-scraper/examples/telegram-lead-generation)**.
- Collect published phone numbers with **[Telegram phone number scraper](https://apify.com/maximedupre/telegram-lead-scraper/examples/telegram-phone-number-scraper)**.
- Find published email addresses with **[Telegram email scraper](https://apify.com/maximedupre/telegram-lead-scraper/examples/telegram-email-scraper)**.
- Review contact details from public groups with **[Telegram group scraper](https://apify.com/maximedupre/telegram-lead-scraper/examples/telegram-group-scraper)**.
- Extract source-linked lead rows from public Telegram content with **[Telegram lead scraper](https://apify.com/maximedupre/telegram-lead-scraper/examples/telegram-lead-scraper)**.

#### 📦 Review normalized Telegram lead rows

Each saved row contains one distinct published contact detail for its Telegram source. `lead.normalizedValue` helps compare values, while `lead.originalValue` keeps the form shown by Telegram. Channel fields add identity and audience context. Source fields point to the description or post that supplied the detail when available.

If the same detail appears again for the same source, the Actor keeps the first eligible saved match and ignores later matches. The saved row and its source fields describe only that first match.

#### ▶️ Scan targets and open the dataset

1. In **Input**, choose whether your targets are public channels or public groups.
2. Add one or more public Telegram URLs or `@handles`, keeping every value the same type as your choice.
3. Start the Actor and open the lead rows from **Output**.

Only public content available to the Actor is used. A detail that was not published is not guessed.

#### ⚙️ Input

Choose the target type, then add one or more non-empty public Telegram targets. Both fields are required.

**Input fields**

| Field | Type | What it does |
| --- | --- | --- |
| `targetType` | string | Chooses `channel` or `group` for the submitted targets. |
| `targets` | array of strings | Lists one or more public Telegram channel or group URLs or `@handles`. Keep every entry the same type as `targetType`. |
| `targets[]` | string | One non-empty public Telegram URL or `@handle` to scan. |

**Input example**

This example is copied from the public input of a successful current-beta default-input run:

```json
{
  "targetType": "channel",
  "targets": [
    "https://t.me/trucallerbot"
  ]
}
```

#### 🧾 Output

The Output tab exposes `defaultDatasetItems`, a link to the default dataset. Each saved dataset item uses one shape. Optional fields appear when Telegram makes the related public value available.

**Output link**

| Field | Type | What it does |
| --- | --- | --- |
| `defaultDatasetItems` | string | Opens the extracted Telegram lead rows in the default dataset. |

**Dataset row fields**

| Field | Type | What it does |
| --- | --- | --- |
| `lead` | object | The published contact detail found in the source. |
| `lead.type` | string | The detail kind: `email`, `phone`, `website`, or `telegramHandle`. |
| `lead.normalizedValue` | string | The normalized detail used to identify the distinct lead. |
| `lead.originalValue` | string | The detail in the form published by Telegram. |
| `lead.confidence` | string | The extraction confidence for the published detail. |
| `lead.contactIntent` | string, optional | Nearby public text that shows the purpose of the detail, when clear. |
| `channel` | object | The public Telegram source that published the detail. |
| `channel.title` | string | The public title of the channel or group. |
| `channel.url` | string (URL) | The public URL of the channel or group. |
| `channel.type` | string | The source type: `channel` or `group`. |
| `channel.handle` | string, optional | The public Telegram handle, when available. |
| `channel.audienceSize` | integer, optional | The public subscriber or member count, when available. |
| `channel.audienceSizeExact` | boolean, optional | Says whether the public audience count is exact. |
| `source` | object | The public description or post that supplied the detail. |
| `source.type` | string | The source kind: `channelDescription` or `post`. |
| `source.url` | string (URL) | The public URL of the description or post. |
| `source.messageId` | integer, optional | The public message identifier when the source is a post. |
| `source.publishedAt` | date-time string, optional | The publication date and time of a post source. |
| `source.text` | string, optional | The public post text that gives context for the detail. |
| `source.mediaUrls` | array of strings, optional | Public URLs for media attached to the post. |
| `source.viewCount` | integer, optional | The public view count for the post. |
| `source.reactionCount` | integer, optional | The public total reaction count for the post. |
| `source.reactions` | array of objects, optional | The public count for each reaction type. |
| `source.reactions[].emoji` | string | The public reaction or emoji name. |
| `source.reactions[].count` | integer | The public count for that reaction type. |
| `source.forwardedChannel` | object, optional | The public channel named as the origin of a forwarded post. |
| `source.forwardedChannel.handle` | string | The public handle of the forwarded channel. |
| `source.forwardedChannel.url` | string (URL), optional | The public URL of the forwarded channel. |
| `source.forwardedChannel.title` | string, optional | The public title of the forwarded channel. |

**Genuine current-beta row**

This complete row comes from a successful current-beta run. It shows a Telegram handle found in a channel description.

```json
{
  "lead": {
    "type": "telegramHandle",
    "normalizedValue": "@truecallerr0bot",
    "originalValue": "@TruecallerR0Bot",
    "confidence": "high"
  },
  "channel": {
    "title": "TrueCallerBot",
    "url": "https://t.me/trucallerbot",
    "type": "channel",
    "handle": "@trucallerbot",
    "audienceSize": 1832714,
    "audienceSizeExact": true
  },
  "source": {
    "type": "channelDescription",
    "url": "https://t.me/trucallerbot"
  }
}
```

#### 💳 Pricing

Pricing is pay per event. The primary event is **Lead detail** at `$0.0036` for each distinct email, phone number, website, or Telegram handle saved to the dataset.

The event is charged only when that lead detail is saved. Empty discovery creates no lead-detail event, and repeated mentions do not create another saved detail for the same source.

**Buyer-facing event**

| Event | What it covers | Price |
| --- | --- | --- |
| Lead detail | One distinct published email, phone number, website, or Telegram handle saved to the dataset. | `$0.0036` |

#### 🔌 Integrations

The Actor runs in Apify. Use the Input panel to submit targets, then open the default dataset from Output for review or API workflows.

See the walkthrough:

https://www.youtube.com/watch?v=bNACk1\_S\_6w\&list=PLObrtcm1Kw6MUrlLNDbK9QRg8VDJg0gOW\&index=4

#### ❓ FAQ

##### Does the Actor look up private contact details?

No. It reads contact details that public Telegram content publishes. It does not guess details or use a private-data lookup.

##### What happens when a detail appears more than once?

The Actor saves the first eligible occurrence of a distinct detail for the source and ignores later matches. The row shows evidence from that first saved match only.

##### Does a high confidence value verify a contact?

No. Confidence describes the extraction evidence. It does not prove that an email address or phone number still works or belongs to a specific person.

##### Why can source fields be missing?

Telegram does not expose every public field for every description or post. For example, a description source has no post message ID or publication date, and optional media or reaction data may not be available.

##### What does the group option do?

The input includes `group` as a target type. The Actor uses only the public content available for the submitted target, so results depend on what Telegram exposes.

##### How much Telegram history does a run cover?

The Actor returns the public history that Telegram makes available for the submitted targets. It does not promise an unlimited or guaranteed-complete archive.

##### Why did a target return no lead row?

The target may not have a published email, phone number, website, or Telegram handle in the public content available to the Actor. A missing row is not replaced with a guess.

##### Can I use the collected details for outreach?

You are responsible for using public contact details lawfully, following privacy and marketing rules, and honoring opt-outs. This Actor does not verify deliverability or identity.

### 📝 Changelog

**v0.0** (18-09-2026)

- Initial release.

### 🆘 Support

For issues, questions, or feature requests, [file a ticket](https://console.apify.com/actors/maximedupre~telegram-lead-scraper/issues) and I'll fix or implement it in less than 24h 🫡

### 🔗 Related Actors

- [Telegram Channel Scraper](https://apify.com/maximedupre/telegram-channels-scraper) helps you find and enrich public channel targets before extracting lead details.
- [Telegram Info Scraper](https://apify.com/maximedupre/telegram-info-scraper) looks up public profile and audience details for known Telegram usernames and links.
- [Website Email Scraper](https://apify.com/maximedupre/website-emails-scraper) extracts public email addresses from websites linked in your Telegram lead rows.
- [Telegram Lead Extractor — Emails & Contacts](https://apify.com/apt_marble/telegram-lead-extractor) provides another workflow for extracting published Telegram contact details.
- [Telegram Channels Scraper: Messages, Contacts & Leads](https://apify.com/khadinakbar/telegram-channel-scraper) helps collect broader public channel messages and contact fields.

**Made with ❤️ by Maxime Dupré**

# Actor input Schema

## `targetType` (type: `string`):

Choose whether your targets are public Telegram channels or public Telegram groups.

## `targets` (type: `array`):

Enter one or more public Telegram channel or group URLs or @handles. Keep all entries the same type as the choice above. The Actor checks their public descriptions and posts for published contact details.

## Actor input object example

```json
{
  "targetType": "channel",
  "targets": [
    "https://t.me/telegram"
  ]
}
```

# Actor output Schema

## `defaultDatasetItems` (type: `string`):

Open the extracted Telegram leads.

# 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 = {
    "targetType": "channel",
    "targets": [
        "https://t.me/telegram"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("maximedupre/telegram-lead-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 = {
    "targetType": "channel",
    "targets": ["https://t.me/telegram"],
}

# Run the Actor and wait for it to finish
run = client.actor("maximedupre/telegram-lead-scraper").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 '{
  "targetType": "channel",
  "targets": [
    "https://t.me/telegram"
  ]
}' |
apify call maximedupre/telegram-lead-scraper --silent --output-dataset

```

## MCP server setup

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

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/ZcEYwHlMX7qK7Q2Up/builds/CBoVxHdgF62jWVSnM/openapi.json
