A full-featured Telegram client running entirely in your browser. No server needed β connects directly to Telegram via MTProto WebSocket using teleproto (actively maintained GramJS fork with up-to-date TL layers).
- Download files from Telegram via bot token β no file size limits
- Parallel multi-connection downloads (up to 8 workers for faster speeds)
- Configurable chunk sizes (64 KB β 1 MB) with auto-tuning support
- Receive incoming messages and files from your bot in real-time
- Reply to messages directly from the browser (with reply-to threading)
- Paste any
t.melink to fetch and download files - Conversation view grouped by sender with full chat history
- Photo thumbnails with full-size lightbox viewer
- File download from chat messages (documents, photos, videos)
- IndexedDB persistence β conversations and files survive page refresh
- Reconstructs file references from stored IDs for download after refresh
- Auto-reconnect on internet loss/restore with connection health monitoring
- Login with phone number β full Telegram user session in the browser
- 2FA support β two-factor authentication with resume-after-refresh
- Multi-account β up to 10 accounts with account switcher and per-account session isolation
- Browse all chats β private, groups, channels, bots with unread counts
- Saved Messages β your self-chat shows as "Saved Messages"
- Search & filter β find chats by name, @username, or Telegram ID; filter by type (private/bot/group/channel)
- Send & receive messages β real-time with new message listener
- Reply threading β reply to specific messages with quote preview
- Photo thumbnails β inline previews with full-size lightbox and download
- Video & audio β inline player with parallel download, video notes, voice messages
- File downloads β any file type with download queue system
- Download queue β sequential processing with progress, cancel, and retry per item
- Parallel downloads β multi-connection parallel chunk downloads for large files
- Stealth mode β read messages without sending read receipts (double ticks)
- Auto-load photos β configurable thumbnail auto-download in chats
- Infinite scroll β load older messages on scroll-up
- Browser notifications β optional alerts for new messages when tab is inactive
- UI state persistence β restores open chat, active filter on page reload
- Bot mode: Parallel workers (1β8), chunk size (64 KB β 1 MB), stealth mode
- User mode: Stealth mode, auto-load photos, notifications, send with Enter/Ctrl+Enter, font size
- Shared: Cloudflare Proxy toggle with custom worker domain (synced across both modes)
- Reset to defaults option for each mode
- Fork this repo
- Go to Cloudflare Pages β Create a project β Connect your fork
- Build settings:
- Build command:
npm run build - Output directory:
dist
- Build command:
- Deploy!
git clone https://github.com/CloudflareHackers/TGCFWorkersDLBot.git
cd TGCFWorkersDLBot
npm install
npm run devOpen http://localhost:3000
| Command | Description |
|---|---|
npm run dev |
Start Vite dev server on port 3000 |
npm run build |
Production build to dist/ |
npm run preview |
Preview the production build locally |
npm run deploy |
Build and deploy to Cloudflare Pages via Wrangler |
If Telegram WebSocket connections are blocked in your region, deploy the TG-WS-API proxy:
This deploys a Cloudflare Worker with Durable Objects that proxies WebSocket connections to Telegram servers. Works on the free plan.
git clone https://github.com/CloudflareHackers/TG-WS-API.git
cd TG-WS-API
npm install
npx wrangler deploy- Open Settings in the web app (Bot or User mode)
- Enable π Cloudflare Proxy
- Enter your worker domain:
tg-ws-api.your-account.workers.dev - Save β all Telegram connections now route through your proxy
The app includes a WebSocket Proxy Hook (src/proxy-hook.js) that intercepts all WebSocket connections globally:
Without proxy: Browser β wss://venus.web.telegram.org/apiws
With proxy: Browser β wss://your-worker.workers.dev/venus.web.telegram.org/apiws
The hook is loaded before teleproto and overrides window.WebSocket to transparently rewrite Telegram WebSocket URLs. It reads proxy settings directly from localStorage to avoid circular imports.
The project also includes a Cloudflare Pages Function (functions/api/[[path]].js) that can serve as a same-origin proxy fallback. It validates Telegram domains and supports both WebSocket upgrades (via Durable Objects) and regular HTTP proxying.
The proxy works on the free Cloudflare plan by default (SQLite-backed Durable Objects).
For heavy usage, upgrade to the Workers Paid plan ($5/month).
Paid plan benefits: 10M+ requests/month, 1M+ DO operations, global low-latency, no daily limits, detailed analytics.
The app comes pre-filled with Telegram Web's public API credentials:
- API ID:
1025907 - API Hash:
452b0359b988148995f22ff0f4229750
You can use your own from my.telegram.org β API Development Tools.
Browser (teleproto MTProto)
β WebSocket (direct or via CF Proxy)
Telegram Servers (DC1βDC5)
- No backend server β everything runs client-side in the browser
- Sessions stored in localStorage β never leaves your device
- IndexedDB for conversation history and file metadata persistence
- teleproto for MTProto protocol (maintained fork of GramJS with latest TL layers)
- Vite for bundling with tree-shaking and manual chunking (teleproto in separate chunk)
- Custom browser shims β pure-JS AES-256 (ECB + CTR), zlib inflate, WebSocket transport, localStorage-based sessions
The WebSocket adapter (src/shims/promised-web-sockets.js) maps Telegram DC IPs to WebSocket hostnames:
| DC | Hostname |
|---|---|
| DC1 | pluto.web.telegram.org |
| DC2 | venus.web.telegram.org |
| DC3 | aurora.web.telegram.org |
| DC4 | vesta.web.telegram.org |
| DC5 | flora.web.telegram.org |
The client overrides getDC() to always return WebSocket hostnames instead of raw IPs, which is critical for browser WebSocket compatibility.
βββ index.html # Entry point β loads /src/main.js
βββ package.json # Dependencies: teleproto, buffer, events, util, process
βββ vite.config.js # Vite config with Node.js shim aliases and manual chunking
βββ wrangler.toml # Cloudflare Pages deployment config
β
βββ functions/
β βββ api/
β βββ [[path]].js # CF Pages Function β WebSocket/HTTP proxy for Telegram API
β
βββ src/
βββ main.js # App entry β mode router, bot mode UI, event bindings, state
βββ telegram-client.js # TGDownloader class β bot auth, file fetch, parallel download, messaging
βββ user-client.js # TGUserClient class β user auth, dialogs, messages, multi-account
βββ user-mode.js # User mode UI β chat list, message viewer, download queue, settings
βββ link-parser.js # Telegram link parser (t.me, tg://) and file utility helpers
βββ settings.js # Settings persistence β bot/user/proxy settings in localStorage
βββ db.js # IndexedDB wrapper β conversations, files, persistence
βββ proxy-hook.js # WebSocket proxy interceptor β rewrites Telegram WS URLs
βββ polyfills.js # Browser polyfills for teleproto (Buffer, process, timer stubs)
βββ style.css # Full UI styles β dark theme, cards, modals, media, queue
β
βββ shims/ # Node.js module shims for browser compatibility
βββ browser-session.js # localStorage-based session (replaces teleproto's StoreSession)
βββ promised-web-sockets.js # WebSocket transport (replaces PromisedNetSockets)
βββ crypto.js # Pure-JS AES-256 (ECB/CTR) + Web Crypto API (SHA, PBKDF2)
βββ zlib.js # Zlib inflate shim for GZIPPacked messages
βββ stream.js # Minimal stream shim
βββ assert.js # Minimal assert shim
βββ constants.js # Node.js constants shim
βββ fs.js # No-op filesystem shim
βββ net.js # No-op network shim
βββ os.js # Minimal OS shim
βββ path.js # Minimal path shim
βββ node-localstorage.js # No-op (browser has native localStorage)
βββ socks.js # No-op SOCKS proxy shim
Both Bot and User mode support parallel multi-connection downloads for large files (>1 MB):
- The file is split into chunks (configurable: 64 KB β 1 MB, default 512 KB)
- Multiple DC senders are created (up to 8 connections)
- Each worker downloads a range of chunks via
upload.GetFilewith different offsets - Workers retry with exponential backoff on failure, with automatic DC migration on
FILE_MIGRATE_errors - All chunks are merged in order into the final file
For small files (<1 MB) or when only one connection is available, it falls back to downloadMedia (single-connection).
The BrowserSession class (src/shims/browser-session.js) extends teleproto's MemorySession to persist session data (auth keys, DC info, entities) in localStorage. This enables:
- Fast reconnection without re-authentication
- Session survival across page refreshes
- Per-account session isolation (keyed by
tg_user_0,tg_user_1, etc.)
Since Web Crypto API doesn't support AES-ECB mode (needed by teleproto's IGE encryption layer), the crypto shim (src/shims/crypto.js) includes a pure JavaScript AES-256 implementation with:
- AES-256-ECB: Synchronous block encryption/decryption with full S-box, ShiftRows, MixColumns
- AES-256-CTR: Counter mode built on top of ECB
- SHA-1/256/512: Delegated to Web Crypto API
- PBKDF2: Delegated to Web Crypto API (used for 2FA password hashing)
The app monitors connection health and automatically reconnects:
- Listens for browser
online/offlineevents - Periodic health checks every 30s (via
_sender.isConnected()) - Auto-reconnect on internet restore (5s delay, 30s retry on failure)
- Manual disconnect prevents auto-reconnect (respects user intent)
ensureConnected()with ping verification before operations
The link parser (src/link-parser.js) supports:
| Format | Example |
|---|---|
| Private channel | https://t.me/c/2113604672/730 |
| Public channel/group | https://t.me/channel_name/123 |
| Bot channel | https://t.me/b/bot_name/456 |
tg:// private post |
tg://privatepost?channel=123&msg_id=456 |
tg:// resolve |
tg://resolve?domain=username&post=789 |
Also supports telegram.me and telegram.dog domains.
| Store | Technology | Purpose |
|---|---|---|
| Session & auth keys | localStorage |
MTProto session, DC info, entity cache |
| Bot/User settings | localStorage |
Per-mode preferences, shared proxy config |
| Credentials | localStorage |
API ID, hash, bot token (for auto-reconnect) |
| Account list | localStorage |
Multi-account metadata (phone, name, username) |
| Conversations | IndexedDB | Bot mode message history (200 msgs/conversation max) |
| Incoming files | IndexedDB | File metadata with doc/photo IDs for reconstruction |
| Component | Technology |
|---|---|
| MTProto Client | teleproto (maintained GramJS fork) |
| Build Tool | Vite (ES2020 target) |
| Hosting | Cloudflare Pages |
| Proxy (optional) | Cloudflare Workers + Durable Objects |
| Crypto | Pure-JS AES-256 (ECB/CTR) + Web Crypto API (SHA-256, PBKDF2) |
| Storage | localStorage + IndexedDB |
| Polyfills | buffer, events, process, util (npm) + custom Node.js shims |
- All processing happens in your browser β zero server-side logic
- Credentials and sessions never leave your device
- MTProto encryption is end-to-end between your browser and Telegram servers
- Proxy mode only relays encrypted WebSocket frames (cannot read content)
- No analytics, no tracking, no data collection
- Open source β audit the code yourself
MIT