merezarezaei / teleproto
Almost-zero-friction Telegram for Laravel & PHP — MTProto 2.0, Bot API, Mini App auth, Passport KYC
Requires
- php: >=8.2
- ext-dom: *
- ext-hash: *
- ext-json: *
- ext-libxml: *
- ext-mbstring: *
- ext-openssl: *
- ext-zlib: *
- illuminate/console: ^10.0|^11.0|^12.0
- illuminate/filesystem: ^10.0|^11.0|^12.0
- illuminate/http: ^10.0|^11.0|^12.0
- illuminate/routing: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
- laravel/prompts: ^0.3
- phpseclib/phpseclib: ^3.0
- vlucas/phpdotenv: ^5.6
Requires (Dev)
- chillerlan/php-qrcode: ^6.0
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^10.0|^11.0
- spaze/phpstan-disallowed-calls: ^4.14
Suggests
- ext-bcmath: Alternative big-integer calculation engine if ext-gmp is not available.
- ext-gmp: Accelerates BigInteger modular arithmetic for Diffie-Hellman and 2FA SRP calculations.
- chillerlan/php-qrcode: Renders scannable terminal QR codes for the QR login flow (teleproto:login --qr).
This package is auto-updated.
Last update: 2026-08-29 01:25:28 UTC
README
Teleproto ⚡
Telegram power with almost zero friction — for PHP & Laravel.
You need to send a message, verify a Mini App, decrypt Passport KYC, run a bot, fetch a file — occasionally, inside a Laravel app that is about something else. You should not have to adopt a Telegram framework to do it.
- One composer package, not a framework. Native MTProto 2.0, Bot API (HTTP), Mini App HMAC auth, Passport KYC decryption, and Storage-backed file streaming — no event loop, no daemon, no IPC.
- Stateless session strings. Auth lives in a portable base64 string (
.envor your DB). No session files, no SQLite, no disk locks. The handshake happened once, ever — it is inside the session string. - Typed errors and AI-shaped docs. Every RPC error resolves to a typed exception carrying Telegram's official error-database hint, and the
skills/directory gives AI agents a per-method reference they can drive the package from.
The friction we remove
| teleproto | MadelineProto | TDLib | |
|---|---|---|---|
| Footprint | One composer package | Full amphp-based framework | Native C++ library + bindings |
| Session model | Stateless string in .env/DB |
Session files on disk | Own local database |
| Daemon / event loop | None — plain blocking calls | amphp event loop | TDLib client process |
| Learning curve | Facade + .env |
Event loop, wrappers, IPC | Auth state machine, build steps |
| Login wizard | php artisan teleproto:login (phone / QR / 2FA / bot) |
Multi-step manual setup | Implement the flows yourself |
| AI-skill docs | Generated per-method reference files | — | — |
If you are building a Telegram client, MadelineProto and TDLib are the right tools. If you need Telegram call X from your Laravel app tonight, that is the gap teleproto fills.
What you can do today
Bot on the HTTP Bot API
use MeRezaRezaei\Teleproto\Facades\TP; TP::bot()->sendMessage('@channel', 'Hello from Teleproto!');
Bot or user over native MTProto 2.0
Binary TCP RPC (Layer 227). Warm calls are a single socket round-trip; file uploads go up to 4 GB.
// Bot over MTProto (auth.importBotAuthorization under the hood): $bot = TP::botMtproto(); $bot->login(); $bot->sendMessage(peer: '@channel', text: 'Bot broadcast over MTProto'); // User account over MTProto: $user = TP::user(); $user->sendMessage('@username', 'Hello from a user account!');
Mini App auth middleware
Cryptographic HMAC-SHA256 verification of Telegram initData, as one route middleware:
// routes/api.php Route::middleware('tg.miniapp')->group(function () { Route::post('/miniapp/me', function (Request $request) { return response()->json($request->attributes->get('telegram_user')); }); });
Passport KYC decryption
use MeRezaRezaei\Teleproto\Passport\PassportDecryptor; $creds = PassportDecryptor::decryptCredentials( encryptedData: $payload['data'], encryptedSecret: $payload['secret'], privateKeyPem: file_get_contents(storage_path('keys/passport_private.pem')), hash: $payload['hash'], ); $firstName = $creds['personal_details']['first_name'];
Stream large files straight from Laravel Storage
512 KB MTProto parts, chunk-by-chunk from any Storage disk (local, s3, minio) — never load the file in memory:
use MeRezaRezaei\Teleproto\Facades\TP; use MeRezaRezaei\Teleproto\Media\StorageMedia; $user = TP::user(); $fileId = random_int(1, PHP_INT_MAX); foreach (StorageMedia::readFromDisk('media/large_video.mp4', disk: 's3') as $part) { $user->call('upload.saveBigFilePart', [ 'file_id' => $fileId, 'file_part' => $part['part_index'], 'file_total_parts' => $part['total_parts'], 'bytes' => $part['bytes'], ]); }
Login wizard: phone / QR / 2FA / bot
php artisan teleproto:login # phone + code, 2FA SRP handled automatically — or pick QR php artisan teleproto:login --qr # scan the terminal QR from Telegram -> Settings -> Devices
Sessions land in .env as TELEGRAM_USER_SESSION / TELEGRAM_BOT_SESSION. After that, TP::user() and TP::botMtproto() take zero parameters.
Typed errors with official hints
Every RPC failure resolves through the packaged catalog of Telegram's official error database (Layer 227) into a typed exception with a doc-backed hint:
use MeRezaRezaei\Teleproto\Exceptions\FloodWaitException; try { TP::user()->sendMessage('@channel', 'hello'); } catch (FloodWaitException $e) { logger()->warning("Flood: retry in {$e->seconds}s — {$e->docHint}"); }
Session strings, not session files
$sessionString = TP::user()->session->exportString(); // Store encrypted in MySQL/PostgreSQL/Redis: $userModel->update(['telegram_session' => Crypt::encryptString($sessionString)]); // Restore anywhere, in one line: $user = TP::fromSession(Crypt::decryptString($userModel->telegram_session));
Zero-friction install
composer require merezarezaei/teleproto
php artisan vendor:publish --tag="teleproto-config"
# Bot API (HTTP) — optional if you only use MTProto TELEGRAM_BOT_TOKEN="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11" # MTProto 2.0 (required for user + bot binary sessions) # Get yours at https://my.telegram.org (API development tools) TELEGRAM_API_ID=12345678 TELEGRAM_API_HASH="your_api_hash_here" # Written automatically by the login wizard: TELEGRAM_USER_SESSION="2:AQAD...:12345678:0" TELEGRAM_BOT_SESSION="2:AQAD...:98765432:0"
Then log in once: php artisan teleproto:login. That is the only setup for MTProto user (and binary-bot) sessions — HTTP Bot API users need nothing but the bot token.
Note: In a Laravel app use
php artisan teleproto:login. The wizard also ships asvendor/bin/teleproto login(in a repo clone:./bin/teleproto login).
Tradeoffs — and why they are deliberate
- Blocking wire, batched where it counts. No Fibers, no event loop:
call()(encrypt → send → read) keeps the engine small and stateless, andcallMany()ships N independent requests in ONE round-trip viamsg_containerbatching — live-measured on production DC4 at 2.3–2.7× vs sequential (docs/scaling.md). - No update-handler framework. Updates arrive as Laravel events (
TelegramUpdateReceived) and through the one-methodUpdateSinkInterfacecontract — your pipeline (Redis Stream, queue, Spatie models) plugs in at that seam. Building opinionated handlers on top is deliberately left to higher layers. - Full schema registry, curated fluent builders. Every schema method is callable today via
call('method.name', [...]); generated fluent builders (Methods::auth()->signIn()->…) are added from a curated list validated against the schema artifacts. - No proxy tunneling yet.
setProxy()accepts config, but connections are currently direct — tracked in the transport layer.
Details and the ranked roadmap: docs/scaling.md · Core design spec.
Going faster
The DH handshake happened once, ever — it is baked into the session string — so a cold start is just connect + salt (~49 ms measured), and a warm call is one socket round-trip (< 5 ms). For N independent calls, callMany() puts them all in one round-trip (N-in-1-RTT, live-measured 2.3–2.7× on production DC4). Three patterns:
- Plain FPM — completely fine for occasional calls per request.
- One queue worker per account — Horizon/queue fan-out is the supported multi-account model.
- Octane — keeps workers (and sockets) warm between requests.
Full scaling guide, Horizon config, and honest load limits: docs/scaling.md.
AI-friendly by design
The skills/telegram-methods/ directory is a generated, per-method reference — parameter tables, return types, every official error with Telegram's own hint, and copy-paste usage:
use MeRezaRezaei\Teleproto\Methods\Methods; $request = Methods::auth()->signIn() ->phoneNumber('+15551234567') ->phoneCodeHash($hash) ->phoneCode($code) ->toRequest(); $result = app(\MeRezaRezaei\Teleproto\Services\TeleprotoClient::class)->dispatch($request);
The same information is indexed for agent crawlers in llms.txt. Both are generated from the packaged schema artifacts — regenerate with php bin/generate-skill-files.php.
Documentation
- Changelog & Release Notes
- Quickstart: Install → First Call
- Docs Index
- User MTProto Client Guide
- Bot API Client Guide
- Telegram Passport KYC Guide
- Scaling: Multiple Accounts & Load Limits
- Core Engine Design Spec
Testing
composer test
Contributing
Please see CONTRIBUTING.md and SECURITY.md for details.
License
Teleproto is open-sourced software licensed under the MIT license.