Full-featured Telegram client library for Python 3
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Comprehensive message handling including sending, receiving, editing, deleting, forwarding, and reading messages with support for formatting, media, and interactive buttons.
Send text messages with formatting, media attachments, buttons, and various options.
async def send_message(
self,
entity,
message='',
*,
reply_to=None,
parse_mode=(),
link_preview: bool = True,
file=None,
thumb=None,
force_document: bool = False,
clear_draft: bool = False,
buttons=None,
silent: bool = None,
background: bool = None,
supports_streaming: bool = False,
schedule=None,
comment_to=None,
ttl: int = None
) -> Message:
"""
Send a message to an entity (user, chat, or channel).
Parameters:
- entity: Target user, chat, channel, or their username/ID
- message: Text message content
- reply_to: Message ID or Message object to reply to
- parse_mode: Text formatting ('md', 'html', or parser object)
- link_preview: Whether to show link previews
- file: File, photo, document, or media to send
- thumb: Custom thumbnail for documents
- force_document: Send as document instead of photo/video
- clear_draft: Clear the draft after sending
- buttons: Inline or reply keyboard buttons
- silent: Send silently (no notification)
- background: Send in background (for channels)
- supports_streaming: Enable streaming for videos
- schedule: Schedule message for future delivery
- comment_to: Reply to specific message in channel comments
- ttl: Time-to-live for self-destructing media
Returns:
Message: The sent message object
Raises:
- ChatWriteForbiddenError: If cannot write to chat
- MessageTooLongError: If message exceeds limits
- MediaInvalidError: If media is invalid
"""Get messages from chats with various filtering and pagination options.
async def get_messages(
self,
entity,
*args,
**kwargs
) -> TotalList:
"""
Get messages from an entity with all results loaded.
Parameters same as iter_messages().
Returns:
TotalList: List of Message objects with total count
"""
def iter_messages(
self,
entity,
limit: int = 1,
*,
offset_date: datetime = None,
offset_id: int = 0,
max_id: int = 0,
min_id: int = 0,
add_offset: int = 0,
search: str = None,
filter=None,
from_user=None,
batch_size: int = 100,
wait_time: int = None,
ids=None,
reverse: bool = False,
reply_to: int = None,
scheduled: bool = False
):
"""
Iterate through messages in an entity with memory-efficient pagination.
Parameters:
- entity: Chat, channel, or user to get messages from
- limit: Maximum number of messages to retrieve
- offset_date: Start from messages before this date
- offset_id: Start from this message ID
- max_id: Get messages with ID less than this
- min_id: Get messages with ID greater than this
- add_offset: Additional offset for pagination
- search: Search for messages containing this text
- filter: Filter messages by type (InputMessagesFilter)
- from_user: Only messages from this user
- batch_size: Number of messages per API request
- wait_time: Wait time between requests
- ids: Specific message IDs to retrieve
- reverse: Iterate in reverse chronological order
- reply_to: Only messages replying to this message ID
- scheduled: Get scheduled messages instead
Yields:
Message: Individual message objects
"""Edit existing messages with new content, formatting, or media.
async def edit_message(
self,
entity,
message=None,
text: str = None,
*,
parse_mode=(),
link_preview: bool = True,
file=None,
thumb=None,
force_document: bool = False,
buttons=None,
schedule=None
) -> Message:
"""
Edit an existing message's content or media.
Parameters:
- entity: Chat where the message is located
- message: Message ID or Message object to edit
- text: New text content (None to keep current)
- parse_mode: Text formatting ('md', 'html', or parser object)
- link_preview: Whether to show link previews
- file: New file/media to replace current media
- thumb: New thumbnail for documents
- force_document: Send new media as document
- buttons: New button layout
- schedule: Reschedule the message
Returns:
Message: The edited message object
Raises:
- MessageNotModifiedError: If no changes made
- MessageEditTimeExpiredError: If edit window expired
- MessageAuthorRequiredError: If not message author
"""Delete messages from chats with options for revocation.
async def delete_messages(
self,
entity,
message_ids,
*,
revoke: bool = True
) -> List[types.messages.AffectedMessages]:
"""
Delete messages from a chat.
Parameters:
- entity: Chat containing the messages
- message_ids: List of message IDs or Message objects to delete
- revoke: Delete for all participants (vs. just yourself)
Returns:
List of AffectedMessages objects with deletion results
Raises:
- MessageDeleteForbiddenError: If cannot delete messages
- MessageIdInvalidError: If message ID doesn't exist
"""Forward messages between chats with various options.
async def forward_messages(
self,
entity,
messages,
from_peer=None,
*,
background: bool = None,
with_my_score: bool = None,
silent: bool = None,
as_album: bool = None,
schedule=None,
noforwards: bool = None,
drop_author: bool = None,
drop_media_captions: bool = None
) -> List[Message]:
"""
Forward messages to another chat.
Parameters:
- entity: Target chat to forward to
- messages: Message IDs or Message objects to forward
- from_peer: Source chat (auto-detected if not provided)
- background: Forward in background (channels only)
- with_my_score: Include sender's game score
- silent: Forward silently (no notification)
- as_album: Group messages as album
- schedule: Schedule forwarded messages
- noforwards: Prevent further forwarding
- drop_author: Don't show original author
- drop_media_captions: Remove media captions
Returns:
List[Message]: The forwarded message objects
"""Mark messages as read and manage read status.
async def send_read_acknowledge(
self,
entity,
message=None,
*,
max_id: int = None,
clear_mentions: bool = False
) -> bool:
"""
Mark messages as read in a chat.
Parameters:
- entity: Chat to mark messages as read
- message: Specific message to mark as read (marks all up to this)
- max_id: Mark all messages up to this ID as read
- clear_mentions: Also clear mention notifications
Returns:
bool: True if read status updated successfully
"""Pin and unpin messages in chats.
async def pin_message(
self,
entity,
message=None,
*,
notify: bool = False,
pm_oneside: bool = False
) -> types.Updates:
"""
Pin a message in a chat.
Parameters:
- entity: Chat to pin message in
- message: Message ID or Message object to pin
- notify: Send notification about pinned message
- pm_oneside: Pin only for yourself (private chats)
Returns:
Updates object with pin result
Raises:
- ChatAdminRequiredError: If admin rights required
- MessageIdInvalidError: If message doesn't exist
"""
async def unpin_message(
self,
entity,
message=None,
*,
notify: bool = False
) -> types.Updates:
"""
Unpin a message or all messages in a chat.
Parameters:
- entity: Chat to unpin message in
- message: Specific message to unpin (None for all)
- notify: Send notification about unpinned message
Returns:
Updates object with unpin result
"""Control text formatting and parsing modes.
@property
def parse_mode(self) -> str:
"""Get current parse mode ('md', 'html', or None)."""
@parse_mode.setter
def parse_mode(self, mode: str):
"""
Set default parse mode for messages.
Parameters:
- mode: 'md' for Markdown, 'html' for HTML, None for plain text
"""import asyncio
from telethon import TelegramClient
async def send_basic_messages():
client = TelegramClient('session', api_id, api_hash)
await client.start()
# Send simple text message
await client.send_message('username', 'Hello, World!')
# Send with formatting
await client.send_message(
'username',
'**Bold text** and *italic text*',
parse_mode='md'
)
# Send with HTML formatting
await client.send_message(
'username',
'<b>Bold</b> and <i>italic</i> text',
parse_mode='html'
)
await client.disconnect()
asyncio.run(send_basic_messages())from telethon import Button
from datetime import datetime, timedelta
async def advanced_messaging():
client = TelegramClient('session', api_id, api_hash)
await client.start()
# Send message with buttons
await client.send_message(
'username',
'Choose an option:',
buttons=[
[Button.inline('Option 1', b'opt1')],
[Button.inline('Option 2', b'opt2')],
[Button.url('Visit Website', 'https://example.com')]
]
)
# Send scheduled message (1 hour from now)
schedule_time = datetime.now() + timedelta(hours=1)
await client.send_message(
'username',
'This message was scheduled!',
schedule=schedule_time
)
# Send silent message
await client.send_message(
'username',
'This won\'t notify the user',
silent=True
)
# Reply to a message
async for message in client.iter_messages('username', limit=1):
await client.send_message(
'username',
'This is a reply!',
reply_to=message.id
)
break
await client.disconnect()async def retrieve_messages():
client = TelegramClient('session', api_id, api_hash)
await client.start()
chat = 'username'
# Get recent messages
messages = await client.get_messages(chat, limit=10)
for msg in messages:
print(f"{msg.sender.first_name}: {msg.text}")
# Search for specific text
async for message in client.iter_messages(chat, search='hello'):
print(f"Found: {message.text}")
# Get messages from specific user
async for message in client.iter_messages(chat, from_user='specific_user'):
print(f"From specific user: {message.text}")
# Get media messages only
from telethon.tl.types import InputMessagesFilterPhotos
async for message in client.iter_messages(chat, filter=InputMessagesFilterPhotos):
print(f"Photo message: {message.id}")
await client.disconnect()async def manage_messages():
client = TelegramClient('session', api_id, api_hash)
await client.start()
chat = 'username'
# Send a message
message = await client.send_message(chat, 'Original message')
# Edit the message
await client.edit_message(
chat,
message.id,
'Edited message with **formatting**',
parse_mode='md'
)
# Pin the message
await client.pin_message(chat, message, notify=True)
# Forward to another chat
await client.forward_messages('another_chat', message)
# Mark as read
await client.send_read_acknowledge(chat, message)
# Delete the message (after 5 seconds)
await asyncio.sleep(5)
await client.delete_messages(chat, [message.id])
await client.disconnect()from typing import Union, List, Optional, Any
from datetime import datetime
from telethon.tl import types
from telethon import custom
EntityLike = Union[int, str, types.User, types.Chat, types.Channel]
MessageLike = Union[int, types.Message, custom.Message]
ButtonLike = Union[Button, List[Button], List[List[Button]]]
FileLike = Union[str, bytes, types.Document, types.Photo]
ParseMode = Union[str, object, None]
class Message:
"""Enhanced message object with utility methods"""
id: int
text: str
date: datetime
sender: types.User
chat: Union[types.User, types.Chat, types.Channel]
media: Optional[Any]
reply_to_msg_id: Optional[int]
class TotalList(List):
"""List with total count attribute"""
total: intInstall with Tessl CLI
npx tessl i tessl/pypi-telethon