Updates are an important topic in a messaging platform like Telegram. After all, you want to be notified when a new message arrives, when a member joins, when someone starts typing, etc. For that, you can use events.


It is strongly advised to enable logging when working with events, since exceptions in event handlers are hidden by default. Please add the following snippet to the very top of your file:

import logging
logging.basicConfig(format='[%(levelname) 5s/%(asctime)s] %(name)s: %(message)s',

Getting Started

Let’s start things with an example to automate replies:

from telethon import TelegramClient, events

client = TelegramClient('anon', api_id, api_hash)

async def my_event_handler(event):
    if 'hello' in event.raw_text:
        await event.reply('hi!')


This code isn’t much, but there might be some things unclear. Let’s break it down:

from telethon import TelegramClient, events

client = TelegramClient('anon', api_id, api_hash)

This is normal creation (of course, pass session name, API ID and hash). Nothing we don’t know already.


This Python decorator will attach itself to the my_event_handler definition, and basically means that on a NewMessage event, the callback function you’re about to define will be called:

async def my_event_handler(event):
    if 'hello' in event.raw_text:
        await event.reply('hi!')

If a NewMessage event occurs, and 'hello' is in the text of the message, we reply() to the event with a 'hi!' message.


Event handlers must be async def. After all, Telethon is an asynchronous library based on asyncio, which is a safer and often faster approach to threads.

You must await all method calls that use network requests, which is most of them.

More Examples

Replying to messages with hello is fun, but, can we do more?

@client.on(events.NewMessage(outgoing=True, pattern=r'\.save'))
async def handler(event):
    if event.is_reply:
        replied = await event.get_reply_message()
        sender = replied.sender
        await client.download_profile_photo(sender)
        await event.respond('Saved your photo {}'.format(sender.username))

We could also get replies. This event filters outgoing messages (only those that we send will trigger the method), then we filter by the regex r'\.save', which will match messages starting with ".save".

Inside the method, we check whether the event is replying to another message or not. If it is, we get the reply message and the sender of that message, and download their profile photo.

Let’s delete messages which contain “heck”. We don’t allow swearing here.

async def handler(event):
    await event.delete()

With the r'(?i).*heck' regex, we match case-insensitive “heck” anywhere in the message. Regex is very powerful and you can learn more at https://regexone.com/.

So far, we have only seen the NewMessage, but there are many more which will be covered later. This is only a small introduction to updates.


When you need the user or chat where an event occurred, you must use the following methods:

async def handler(event):
    # Good
    chat = await event.get_chat()
    sender = await event.get_sender()
    chat_id = event.chat_id
    sender_id = event.sender_id

    # BAD. Don't do this
    chat = event.chat
    sender = event.sender
    chat_id = event.chat.id
    sender_id = event.sender.id

Events are like messages, but don’t have all the information a message has! When you manually get a message, it will have all the information it needs. When you receive an update about a message, it won’t have all the information, so you have to use the methods, not the properties.

Make sure you understand the code seen here before continuing! As a rule of thumb, remember that new message events behave just like message objects, so you can do with them everything you can do with a message object.