Pyrogram v1.0#

Asynchronous support#

Welcome to Pyrogram 1.0!#

Since the first release almost three years ago, we’ve made over 3,000 commits by continuously delivering plenty of new features and fixes, which account for more than 300,000 lines of code added, edited or removed. Thousands of developers across the world have shown their appreciation to the project by kind words praising the way Pyrogram is built and performing, by donations or by simply giving a star to the repository.

This really means a lot, and today I’m pleased to announce the next step taken towards what represents over two and a half years worth of Open Source software development and community management efforts.

What’s New#

Pyrogram now fully supports asynchronous handlers and filters by default. This was possible by rewriting the whole framework using asynchronous interfaces down to the TCP core level. The result is concurrent code running in a single OS-level thread allowing for greater performance.

async def my_handler(client, message):
    await message.reply_text("Hello, async world!")

Asynchronous support is entirely backwards-compatible and transparent to users, meaning your existing synchronous code will still be functional. In fact, you are free to mix async and sync handlers and filters as much as you want. Pyrogram will still work concurrently and efficiently regardless of what you choose.

We expect that most projects will migrate to asynchronous handlers and filters for long-running applications such as event-driven bots in order to take advantage of a considerable speed increase. Batch applications without user interactions can still be written using synchronous calls to keep code more concise, but it is entirely your choice.

You can read more about Pyrogram’s async support in the documentation:

Notable Changes#

  • Since Pyrogram is now async natively, all the branches dedicated to the old async variant will be deleted soon, namely asyncio and asyncio-dev. To add Pyrogram in your requirements list, you can now simply use pyrogram instead of a URL.

  • The develop branch will also be removed in favor of the default master branch to keep branching clean. This is due to the fact that the master branch was never found to be of any real use except for keeping track of the latest published release (something that can be done with git tags).

  • Python 3.5 (EOL in less than three weeks) is no longer supported and you need to upgrade to at least Python 3.6.

  • Pyrogram’s TL compiler now generates better code: the types used across the Telegram raw API are now 100% hinted allowing for excellent IDE support (auto-completion, warnings in case of wrong type usages, …).

  • Pyrogram types, filters, handlers and emoji have been moved to their dedicated packages/modules:

    • The Filters and Emoji classes are now turned into modules. Import them this way:

      from pyrogram import filters, emoji

      instead of the old way:

      from pyrogram import Filters, Emoji
    • Pyrogram types and handlers now live in separate packages. Import them this way:

      from pyrogram.types import Message, User, ...
      from pyrogram.handlers import MessageHandler, ...

      instead of the old way:

      from pyrogram import Message, User, MessageHandler
  • idle() is now a function you can import from the main package and can be used right away:

    from pyrogram import idle
  • The package holding the Telegram API raw methods and types has been renamed to a more suitable name. Import it this way:

    from pyrogram.raw import types, functions

    instead of the old way:

    from pyrogram.api import types, functions
  • Filter callbacks now take three arguments (self, client, update) instead of two (self, update). Your functions will therefore need to be defined like this:

    lambda flt, client, update: ...


    def filter_callback(flt, client, update):

    or (async):

    async def filter_callback(flt, client, update):


  • Pyrogram now uses a synced internal clock (synced with Telegram’s server) that’s independent of the local system’s clock.

  • Heavy crypto parts will be executed in a pool of threads for big enough chunks of data. This will prevent the async event loop from blocking for too much time while allowing encryption & decryption tasks running in parallel thanks to TgCrypto’s ability to leverage multiple CPU cores.

  • Examples previously found in GitHub are now accessible at

  • getpass is brought back, allowing to input your password without echoing it when you log-in with your account.

  • A warning message saying “do not edit - changes are lost” has been put inside each of the automatically generated Python files to warn curious developers about the possibility of losing changes to those files in case of re-compilations.

  • Implemented short-circuit evaluation for filters to avoid useless checks in and and or operations.

  • Added support for compiled patterns in filters.regex (contributed by @CyanBook in #468).

  • Updated send_* methods to accept pathlib objects (contributed by @CyanBook in $458).

  • Async filters are partly contributed by @HasibulKabir in #437, extended later on to work in an executor.

  • Added filters.all to filter all updates, useful as default filter to be combined with other optional filters (contributed bu @Princic-1837592 in #464).