Unofficial Telegram Ads reporting API service, client, and parser toolkit for Node.js and TypeScript.
This project reads the CSV, TSV, and account HTML surfaces exposed by
https://ads.telegram.org, normalizes them into typed JavaScript objects, and
can run as a standalone HTTP API service. It is not an official Telegram
project and does not implement ad mutation or campaign management.
npm install tg-ads-kitFor a standalone checkout:
git clone https://github.com/Lotfree618/tg-ads-kit.git tg-ads-kit
cd tg-ads-kit
npm ci
cp .env.example .envThe server and CLI load .env automatically.
- Node.js 20 or newer.
- A valid
ads.telegram.orgbrowser Cookie header. - A Telegram Ads account token from the account report URLs.
- A local API bearer token when running the HTTP service.
Set environment variables:
export TELEGRAM_ADS_COOKIE='stel_adowner=...; stel_ssid=...; stel_token=...'
export TG_ADS_API_TOKEN='replace-with-a-long-random-token'Run in development:
npm run devBuild and run the compiled server:
npm run build
npm startCall the API:
curl "http://127.0.0.1:3000/v1/accounts/$TELEGRAM_ADS_ACCOUNT_TOKEN/daily" \
-H "Authorization: Bearer $TG_ADS_API_TOKEN"Main routes:
GET /healthGET /v1/accounts/:accountToken/dailyGET /v1/accounts/:accountToken/hourlyGET /v1/accounts/:accountToken/stats-pageGET /v1/accounts/:accountToken/monthly?month=YYYYMMGET /v1/session/adsGET /v1/session/account/budget?offset=0&limit=100GET /v1/session/account/editGET /v1/accounts/:accountToken/ads/:adId/detailGET /v1/accounts/:accountToken/ads/:adId/stats-pageGET /v1/accounts/:accountToken/ads/:adId/share-stats-pageGET /v1/accounts/:accountToken/ads/:adId/budget-pageGET /v1/accounts/:accountToken/ads/:adId/edit/:sectionGET /v1/accounts/:accountToken/ads/:adId/daily?month=YYYYMMGET /v1/accounts/:accountToken/ads/:adId/hourlyGET /v1/accounts/:accountToken/snapshot?month=YYYYMM
See docs/api.md for the API contract.
After npm run build, the CLI is available at dist/cli.js; when installed as
a package it is exposed as tg-ads-kit.
tg-ads-kit account-daily "$TELEGRAM_ADS_ACCOUNT_TOKEN"
tg-ads-kit account-hourly "$TELEGRAM_ADS_ACCOUNT_TOKEN"
tg-ads-kit monthly "$TELEGRAM_ADS_ACCOUNT_TOKEN" 202606
tg-ads-kit session-ads
tg-ads-kit account-budget 0 100
tg-ads-kit account-stats-page "$TELEGRAM_ADS_ACCOUNT_TOKEN"
tg-ads-kit account-edit
tg-ads-kit ad-detail 187
tg-ads-kit ad-stats-page "$TELEGRAM_ADS_ACCOUNT_TOKEN" 187
tg-ads-kit ad-share-stats-page "$TELEGRAM_ADS_ACCOUNT_TOKEN" 187
tg-ads-kit ad-budget-page 187
tg-ads-kit ad-edit-page 187 status
tg-ads-kit ad-daily "$TELEGRAM_ADS_ACCOUNT_TOKEN" 187 202606
tg-ads-kit ad-hourly "$TELEGRAM_ADS_ACCOUNT_TOKEN" 187
tg-ads-kit serveimport { createTelegramAdsClient } from 'tg-ads-kit';
const client = createTelegramAdsClient({
cookie: process.env.TELEGRAM_ADS_COOKIE!,
});
const accountToken = process.env.TELEGRAM_ADS_ACCOUNT_TOKEN!;
const dailyRows = await client.fetchAccountDailyRows(accountToken);
const ads = await client.fetchAccountAds();
const monthlyRows = await client.fetchMonthlyReport(accountToken, '202606');
console.log({ dailyRows, ads, monthlyRows });import {
mergeAccountDailyRows,
parseTelegramAdsDailyBudgetCsv,
parseTelegramAdsDailyStatsCsv,
} from 'tg-ads-kit';
const stats = parseTelegramAdsDailyStatsCsv(statsTsv);
const budget = parseTelegramAdsDailyBudgetCsv(budgetTsv);
const rows = mergeAccountDailyRows(stats, budget);/csv?prefix=account/{accountToken}&period=day/csv?prefix=account/{accountToken}/budget&period=day/csv?prefix=account/{accountToken}&period=5min/csv?prefix=account/{accountToken}/budget&period=5min/reports/account/{accountToken}?month={YYYYMM}/reports/account/{accountToken}/ad/{adId}?month={YYYYMM}/csv?prefix=ad/{accountToken}/{adId}&period=day/csv?prefix=ad/{accountToken}/{adId}&period=5min/csv?prefix=ad/{accountToken}/{adId}/budget&period=5min/accountad metadata table/account/statsaccount stats page links and table rows/account/ad/{adId}ad detail form snapshot/account/ad/{adId}/statsad stats page links and table rows/account/ad/{adId}/stats/shareshared ad stats page links and table rows/account/budgetaccount budget transactions/account/editaccount info form snapshot/account/ad/{adId}/budgetad budget form snapshot/account/ad/{adId}/edit_{cpm|budget|status}edit form snapshots
Money is represented as TON micros, where 1 TON = 1_000_000 micros.
Telegram Ads hourly CSVs are observed as five-minute rows. The parser groups them into hourly rows and returns only complete hours containing 12 five-minute intervals. This is intentional because the current hour can be incomplete.
Account-level hourly rows use the account five-minute CSVs and ad-level hourly rows use the ad five-minute CSVs. Other observed period values that return daily rows are not treated as hourly data.
Use parseTelegramAdsAdFiveMinuteStatsCsv or
parseTelegramAdsAdFiveMinuteBudgetCsv if you need the raw five-minute rows.
The package exposes authenticated Telegram Ads HTML pages as typed read-only
snapshots. This includes form field values from account, ad, budget, and edit
pages. These methods only perform GET requests. They do not submit forms, call
Telegram's internal /api?hash=... endpoint, or mutate campaigns.
The package fails clearly when required columns, dates, numbers, account tokens, or session cookies are invalid. It does not support legacy aliases or silent fallback response shapes.
HTTP failures throw TelegramAdsHttpError. Parser and validation failures throw
TelegramAdsParseError or TelegramAdsValidationError.
Do not commit Telegram Ads cookies or account tokens. Treat the Cookie header as a secret and rotate it if exposed.
MIT