MadelineProto: a PHP MTProto client that skips the Bot API
Async PHP client API for the telegram MTProto protocol
At a glance
- What is it?
- MadelineProto is an async PHP client for Telegram's MTProto protocol. It logs in with a phone number or a bot token, runs on PHP 8.2+, and ships under AGPL-3.0. Here is what the documentation actually covers, and where the sharp edges are.
- Who is it for?
- Adopt MadelineProto when you need user-account access, secret chats, calls or update handling that the Bot API cannot express, and you are willing to run PHP 8.2+ with the mbstring, xml, json, fileinfo, gmp, openssl, iconv and gd extensions present. Do not adopt it if you only need a plain bot token and a webhook, or if AGPL-3.0 does not fit your distribution plan.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What MadelineProto solves that the Bot API cannot
The Bot API is a restricted view of Telegram. MadelineProto speaks MTProto directly, the same protocol the official apps use, so a script can log in as a phone number or as a bot token without the Bot API layer in between. The README is blunt about the scope: the library "can be used to easily interact with Telegram without the bot API, just like the official apps." That sentence is the whole pitch, and it is also the boundary. If your task is a bot that answers commands in a group, the Bot API is simpler and has fewer moving parts. If your task is reading a user's own dialog list, joining channels, handling secret chats, or driving VoIP, MTProto is the only door, and MadelineProto is a PHP door to it.
The audience follows from that. PHP shops that already run long-lived CLI workers, Laravel or Symfony services with queue workers, and hobbyists who want a userbot without leaving the language they know. The examples directory points the same way: simpleBot.php, tgstories_dl_bot.php, downloadRenameBot, pipesbot, secret_bot.php, libtgvoipbot.php, magnaluna. Those are not toy names. They map to inline bots, file download and rename, secret chats and a Telegram VoIP webradio.
How the async MTProto client is put together
The README states the library is "now fully async" and links to an ASYNC page in the docs. The topics list confirms the runtime underneath: amphp. The repository layout backs this up. There is a src/ directory, a schemas/ directory, and a tools/ directory, and composer.json plus a vendor-bin/ directory for isolated tooling. Several core pieces are published as standalone libraries rather than buried in the main tree: danog/async-orm for an async ORM on AMPHP v3 and fibers, danog/loop for a loop and actor model abstraction, danog/ipc for async IPC, danog/dns-over-https for DNS-over-HTTPS resolution, danog/better-prometheus for metrics, plus danog/telegram-entities, danog/tg-file-decoder and danog/tg-dialog-id for Telegram-specific data handling.
That split is the architecture. A MadelineProto process is not one monolith holding a socket; it is an AMPHP event loop with components that can be reused outside the client. The practical consequence is that your own code has to live inside that loop. Blocking calls stall everything, which is why the async framing matters more than the marketing line suggests. The documentation also describes metrics that can be exposed and visualized with a Grafana dashboard, and a broadcasting page for sending to all users, chats and channels of a bot or userbot. Update handling is documented as a choice rather than a default, with an async event-driven mode listed among the options.
Installing MadelineProto and running a first client
The README's getting-started example is the fastest path. It downloads a single madeline.php file from the phar host if it is not already present, includes it, constructs an API object pointed at a session file, and calls start(). PHP 8.2 or newer is required, and the comment in the example says so directly.
<?php
// PHP 8.2+ is required.
if (!file_exists('madeline.php')) {
copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php');
}
include 'madeline.php';
$MadelineProto = new \danog\MadelineProto\API('session.madeline');
$MadelineProto->start();Running that produces a login prompt on first start, because no session exists yet. The session is written to session.madeline in the working directory, so the next run reuses it. The README notes that if you get an error or nothing at all, the project asks for the error message and the MadelineProto.log file created in the same directory.
From there the example calls getSelf() and logs the result, then branches on whether the account is a bot.
$me = $MadelineProto->getSelf();
$MadelineProto->logger($me);
if (!$me['bot']) {
$MadelineProto->messages->sendMessage(peer: '@stickeroptimizerbot', message: "/start");
$MadelineProto->channels->joinChannel(channel: '@MadelineProto');
}
$MadelineProto->echo('OK, done!');The API surface is the MTProto method namespace, so messages->sendMessage and channels->joinChannel are called with named arguments rather than positional ones. Errors from the API arrive as \danog\MadelineProto\RPCErrorException, which the example catches around importChatInvite. There are two other installation routes in the docs: Composer from an existing project and Composer from scratch. An official Docker image exists for linux/amd64, linux/arm64 and linux/riscv64 at hub.madelineproto.xyz/danog/madelineproto, with separate sections for a CLI bot, databases, web and custom extensions. The requirements page lists the extensions you need: mbstring, xml, json, fileinfo, gmp, openssl, iconv and gd.
Session files, log files and the operational edges
The session file is the thing to think about before deployment. It holds the authorization, and the README example writes it to the working directory next to the script. That is fine on a laptop and awkward in a container that gets replaced. The docs cover databases on Docker, which is the signal that session storage is expected to move somewhere durable in production. Nothing in the README describes a rollback procedure for a corrupted or revoked session, so plan for a re-login path rather than assuming one is documented.
The second edge is the extension list. gmp and gd are not installed by default on every PHP build. If you are on a minimal image, the first run will fail before it reaches Telegram. The third is the async model itself. A fully async client wants a long-running process. Dropping it into a request-response web handler works for small scripts, and the README explicitly invites running the example "in a browser or in a console", but the docs also separate a CLI bot path in Docker and label it recommended. Treat that label as a hint about where the design is aimed.
The fourth edge is the release cadence. The most recent release listed is 8.7.0 from 2026-05-12, preceded by 8.6.5 (Layer 225) on 2026-04-20 and 8.6.4 (Layer 223) on 2026-03-03. Two of those names carry a Layer number, which means the MTProto schema layer moved between them. The default branch is v8 and the last push was on 2026-09-22, so the branch is moving ahead of the tagged releases. If you pin to a tag, you are pinning to a schema layer, and Telegram's server side does not wait for you.
MadelineProto settings, proxies and where it does not fit
The repository ships a .env.example with a small set of keys: MTPROTO_SETTINGS, TEST_USERNAME, TEST_DESTINATION_GROUPS, TEST_SECRET_CHAT and BOT_TOKEN. MTPROTO_SETTINGS is a JSON object, which tells you that connection and client behaviour is configured through a settings structure rather than a long list of environment variables. The docs have a settings page and a proxy page, and the topics list includes proxy, so routing through a proxy is a first-class concern rather than an afterthought. That is consistent with the userbot use case: a user account connecting from a datacenter IP is a different proposition from a bot token.
Where it does not fit is worth stating plainly. If you have a bot token and a webhook, MadelineProto is more machinery than the job needs, and you inherit the extension requirements, the session file and the async runtime for nothing. If your team has no PHP 8.2 runtime and no appetite for AMPHP's model, the learning cost is real. If you need a stable, frozen protocol surface, the Layer churn between 8.6.4 and 8.6.5 is a warning: this client tracks Telegram, and Telegram moves. And if AGPL-3.0 is incompatible with how you distribute your service, the licence question comes before any of the technical ones.
MadelineProto against tdlib-php and the Bot API
The topics list names tdlib and tdlib-php alongside MadelineProto, which is the honest comparison. TDLib is Telegram's own C++ library, with bindings for many languages. The difference in approach is where the protocol logic lives. TDLib owns the database, the update state and the network layer in native code, and your binding calls into it. MadelineProto implements the client in PHP on top of AMPHP, with the session, the update loop and the serialization in your process. That means no native build step and no FFI or extension to compile, at the cost of doing the work in PHP rather than in C++.
The second comparison is the Bot API itself. The Bot API is HTTP, stateless from your side, and rate-limited by Telegram in ways you do not control. MadelineProto is a persistent MTProto connection with a session. The README draws the line explicitly: login with a bot token happens through MTProto, with "no bot API involved". The trade is control against convenience. You get the full method namespace and user-account capabilities; you also get a connection to keep alive, a session to store and a schema layer to track.
Licence and the cost of keeping up
MadelineProto is AGPL-3.0. That is a strong copyleft licence with a network clause: if you run a modified version as a service that users interact with over a network, the licence's terms reach the users of that service. This is not legal advice, and the specifics depend on what you modify and how you deploy. The practical point is that AGPL-3.0 is a different commitment from MIT or Apache-2.0, and it should be checked against your distribution model before the first line of integration code, not after.
The upgrade cost is tied to the Layer. Releases 8.6.4 and 8.6.5 are labelled Layer 223 and Layer 225, so the schema changed twice in roughly six weeks. The changelog file at the repository root is where that is recorded. Because the default branch is v8 and the last push was on 2026-09-22, the branch carries work beyond the newest tagged release, and pinning to a tag means accepting a schema snapshot. The mitigation the project offers is the Docker image, which fixes the runtime and the extensions alongside the library version.
Editorial conclusion
Adopt MadelineProto when you need user-account access, secret chats, calls or update handling that the Bot API cannot express, and you are willing to run PHP 8.2+ with the mbstring, xml, json, fileinfo, gmp, openssl, iconv and gd extensions present. Do not adopt it if you only need a plain bot token and a webhook, or if AGPL-3.0 does not fit your distribution plan. Before writing code, confirm the release you are installing, the Layer it targets, and whether your deployment path is the phar or the official Docker image at hub.madelineproto.xyz/danog/madelineproto.
Frequently asked questions
What protocol does Telegram use, and how does MadelineProto fit in?
Telegram's own apps use MTProto, and MadelineProto is a PHP client for that protocol. The README states it can log in with a phone number or with a bot token through MTProto, with no Bot API involved.
Does MTProto use TCP or UDP, and does that affect MadelineProto?
The documentation does not state which transport MTProto uses. Connection behaviour in MadelineProto is configured through the MTPROTO_SETTINGS key shown in the repository's .env.example, and there is a separate proxy page in the docs.
How do I install MadelineProto and log in?
The README's example copies madeline.php from the phar host, includes it, constructs a danog\MadelineProto\API object with a session file path, and calls start(). PHP 8.2 or newer is required, and the login prompt appears on first start because no session exists yet.
What PHP extensions does MadelineProto need?
The requirements page lists mbstring, xml, json, fileinfo, gmp, openssl, iconv and gd. Missing any of them will stop the client before it reaches Telegram.
Can I run MadelineProto in Docker?
Yes. The documentation describes an official image for linux/amd64, linux/arm64 and linux/riscv64 at hub.madelineproto.xyz/danog/madelineproto, with separate sections for a CLI bot, databases, web and custom extensions. The CLI bot section is labelled recommended.
What licence is MadelineProto released under?
AGPL-3.0, per the repository's LICENSE file and the project's stated licence. That is a network copyleft licence, so the terms apply differently from a permissive licence when you run a modified version as a service.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/danog-madelineproto)