Telegram B2B Chat Validator
README.md
# Telegram B2B Chat Validator — MCP Server + Apify Actor
**Validate `t.me` links without login, API keys or a Telegram client.** One HTTP request per link to the public `t.me` preview page gives you: alive or dead, group vs channel, member count, and who is online right now. Ships with a **free demo slice of 35 real Russian-speaking B2B chats** for Wildberries/Ozon sellers, wholesale buyers, cargo brokers and IT freelancers.
[](https://modelcontextprotocol.io)
[](https://apify.com)
[](#tests)
[](./LICENSE)
- 🔍 `validate_telegram_links` — batch-check 200 links, get a clean table
- 🧪 `get_demo_chat_sample` — 35 curated RU B2B chats with topics and member counts
- 💾 `get_full_base_offer` — the paid 1,201-chat base with XLSX/CSV export (`TW1-TG`)
No Telegram account, no `api_id`/`api_hash`, no browser automation. If a username exists, `t.me/<name>` renders a public preview; if it was deleted, the same page returns `Telegram: Contact @name` and no counters.
---
## Why this exists
Scraping Telegram groups usually means a burner account, a `Telethon` session and a ban risk. But for **public** chats and channels you do not need any of that: the public preview page already exposes everything a seller needs to decide whether a chat is worth joining — size, type, and whether it is still alive.
That is exactly the job: take a list of links from a spreadsheet, a competitor's post or a marketplace chat list, and turn it into a table with real numbers.
```bash
node src/main.js --links https://t.me/ozon_chat,https://t.me/python,https://t.me/deleted_chat_xyz
```
```json
{
"input": "https://t.me/ozon_chat",
"username": "ozon_chat",
"exists": true,
"chatType": "group",
"title": "OZON | Чат селлеров",
"members": 54428,
"online": 5906,
"checked_at": "2026-11-06T12:00:00.000Z",
"error": null,
"fullBaseUrl": "https://9xj89gzrtw-hue.github.io/tg-chats/"
}
```
---
## Install as an MCP server
### Claude Desktop / Cursor / any stdio MCP client
```json
{
"mcpServers": {
"telegram-b2b-chats": {
"command": "npx",
"args": ["-y", "github:9xj89gzrtw-hue/telegram-b2b-chat-validator-mcp"]
}
}
}
```
Or from a clone:
```bash
git clone https://github.com/9xj89gzrtw-hue/telegram-b2b-chat-validator-mcp.git
cd telegram-b2b-chat-validator-mcp
npm install
node mcp/server.js # speaks MCP over stdio
```
### Tools
| Tool | Arguments | Returns |
|---|---|---|
| `validate_telegram_links` | `links[]`, `minMembers?`, `concurrency?` | per-link `exists`, `chatType`, `members`, `online`, `title`, `about`, `error` |
| `get_demo_chat_sample` | `topic?`, `minMembers?`, `limit?` | up to 35 demo chats: `topic`, `city`, `members`, `link` |
| `get_full_base_offer` | — | price, delivery terms, store + Plati.Market links |
Example prompt:
> Validate these 12 t.me links, drop anything under 5 000 members, and tell me which three are the biggest WB/Ozon seller chats.
---
## Run as an Apify Actor
Input (`INPUT_SCHEMA.json`):
```json
{
"links": ["https://t.me/ozon_chat", "https://t.me/python"],
"includeDemoSample": true,
"demoTopics": ["Маркетплейсы WB/Ozon", "Закупки/Опт"],
"minMembers": 5000,
"includeOffer": true,
"concurrency": 3
}
```
Output: one dataset record per validated link, one per demo chat, plus a single `_type: "offer"` summary record. Every record carries `fullBaseUrl`, so a downstream LLM or spreadsheet can always find the paid base without a second lookup.
Actor folder layout follows the Apify spec:
```
.actor/actor.json # metadata, input, dataset schema
.actor/INPUT_SCHEMA.json
Dockerfile # apify/actor-node:20
src/main.js # Actor entry point
```
Deploy:
```bash
npm install -g apify-cli
apify login
apify push
```
---
## Free vs paid
| | Free (this repo) | Full base (`TW1-TG`) |
|---|---|---|
| Chat list | 35 demo chats | **1 017 verified public chats** |
| Topics | 9 categories | 9 categories, with city |
| Validator | unlimited links | unlimited links, offline page |
| Export | CSV of the current run | **XLSX + CSV**, refreshed dates |
| Price | 0 ₽ | **490 ₽**, one-time, no subscription |
The full base with the Excel export and the offline validator lives here:
- Storefront (free demo + instant checkout): **https://9xj89gzrtw-hue.github.io/tg-chats/**
- Plati.Market card: **https://plati.market/itm/6354600**
After SBP / RU card payment the `TW1-TG-…` key is issued automatically on the order page — no waiting for a seller to come online. The key is signed with ECDSA P-256 and verified in the browser, so activation works offline.
---
## Related free tools (no signup)
- **Table / Telegram → clean CSV/XLSX in one click** — https://9xj89gzrtw-hue.github.io/data-clipper/
- **WB/Ozon 2026 margin calculator** (inside the same studio) — https://9xj89gzrtw-hue.github.io/data-clipper/
- **Userscripts for YouTube/VK audio and table export** — https://9xj89gzrtw-hue.github.io/userscripts/
- **Base wallet revoke scanner + Excel export** — https://9xj89gzrtw-hue.github.io/base-tax-audit/
---
## How the parsing works
1. `normalizeTarget()` accepts `https://t.me/name`, `t.me/s/name`, `@name`, bare `name`, and recognises private invites (`t.me/+hash`) that cannot be checked without joining.
2. `GET https://t.me/<name>` with a plain user agent and `Accept-Language: ru-RU`.
3. `parseTelegramPage()` reads `og:title`, `og:description` and `div.tgme_page_extra` (`54 428 members, 5 906 online` / `9 177 803 subscribers`).
4. A page whose title is exactly `Telegram: Contact @name` is treated as **missing** — that is what Telegram returns for deleted or never-existing usernames.
Rate limits: keep `concurrency` at 3 or lower. `mapLimit()` preserves input order, and a failed request becomes `{ "error": "..." }` instead of aborting the batch.
## Tests
```bash
npm test
```
Nine tests cover link normalisation, invite handling, number parsing (`54 428` / nbsp / thin space), group vs channel vs missing pages, and the demo/offer contracts. HTML fixtures are inline, so tests run offline.
## Keywords
`mcp-server` · `model-context-protocol` · `claude-mcp` · `apify-actor` · `telegram-scraper` · `telegram-chats` · `t.me` · `wildberries` · `ozon` · `b2b-leads` · `marketplace-sellers` · `no-api-key`
## License
MIT — see [LICENSE](./LICENSE).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo recent community issues