TelegramAccount: управление Telegram-аккаунтом на Python через MTProto
TelegramAccount — асинхронный Python-клиент, который работает от имени обычного аккаунта Telegram по протоколу MTProto (поверх Telethon). Он делает то, чего нет в Bot API: читает историю чатов, получает список участников группы, сам вступает в группы и каналы, создаёт каналы, публикует истории и планирует сообщения. Вход выполняется один раз — телефон, код и при необходимости пароль 2FA, дальше используется строка сессии.
from socialift import TelegramAccountМетодов: 90по версии socialift 1.3.0Обновлено:
Как подключить TelegramAccount и войти в аккаунт?
Сначала получите api_id и api_hash: войдите на my.telegram.org со своим номером Telegram, откройте API development tools и заполните форму. По правилам Telegram сейчас к одному номеру привязывается один api_id. Не храните ключи в коде — используйте переменные окружения TELEGRAM_API_ID и TELEGRAM_API_HASH.
Установка: pip install "socialift[telegram]" — Telethon ставится как дополнительная зависимость (Python 3.11+). Лицензионный ключ берётся из SOCIALIFT_LICENSE_KEY или аргумента license_key= и проверяется при connect(). Конструкция async with TelegramAccount(...) as tg: открывает соединение и закрывает его при выходе из блока.
Вход состоит из трёх шагов: send_code() → sign_in() → sign_in_password(), если в аккаунте включён облачный пароль. Сохраните строку session из результата — в следующий раз TelegramAccount.from_env() прочитает её из TELEGRAM_SESSION, и код не понадобится. Если шаги входа идут в разных HTTP-запросах, передавайте дальше и промежуточную session из send_code(): phone_code_hash действует только внутри этой сессии.
Строка сессии равна паролю: в ней ключ авторизации, дающий полный доступ к аккаунту. Храните её в базе в зашифрованном виде, не пишите в логи и не отдавайте в браузер. При утечке вызовите log_out() или завершите сеанс с другого устройства. Попробовать без кода можно в кабинете: подключите аккаунт в разделе «Ulanishlar» и вызывайте методы в Playground.
import asyncio
import os
from socialift import TelegramAccount
PHONE = "+79001234567"
async def login() -> str:
# Один раз: телефон -> код -> (если включена) пароль 2FA
async with TelegramAccount(
api_id=os.environ["TELEGRAM_API_ID"],
api_hash=os.environ["TELEGRAM_API_HASH"],
) as tg:
sent = await tg.send_code(PHONE)
code = input("Код из Telegram: ")
result = await tg.sign_in(PHONE, code, phone_code_hash=sent["phone_code_hash"])
if result["two_factor_required"]:
result = await tg.sign_in_password(input("Пароль 2FA: "))
return result["session"] # храните зашифрованной -> TELEGRAM_SESSION
async def main() -> None:
# Дальше: TELEGRAM_API_ID, TELEGRAM_API_HASH, TELEGRAM_SESSION
async with TelegramAccount.from_env() as tg:
me = await tg.me()
await tg.send_message("me", f"Привет, {me.first_name}!")
asyncio.run(main()) # первый запуск: print(asyncio.run(login()))Подключение и вход
Создание клиента, вход по телефону, коду и паролю 2FA, строка сессии и активные сеансы.
closeconnectdisconnectexport_sessionfrom_envis_authorizedlog_outreset_sessionsend_codesessionssign_insign_in_password
close
asyncПсевдоним disconnect() — для единообразия с close() в других клиентах SDK.
await tg.close() -> Noneconnect
asyncОткрывает MTProto-соединение и проверяет лицензию, но не проверяет авторизацию аккаунта — при входе соединение нужно ещё до авторизации. async with TelegramAccount(...) вызывает его автоматически.
await tg.connect() -> TelegramAccount- Большинство методов подключаются сами, но некоторые (
raw,export_session,join,create_channel,stats,contacts,resolve) ждут уже открытого соединения — используйтеasync withили заранее вызовитеconnect(). - Повторный вызов на подключённом клиенте безопасен и ничего не делает.
disconnect
asyncЗакрывает соединение; вызывается автоматически при выходе из async with. Сеанс в Telegram не завершается — сохранённая строка сессии продолжает работать.
await tg.disconnect() -> None- Чтобы завершить сеанс и на стороне Telegram, используйте
log_out().
Возвращает текущую сессию строкой StringSession — чтобы в следующий раз подключиться через TelegramAccount(session=...) без кода. Синхронный метод, но требует открытого соединения.
tg.export_session() -> str- В строке адрес дата-центра и ключ авторизации — это полный доступ к аккаунту. Храните зашифрованной, не выводите в логи.
- При утечке:
log_out()илиreset_session()из другой сессии.
from_env
classmethodСоздаёт клиент из переменных окружения: TELEGRAM_API_ID, TELEGRAM_API_HASH и необязательной TELEGRAM_SESSION. Дополнительные аргументы (license_key, proxy, device_model ...) передаются в конструктор.
TelegramAccount.from_env(**kwargs) -> TelegramAccount- Если
TELEGRAM_SESSIONпуста, клиент создаётся без сессии — сначала нужен вход (send_code→sign_in). - Отсутствующий или неположительный
TELEGRAM_API_ID, пустойTELEGRAM_API_HASH—ConfigurationError.
log_out
asyncЗавершает сеанс в Telegram (auth.logOut) и закрывает соединение. После этого сохранённая строка сессии не работает — для повторного подключения снова нужны телефон и код.
await tg.log_out() -> bool- Если нужно только закрыть соединение и сохранить сессию —
disconnect().
await tg.log_out()reset_session
asyncЗавершает сеанс на другом устройстве по hash из sessions() (account.resetAuthorization).
await tg.reset_session(session_id: int) -> Any- Если с входа в текущий сеанс прошло меньше 24 часов, Telegram не даёт завершать другие сеансы (
FRESH_RESET_AUTHORISATION_FORBIDDEN).
await tg.reset_session(session_hash)send_code
asyncШаг 1 входа: запрашивает код подтверждения для номера и возвращает phone_code_hash и промежуточную строку session. Номер указывается в международном формате; пробелы и дефисы удаляются автоматически.
await tg.send_code(phone: str) -> dict- Код может прийти не по SMS, а в приложение Telegram, где аккаунт уже открыт; способ доставки — в поле
typeответа. phone_code_hashдействует только внутри этой сессии: если шаги в разных запросах, продолжайте сTelegramAccount(..., session=sent["session"]).- Если сессия уже авторизована, код не отправляется и возвращается
already_authorized: True.
sent = await tg.send_code("+998901234567")sessions
asyncСписок всех активных сеансов (устройств) аккаунта — account.getAuthorizations. В каждой записи устройство, приложение, время активности и hash.
await tg.sessions() -> Anyhash— идентификатор для завершения сеанса черезreset_session().
sessions = await tg.sessions()sign_in
asyncШаг 2 входа: вход по полученному коду и phone_code_hash. При успехе возвращает authorized: True, постоянную строку session и user (id, username, телефон, имя).
await tg.sign_in(
phone: str,
code: str,
*,
phone_code_hash: Optional[str] = None,
) -> dict- Если в аккаунте включён облачный пароль, исключения нет — возвращается
two_factor_required: True, дальше вызовитеsign_in_password(). - Неверный или просроченный код, недействительный номер или пара
api_id/api_hash—AuthErrorс понятным текстом.
result = await tg.sign_in("+998901234567", code="12345", phone_code_hash=sent["phone_code_hash"])sign_in_password
asyncШаг 3 входа: завершает вход облачным паролем (2FA) и возвращает результат того же вида, что и sign_in().
await tg.sign_in_password(password: str) -> dict- Пароль не передаётся на сервер в открытом виде: Telegram использует протокол SRP, доказательство Telethon вычисляет локально.
- Неверный пароль —
AuthError. Не пишите пароль в логи и не храните его.
result = await tg.sign_in_password("mening-parolim")Профиль и аккаунт
Текущий аккаунт, имя и био, username, фото профиля.
delete_profile_photosmeprofile_photosset_profile_photoset_usernameupdate_profile
Удаляет фото профиля; без photos удаляются все фото аккаунта.
await tg.delete_profile_photos(photos: Optional[Sequence[Any]] = None) -> Any- Чтобы удалить одно фото, передайте его объект из
profile_photos()в списке — вызов без аргументов удаляет все.
me
asyncТекущий аккаунт (User): id, имя, username, телефон. Помогает понять, чья это сессия.
await tg.me() -> Anyme = await tg.me()profile_photos
asyncСписок фото профиля пользователя, группы или канала; по умолчанию ваши, до 20 штук.
await tg.profile_photos(entity: Union[int, str, Any] = 'me', *, limit: int = 20) -> listset_profile_photo
asyncЗагружает и устанавливает новое фото профиля; принимает путь, байты или файловый объект.
await tg.set_profile_photo(file: Any) -> Anyset_username
asyncУстанавливает публичный @username аккаунта; пустая строка его удаляет.
await tg.set_username(username: str) -> Any- Username — 5–32 символа: латиница, цифры и подчёркивание.
- Занятое имя —
USERNAME_OCCUPIED, неверный формат —USERNAME_INVALID; в SDK этоApiError.
update_profile
asyncМеняет имя, фамилию и био (about); непереданные поля не трогаются (account.updateProfile).
await tg.update_profile(
*,
first_name: Optional[str] = None,
last_name: Optional[str] = None,
about: Optional[str] = None,
) -> Any- Длина био ограничена, отдельно для обычных и Premium-аккаунтов (
about_length_limit_*в конфигурации).
Диалоги и сообщения
Список чатов, история, отправка, редактирование, удаление, пересылка, закрепление, реакции, опросы и отложенные сообщения.
actionarchivedelete_dialogdelete_messagesdialogsedit_messageforward_messagesmark_readmessagemessagesmutepin_dialogpin_messagereactscheduledsend_messagesend_pollunmuteunpin_message
action
asyncПоказывает в чате статус «печатает...», «отправляет фото...» и т. п. Значения: typing, cancel, photo, video, record-video, audio, record-audio, document, location, contact, game.
await tg.action(entity: Union[int, str, Any], action: str = 'typing') -> Any- Статус действует 6 секунд; чтобы показывать дольше, повторяйте вызов или используйте
async with tg.client.action(entity, "typing"):.
await tg.action("@durov", "typing")archive
asyncПеремещает диалог в архив (archived=True) или возвращает из архива (archived=False).
await tg.archive(entity: Union[int, str, Any], *, archived: bool = True) -> Anydelete_dialog
asyncУбирает диалог из списка: выходит из канала или супергруппы, из обычной группы — с очисткой истории, в личном чате удаляет историю.
await tg.delete_dialog(entity: Union[int, str, Any], *, revoke: bool = False) -> Anyrevoke=True— история личного чата удаляется и у собеседника; на каналы и супергруппы не влияет.
delete_messages
asyncУдаляет сообщения по ID. revoke=True (по умолчанию) — у всех; False — в личном чате и обычной группе только у вас.
await tg.delete_messages(
entity: Union[int, str, Any],
message_ids: Iterable[int],
*,
revoke: bool = True,
) -> Any- В супергруппах и каналах сообщение всегда удаляется у всех; для чужих сообщений нужно право администратора
delete_messages. - Служебные сообщения удалить нельзя (
MESSAGE_DELETE_FORBIDDEN→PermissionError). - Удаление тоже может быть ограничено по времени (
revoke_time_limit,revoke_pm_time_limit).
await tg.delete_messages("me", [101, 102], revoke=True)dialogs
asyncСписок диалогов — личные чаты, группы и каналы по последней активности. По умолчанию 50; archived=True — только архив, folder — ID папки.
await tg.dialogs(
*,
limit: int = 50,
archived: Optional[bool] = None,
folder: Optional[int] = None,
) -> listlimit=Noneзагружает все, но на большом аккаунте это много запросов и риск флуда — берите нужную часть.- ID архивной папки —
1, остальные чаты в0.
dialogs = await tg.dialogs(limit=50)edit_message
asyncРедактирует текст, медиа или кнопки отправленного сообщения. Как правило, только своего; посты канала — с правом администратора edit_messages.
await tg.edit_message(
entity: Union[int, str, Any],
message_id: int,
text: Optional[str] = None,
*,
file: Optional[Any] = None,
parse_mode: Optional[str] = 'md',
link_preview: bool = True,
buttons: Optional[Any] = None,
) -> Any- Время на редактирование ограничено: для слишком старого сообщения —
MESSAGE_EDIT_TIME_EXPIRED(порог —edit_time_limitв конфигурации). - Если содержимое не изменилось, Telegram вернёт
MESSAGE_NOT_MODIFIED.
await tg.edit_message("me", message_id, "Tahrirlangan matn")forward_messages
asyncПересылает сообщения из from_entity в to_entity (порядок аргументов: куда, ID, откуда). drop_author=True скрывает автора, schedule — отложенная пересылка.
await tg.forward_messages(
to_entity: Union[int, str, Any],
message_ids: Iterable[int],
from_entity: Union[int, str, Any],
*,
silent: bool = False,
drop_author: bool = False,
schedule: Optional[datetime.datetime] = None,
) -> Any- Из защищённого чата с запретом пересылки переслать нельзя —
CHAT_FORWARDS_RESTRICTED. - Число сообщений за один вызов ограничено (
forwarded_count_max).
await tg.forward_messages("me", [42], "@kanal", drop_author=True)mark_read
asyncОтмечает диалог прочитанным; с message — до этого сообщения.
await tg.mark_read(
entity: Union[int, str, Any],
*,
message: Optional[Any] = None,
) -> Anyawait tg.mark_read("@guruh")message
asyncВозвращает одно сообщение по ID; если его нет — None, а не исключение.
await tg.message(entity: Union[int, str, Any], message_id: int) -> Anymsg = await tg.message("@kanal", 42)msg = await tg.message("@kanal", 42)
data = await tg.download(msg)messages
asyncЧитает историю чата — в Bot API такого метода нет. От новых к старым; фильтры search, from_user, filter, min_id/max_id, а ids возвращает конкретные сообщения.
await tg.messages(
entity: Union[int, str, Any],
*,
limit: int = 50,
offset_id: int = 0,
min_id: int = 0,
max_id: int = 0,
search: Optional[str] = None,
from_user: Union[int, str, Any, NoneType] = None,
reverse: bool = False,
ids: Union[int, Sequence[int], NoneType] = None,
filter: Optional[Any] = None,
) -> list- Пагинация: для следующей страницы передайте в
offset_idнаименьшийmessage.idпредыдущей;reverse=True— от старых к новым. - С
idsдлина списка сохраняется — на месте ненайденного сообщенияNone.
history = await tg.messages("@durov", limit=50)mute
asyncОтключает уведомления диалога. until — unix-время в секундах; без него — фактически навсегда.
await tg.mute(
entity: Union[int, str, Any],
*,
until: Union[int, datetime.datetime, NoneType] = None,
) -> Anyuntil=0тоже трактуется как «навсегда» — включить обратно можно черезunmute().
pin_dialog
asyncЗакрепляет диалог вверху списка чатов или открепляет его с pinned=False.
await tg.pin_dialog(entity: Union[int, str, Any], *, pinned: bool = True) -> Any- Число закреплённых диалогов ограничено (для аккаунтов без Premium —
dialogs_pinned_limit_default).
pin_message
asyncЗакрепляет сообщение в чате; по умолчанию без уведомления (notify=False). pm_oneside=True — в личном чате закрепить только у себя.
await tg.pin_message(
entity: Union[int, str, Any],
message_id: int,
*,
notify: bool = False,
pm_oneside: bool = False,
) -> Any- В группах и каналах нужно право закреплять — иначе
CHAT_ADMIN_REQUIREDилиPIN_RESTRICTED.
await tg.pin_message("me", 42, notify=False)react
asyncСтавит реакцию-эмодзи на сообщение; emoji=None снимает реакцию, big=True показывает большую анимацию.
await tg.react(
entity: Union[int, str, Any],
message_id: int,
emoji: Optional[str] = None,
*,
big: bool = False,
) -> Any- Администраторы могут ограничить набор реакций (
available_reactionsвchat_full()); недопустимый эмодзи —REACTION_INVALID.
await tg.react("@guruh", 42, "👍")scheduled
asyncОтложенные, ещё не отправленные сообщения чата — поставленные через send_message(..., schedule=...) или send_file(..., schedule=...).
await tg.scheduled(entity: Union[int, str, Any]) -> Anyscheduled = await tg.scheduled("me")send_message
asyncОтправляет сообщение в личный чат, группу или канал; entity — @username, числовой ID, ссылка t.me/... или "me" (Избранное). Поддерживаются ответ, файл, кнопки, тихая отправка и комментарий к посту канала (comment_to).
await tg.send_message(
entity: Union[int, str, Any],
message: str = '',
*,
reply_to: Optional[int] = None,
parse_mode: Optional[str] = 'md',
link_preview: bool = True,
file: Optional[Any] = None,
silent: bool = False,
schedule: Optional[datetime.datetime] = None,
buttons: Optional[Any] = None,
formatting_entities: Optional[list] = None,
comment_to: Optional[int] = None,
) -> Anyschedule=datetimeставит сообщение в очередь на сервере Telegram, и в нужное время Telegram отправит его сам — ваше приложение может быть выключено.- По умолчанию
parse_mode="md":**,__,~~или[текст](url)в пользовательском тексте превратятся в разметку. Для сырого текста —parse_mode=None. - Массовые непрошеные сообщения — это спам: аккаунты, использующие Telegram API для спама, блокируются навсегда.
await tg.send_message("@mening_guruhim", "Salom!", silent=True)send_poll
asyncОтправляет опрос или викторину (quiz=True): options — варианты ответа, multiple — несколько вариантов, public — видно, кто как голосовал.
await tg.send_poll(
entity: Union[int, str, Any],
question: str,
options: Sequence[str],
*,
multiple: bool = False,
quiz: bool = False,
correct: Optional[int] = None,
public: bool = False,
) -> Any- Для викторины обязателен
correct(индекс правильного ответа с 0) — без него SDK выброситConfigurationError, не отправляя запрос.
await tg.send_poll("@guruh", "Qaysi kun?", ["Dushanba", "Juma"], multiple=False)unmute
asyncСнова включает уведомления диалога.
await tg.unmute(entity: Union[int, str, Any]) -> Anyunpin_message
asyncОткрепляет сообщение; без message_id открепляются все закреплённые сообщения чата.
await tg.unpin_message(
entity: Union[int, str, Any],
message_id: Optional[int] = None,
) -> Anyawait tg.unpin_message("me", 42)Медиа и файлы
Отправка фото, видео, документов и альбомов, скачивание и предварительная загрузка файлов.
downloadsend_albumsend_fileupload
download
asyncСкачивает медиа из сообщения: по умолчанию возвращает bytes; если передать путь в file, пишет на диск и возвращает путь.
await tg.download(message: Any, *, file: Any = <class 'bytes'>) -> Anymsg = await tg.message("@kanal", 42)
data = await tg.download(msg)send_album
asyncОтправляет несколько файлов одним альбомом (media group); поддерживает caption и остальные параметры send_file().
await tg.send_album(
entity: Union[int, str, Any],
files: Sequence[Any],
*,
caption: Optional[str] = None,
**kwargs: Any,
) -> Any- В один альбом Telegram принимает до 10 медиа; если файлов больше, Telethon разбивает их на несколько альбомов по 10.
send_file
asyncОтправляет фото, видео, документ, голосовое или видеосообщение-кружок; file — путь, байты, файловый объект, URL или результат upload(). Поддерживаются caption, reply_to, silent, schedule.
await tg.send_file(
entity: Union[int, str, Any],
file: Any,
*,
caption: Optional[str] = None,
force_document: bool = False,
voice_note: bool = False,
video_note: bool = False,
silent: bool = False,
reply_to: Optional[int] = None,
thumb: Optional[Any] = None,
attributes: Optional[list] = None,
schedule: Optional[datetime.datetime] = None,
parse_mode: Optional[str] = 'md',
) -> Any- Чтобы доставить файл как есть (документом), укажите
force_document=True. voice_note=True— голосовое сообщение,video_note=True— видеосообщение-кружок.
await tg.send_file("me", "photo.jpg", caption="Rasm")upload
asyncЗаранее загружает файл на сервер Telegram и возвращает результат, который затем можно передать в send_file() (filename — отображаемое имя).
await tg.upload(file: Any, *, filename: Optional[str] = None) -> Any- Загруженные части хранятся на сервере временно — от нескольких минут до нескольких часов, поэтому используйте результат сразу.
Истории (Stories)
Публикация, чтение, редактирование и удаление историй. Чтобы публиковать от имени пользователя, нужен Telegram Premium.
can_send_storydelete_storyedit_storysend_storystoriesstory_targets
can_send_story
asyncПроверяет, можно ли опубликовать историю, до самой публикации (stories.canSendStory). При успехе возвращает число свободных «слотов» историй (count); документация Telegram требует этот вызов перед отправкой истории.
await tg.can_send_story(entity: Union[int, str, Any] = 'me') -> Anyentity="me"— от своего имени; если передать канал или супергруппу, проверка будет для них.- Ошибки в терминах SDK:
PREMIUM_ACCOUNT_REQUIRED— у пользователя нет Premium;CHAT_ADMIN_REQUIRED— нет праваpost_storiesв канале (PermissionError);BOOSTS_REQUIRED— каналу не хватает «бустов»;STORIES_TOO_MUCH— превышен лимит активных историй. - Недельный и месячный лимиты (
STORY_SEND_FLOOD_WEEKLY/STORY_SEND_FLOOD_MONTHLY) приходят какRateLimitError, секунды ожидания — вretry_after. - Это не гарантия: если между проверкой и
send_story()состояние изменится (например, историю опубликуют с другого устройства), те же ошибки вернутся уже при публикации.
check = await tg.can_send_story("me")delete_story
asyncУдаляет одну историю или сразу несколько по списку (stories.deleteStories) и возвращает список действительно удалённых ID.
await tg.delete_story(
entity: Union[int, str, Any],
story_id: Union[int, Iterable[int]],
) -> Any- Удаляются и активные, и закреплённые в профиле, и архивные истории; отменить это нельзя.
- Несуществующий ID — не ошибка: он просто не попадёт в список из ответа.
await tg.delete_story("me", [42, 43])edit_story
asyncРедактирует опубликованную историю (stories.editStory): отправляются только переданные поля, остальные не меняются. Подходит, чтобы заменить caption или сузить приватность.
await tg.edit_story(
entity: Union[int, str, Any],
story_id: int,
*,
file: Optional[Any] = None,
caption: Optional[str] = None,
privacy: Union[str, Sequence[Any], NoneType] = None,
allow: Optional[Sequence[Union[int, str, Any]]] = None,
deny: Optional[Sequence[Union[int, str, Any]]] = None,
photo: Optional[bool] = None,
thumb: Optional[Any] = None,
parse_mode: Optional[str] = None,
entities: Optional[list] = None,
media_areas: Optional[list] = None,
) -> Anyprivacyздесь по умолчаниюNone(в отличие отsend_story, где приватность обязательна и равна"everyone"): если её не трогать, текущая приватность истории сохранится.- Если не передать ни одного поля, будет
ConfigurationError— пустое редактирование для Telegram бессмысленный запрос. - С
fileмедиа загружается заново (с тем же лимитом 30 МБ): по документации Telegram атрибуты файла «впаяны» в медиа, иначе их не изменить.
await tg.edit_story("me", 42, caption="Tahrirlangan matn")send_story
asyncПубликует историю (stories.sendStory): entity — от чьего имени ("me" или канал/супергруппа), file — вертикальное фото или видео. В ответе Updates с id новой истории (updateStoryID).
await tg.send_story(
entity: Union[int, str, Any],
file: Any,
*,
caption: Optional[str] = None,
period: Union[int, datetime.timedelta, NoneType] = None,
privacy: Union[str, Sequence[Any], NoneType] = 'everyone',
allow: Optional[Sequence[Union[int, str, Any]]] = None,
deny: Optional[Sequence[Union[int, str, Any]]] = None,
pinned: bool = False,
noforwards: bool = False,
photo: Optional[bool] = None,
thumb: Optional[Any] = None,
parse_mode: Optional[str] = None,
entities: Optional[list] = None,
media_areas: Optional[list] = None,
albums: Optional[Sequence[int]] = None,
) -> Any- Требование Telegram: чтобы публиковать от имени пользователя, на аккаунте должен быть **Telegram Premium** (иначе
PREMIUM_ACCOUNT_REQUIRED); от имени канала — быть админом с правомpost_storiesи иметь достаточно «бустов». Поэтому сначала вызывайтеcan_send_story(entity): ошибка будет видна до загрузки файла, а не после. file— путь, байты, файловый объект или готовыйInputFile; не больше 30 МБ, и этот лимит проверяется локально. Тип определяется по расширению (.jpg/.png— фото, остальное — видео), принудительно — черезphoto=True/False.period— через сколько секунд история уйдёт в архив; принимаются только четыре значения: 21600 (6 часов), 43200 (12 часов), 86400 (24 часа), 172800 (48 часов), можно передатьtimedelta. Без Premium работает только 86400 — остальные Telegram отклоняет. Если не передать, поле не отправляется и Telegram ставит 24 часа.privacy:"everyone"(по умолчанию),"contacts","close_friends"(список ведётся в приложении Telegram) или"selected"— в последнем случаеallowобязателен.deny— список исключений, он добавляется в конец правил («контакты, но не такой-то»).pinned=True— после истечения срока история остаётся в профиле;noforwards=True— запрещает пересылку и сохранение.- Лимит длины
captionберётся из конфига Telegram и числом в документации не задан, поэтому SDK его не проверяет. Безparse_modeтекст уходит без форматирования: форматирование в историях зависит от конфигурации аккаунта и доступно не всем. - Соотношение сторон и длительность Telegram числом не документирует — SDK их не проверяет, а невертикальное медиа в приложениях обрежется неправильно.
await tg.send_story("me", "story.mp4", caption="Salom!", period=86400,
privacy="contacts", pinned=False)stories
asyncВозвращает активные истории пира (stories.getPeerStories): объект stories.PeerStories с элементами StoryItem. Если передать ids=[...], запрашиваются именно эти истории (stories.getStoriesByID).
await tg.stories(
entity: Union[int, str, Any] = 'me',
*,
ids: Union[int, Iterable[int], NoneType] = None,
) -> Any- Часть элементов может прийти как
StoryItemSkipped— Telegram экономит трафик и не отдаёт полные данные; такие истории запрашивайте отдельно черезstories(entity, ids=[...]). - Истёкших историй здесь нет: они в архиве (
stories.getStoriesArchive) или среди закреплённых в профиле (stories.getPinnedStories) — для них используйтеraw().
items = await tg.stories("me")story_targets
asyncВозвращает каналы и супергруппы, от имени которых можно публиковать истории (stories.getChatsToSend). Подходит для списка «от чьего имени публикуем» в интерфейсе.
await tg.story_targets() -> Any- Присутствие в списке ещё не значит «можно публиковать»: бусты и лимиты проверяются в
can_send_story(entity), поэтому вызывайте её всё равно.
targets = await tg.story_targets()Контакты и пользователи
Контакты, блокировка, профиль пользователя и поиск объекта по username или ID.
add_contactblockblockedcommon_chatscontactsdelete_contactentityresolveunblockuser_full
add_contact
asyncДобавляет контакт по номеру телефона (contacts.importContacts). Если номер есть в Telegram, пользователь возвращается в imported и users.
await tg.add_contact(phone: str, first_name: str, *, last_name: str = '') -> Any- Если номер не найден, исключения нет —
importedбудет пустым, проверяйте результат. retry_contacts— контакты, не импортированные из-за системного ограничения; их нужно добавить позже.
await tg.add_contact("+998901234567", "Ali", last_name="Valiyev")block
asyncБлокирует пользователя (contacts.block); снять блокировку — unblock().
await tg.block(user: Union[int, str, Any]) -> Anyawait tg.block("@spam_bot")
await tg.unblock("@spam_bot")blocked
asyncСписок заблокированных пользователей, по умолчанию до 100.
await tg.blocked(*, limit: int = 100) -> Anyblocked = await tg.blocked(limit=100)common_chats
asyncГруппы и каналы, в которых вы состоите вместе с указанным пользователем, по умолчанию до 100.
await tg.common_chats(user: Union[int, str, Any], *, limit: int = 100) -> Anychats = await tg.common_chats("@foydalanuvchi")contacts
asyncСписок контактов аккаунта (contacts.getContacts): записи контактов и объекты users.
await tg.contacts() -> Anycontacts = await tg.contacts()delete_contact
asyncУдаляет пользователя из контактов.
await tg.delete_contact(user: Union[int, str, Any]) -> Anyawait tg.delete_contact("@foydalanuvchi")entity
asyncПревращает @username, числовой ID, ссылку t.me/... или телефон в объект Telegram (User, Chat, Channel). Остальные методы используют это внутри.
await tg.entity(entity: Union[int, str, Any]) -> Any- Числовой ID работает только для объектов из памяти сессии (например, после
dialogs()илиparticipants()) — строка сессии этот кэш не хранит. Если не найдено —NotFoundError.
resolve
asyncЗапрашивает @username напрямую у Telegram (contacts.resolveUsername); работает с @ и без. В ответе peer, users и chats.
await tg.resolve(username: str) -> Any- В отличие от
entity(), который смотрит в кэш, каждый вызов идёт на сервер — для повторных поисков лучшеentity().
unblock
asyncСнимает блокировку с пользователя.
await tg.unblock(user: Union[int, str, Any]) -> Anyawait tg.block("@spam_bot")
await tg.unblock("@spam_bot")user_full
asyncПолная информация о пользователе (users.getFullUser): био, число общих групп и другие поля профиля.
await tg.user_full(user: Union[int, str, Any]) -> Anyuser = await tg.user_full("@durov")Группы и каналы
Создание, вступление, выход, удаление, название, описание, фото, медленный режим и права по умолчанию.
chat_fullcreate_channelcreate_groupdelete_chatjoinleaveset_aboutset_default_permissionsset_photoset_slowmodeset_title
chat_full
asyncПолная информация о группе или канале: описание, число участников, ссылка-приглашение, связанная группа обсуждения, ожидающие заявки. Для супергрупп и каналов — channels.getFullChannel, для обычных групп — messages.getFullChat.
await tg.chat_full(entity: Union[int, str, Any]) -> Any- Полезные флаги внутри
full_chat:can_view_stats— доступна ли статистика,can_view_participants— виден ли список участников,slowmode_seconds— текущий медленный режим.
info = await tg.chat_full("@kanal")create_channel
asyncСоздаёт канал (broadcast=True, по умолчанию) или супергруппу (broadcast=False); about — описание.
await tg.create_channel(title: str, *, about: str = '', broadcast: bool = True) -> Any- Новый канал создаётся без публичного username, то есть приватным.
channel = await tg.create_channel("Yangiliklar", about="Kompaniya yangiliklari")create_group
asyncСоздаёт группу: megagroup=True (по умолчанию) — супергруппа, megagroup=False — обычная группа с users.
await tg.create_group(
title: str,
users: Sequence[Union[int, str, Any]],
*,
megagroup: bool = True,
about: str = '',
) -> Any- При
megagroup=Trueпользователи изusersне добавляются — пригласите их потом черезinvite(). В обычной группеaboutне применяется. - Обычная группа вмещает до 200 участников, супергруппа — до 200 000.
group = await tg.create_group("Playground guruhi", ["@do'stim"], megagroup=True)delete_chat
asyncПолностью удаляет группу или канал для всех — участников и историю не вернуть. Нужны права создателя, иначе PermissionError.
await tg.delete_chat(entity: Union[int, str, Any]) -> Any- Канал или супергруппу больше чем с 1000 участников через API удалить нельзя —
CHANNEL_TOO_LARGE.
await tg.delete_chat("@mening_kanalim")join
asyncВступает в группу или канал: принимает и публичный @username, и ссылку-приглашение t.me/+... или t.me/joinchat/... — нужный TL-запрос SDK выбирает сам.
await tg.join(entity: Union[str, int, Any]) -> Any- Если ссылка требует одобрения администратора, Telegram возвращает
INVITE_REQUEST_SENT— заявка отправлена (в SDK этоApiError). - Число каналов и супергрупп, в которых может состоять аккаунт, ограничено — при превышении
CHANNELS_TOO_MUCH.
await tg.join("@kanal")leave
asyncВыходит из группы или канала; в обычной группе история чата у вас тоже очищается.
await tg.leave(entity: Union[int, str, Any]) -> Anyawait tg.leave("@kanal")set_about
asyncМеняет описание (about) группы или канала.
await tg.set_about(entity: Union[int, str, Any], about: str) -> Any- Длина описания ограничена — при превышении
CHAT_ABOUT_TOO_LONG, если текст не изменился —CHAT_ABOUT_NOT_MODIFIED.
Задаёт права по умолчанию для всех участников группы (например, запретить всем писать: send_messages=False). Как и в restrict(), False — запрет.
await tg.set_default_permissions(entity: Union[int, str, Any], **rights: bool) -> Anyview_messagesздесь не используется — он только для бана конкретного участника.- Telethon выполняет это только для супергрупп и каналов; для обычной группы SDK выбрасывает
NotFoundError.
set_photo
asyncЗагружает и устанавливает фото группы или канала из пути, байтов или файлового объекта.
await tg.set_photo(entity: Union[int, str, Any], file: Any) -> Anyawait tg.set_photo("@guruh", "logo.png")set_slowmode
asyncВключает медленный режим в супергруппе: участник может отправлять одно сообщение раз в seconds секунд; 0 — выключить.
await tg.set_slowmode(entity: Union[int, str, Any], seconds: int = 0) -> Any- Только для супергрупп. Недопустимая длительность —
SECONDS_INVALID.
await tg.set_title("@guruh", "Yangi nom")
await tg.set_slowmode("@guruh", 30)set_title
asyncМеняет название группы или канала; нужно право change_info.
await tg.set_title(entity: Union[int, str, Any], title: str) -> Anyawait tg.set_title("@guruh", "Yangi nom")
await tg.set_slowmode("@guruh", 30)Участники и модерация
Список участников, приглашение, исключение, бан, ограничения и права администратора.
adminsbanbanneddemoteinvitekickmute_memberparticipantspermissionspromoterestrictunban
admins
asyncТолько администраторы, без ограничения limit; роль и права — в поле participant каждого пользователя.
await tg.admins(entity: Union[int, str, Any]) -> listadmins = await tg.admins("@guruh")ban
asyncИсключает участника и запрещает ему возвращаться. until (datetime) — срок бана; без него — навсегда.
await tg.ban(
entity: Union[int, str, Any],
user: Union[int, str, Any],
*,
until: Optional[datetime.datetime] = None,
) -> Any- Срок больше 366 дней или меньше 30 секунд Telegram считает бессрочным.
- Работает в супергруппах и каналах (нужно право
ban_users); в обычной группе —kick().
await tg.ban("@guruh", "@foydalanuvchi")banned
asyncЗабаненные (исключённые) участники, по умолчанию до 100.
await tg.banned(entity: Union[int, str, Any]) -> list- Для участников только с ограничениями:
participants(entity, filter=tg.tl().types.ChannelParticipantsBanned(q="")).
banned = await tg.banned("@guruh")demote
asyncСнимает права администратора и возвращает пользователя в обычные участники.
await tg.demote(entity: Union[int, str, Any], user: Union[int, str, Any]) -> Anyawait tg.demote("@guruh", "@foydalanuvchi")invite
asyncДобавляет пользователей в группу или канал: в супергруппу и канал одним запросом, в обычную группу по одному.
await tg.invite(
entity: Union[int, str, Any],
users: Sequence[Union[int, str, Any]],
) -> Any- Если настройки приватности запрещают, будет
USER_PRIVACY_RESTRICTED(PermissionError) — отправьте такому человеку ссылку-приглашение. missing_inviteesв ответе супергруппы или канала — те, кого добавить не удалось.- Массовое добавление незнакомых людей — спам: аккаунты, использующие Telegram API для спама, блокируются навсегда.
await tg.invite("@guruh", ["@foydalanuvchi"])kick
asyncИсключает участника без бана — он сможет вернуться по ссылке. Для бана используйте ban().
await tg.kick(entity: Union[int, str, Any], user: Union[int, str, Any]) -> Any- В супергруппах и каналах Telethon делает это как «бан и сразу разбан».
await tg.kick("@guruh", "@foydalanuvchi")mute_member
asyncЗапрещает участнику писать — сокращение для restrict(send_messages=False); с until — на время.
await tg.mute_member(
entity: Union[int, str, Any],
user: Union[int, str, Any],
*,
until: Optional[datetime.datetime] = None,
) -> Anyparticipants
asyncСписок участников группы или канала — в Bot API такого метода нет. search — по имени или username, filter — админы, боты, забаненные и т. д., limit=None — все.
await tg.participants(
entity: Union[int, str, Any],
*,
limit: Optional[int] = 100,
search: Optional[str] = None,
aggressive: bool = False,
filter: Optional[Any] = None,
) -> list- Для подписчиков канала нужны права администратора (
CHAT_ADMIN_REQUIRED→PermissionError); в супергруппе список может быть скрыт — проверьтеcan_view_participantsвchat_full(). - Параметр
aggressiveв актуальных версиях Telethon ничего не делает и оставлен для совместимости. - Рассылка непрошеных сообщений по полученному списку или массовое добавление людей в другие чаты — это спам, за который аккаунт блокируют.
members = await tg.participants("@guruh", limit=200)permissions
asyncСтатус и права одного участника: создатель, администратор, ограничен ли и что ему разрешено (Telethon ParticipantPermissions).
await tg.permissions(entity: Union[int, str, Any], user: Union[int, str, Any]) -> Anyrights = await tg.permissions("@guruh", "@foydalanuvchi")promote
asyncНазначает участника администратором; каждое право — отдельный флаг (delete_messages, ban_users, pin_messages ...), title — должность. add_admins по умолчанию False: новый админ не сможет назначать других.
await tg.promote(
entity: Union[int, str, Any],
user: Union[int, str, Any],
*,
title: Optional[str] = None,
change_info: bool = True,
post_messages: bool = True,
edit_messages: bool = True,
delete_messages: bool = True,
ban_users: bool = True,
invite_users: bool = True,
pin_messages: bool = True,
add_admins: bool = False,
manage_call: bool = True,
anonymous: bool = False,
) -> Any- В обычной группе гранулярных прав нет — пользователь просто становится админом.
anonymous=Trueскрывает админа из списка участников и не даёт ему писать от своего аккаунта.
await tg.promote("@guruh", "@foydalanuvchi", title="Moderator", ban_users=True)restrict
asyncОграничивает отдельные права участника: сообщения, медиа, стикеры, GIF, ссылки, опросы и т. д. Внимание: False — запрет, True — разрешение; until — срок.
await tg.restrict(
entity: Union[int, str, Any],
user: Union[int, str, Any],
*,
until: Optional[datetime.datetime] = None,
send_messages: bool = True,
send_media: bool = True,
send_stickers: bool = True,
send_gifs: bool = True,
send_games: bool = True,
send_inline: bool = True,
embed_links: bool = True,
send_polls: bool = True,
change_info: bool = True,
invite_users: bool = True,
pin_messages: bool = True,
embed_link_previews: bool = True,
) -> Any- Только в супергруппах: индивидуальные ограничения в обычной группе невозможны (SDK выбросит
NotFoundError). - Непереданный параметр считается
True— каждый вызов перезаписывает весь набор прав, прежние ограничения не сохраняются.
await tg.restrict("@guruh", "@foydalanuvchi", send_messages=False)unban
asyncСнимает бан и ограничения. Пользователь не возвращается автоматически — он должен вступить сам или получить приглашение.
await tg.unban(entity: Union[int, str, Any], user: Union[int, str, Any]) -> Anyawait tg.unban("@guruh", "@foydalanuvchi")Ссылки-приглашения и заявки
Создание и отзыв ссылок-приглашений, просмотр и одобрение заявок на вступление.
approve_join_requestcreate_invite_linkinvite_linkjoin_requestsrevoke_invite_link
approve_join_request
asyncОдобряет (approved=True) или отклоняет (approved=False) заявку на вступление.
await tg.approve_join_request(
entity: Union[int, str, Any],
user: Union[int, str, Any],
*,
approved: bool = True,
) -> Anyawait tg.approve_join_request("@guruh", 123456789, approved=True)create_invite_link
asyncСоздаёт дополнительную ссылку-приглашение: title (видят только админы), expire_date, usage_limit — максимум вступлений, request_needed — одобрение каждого вступления админом.
await tg.create_invite_link(
entity: Union[int, str, Any],
*,
title: Optional[str] = None,
expire_date: Optional[datetime.datetime] = None,
usage_limit: Optional[int] = None,
request_needed: bool = False,
) -> Any- Заявки по ссылке с
request_needed=Trueвидны вjoin_requests()и решаются черезapprove_join_request().
link = await tg.create_invite_link("@guruh", title="Reklama", usage_limit=100)invite_link
asyncСоздаёт новую ссылку-приглашение без ограничений (messages.exportChatInvite); сама ссылка — в поле link ответа.
await tg.invite_link(entity: Union[int, str, Any]) -> Any- Каждый вызов создаёт дополнительную ссылку, существующие не отзываются. Текущая ссылка чата —
full_chat.exported_inviteвchat_full(). - Если нужны срок, лимит или одобрение админом —
create_invite_link().
link = await tg.invite_link("@guruh")join_requests
asyncЗаявки на вступление, ожидающие одобрения (messages.getChatInviteImporters), по умолчанию до 50; в ответе importers и users.
await tg.join_requests(entity: Union[int, str, Any], *, limit: int = 50) -> Anyrequests = await tg.join_requests("@guruh")revoke_invite_link
asyncОтзывает ссылку-приглашение — вступить по ней больше нельзя; link — полная ссылка.
await tg.revoke_invite_link(entity: Union[int, str, Any], link: str) -> Any- Информация об отозванной ссылке остаётся доступной администраторам.
await tg.revoke_invite_link("@guruh", "https://t.me/+AbCdEf")Поиск и статистика
Поиск внутри чата и по всем чатам, статистика канала.
search
asyncИщет текст внутри одного чата; с from_user — только сообщения одного пользователя. Сокращение для messages(search=...).
await tg.search(
entity: Union[int, str, Any],
query: str,
*,
limit: int = 50,
from_user: Union[int, str, Any, NoneType] = None,
) -> listfound = await tg.search("@guruh", "narx", limit=50)
everywhere = await tg.search_global("socialift")search_global
asyncИщет сообщения по всем вашим чатам (messages.searchGlobal) и возвращает сырой TL-ответ (messages, chats, users).
await tg.search_global(query: str, *, limit: int = 50) -> Any- Возвращается только первая страница (
limitштук); для продолжения используйтеraw()сoffset_rate,offset_peer,offset_id.
found = await tg.search("@guruh", "narx", limit=50)
everywhere = await tg.search_global("socialift")stats
asyncСтатистика канала (stats.getBroadcastStats): подписчики, просмотры и репосты постов, графики роста. Для администраторов канала.
await tg.stats(entity: Union[int, str, Any]) -> Any- Статистика доступна только каналам определённого размера; порог задаёт сервер — проверяйте
full_chat.can_view_statsвchat_full(). - Telegram требует отправлять этот запрос в дата-центр
stats_dcканала, а SDK шлёт его в текущий — возможна ошибкаSTATS_MIGRATE. В этом случае, а также для статистики супергрупп используйтеawait tg.client.get_stats("@channel"): Telethon сам выберет дата-центр.
stats = await tg.stats("@kanal")Низкий уровень: TL-запросы
Вызов любого метода MTProto через Telethon, если в SDK нет обёртки.
raw
asyncОтправляет любой TL-запрос Telethon (functions.*Request) и переводит ошибки в иерархию SDK (RateLimitError, AuthError, PermissionError, NotFoundError). Для возможностей, у которых нет обёртки.
await tg.raw(request: Any) -> Any- В поля запроса можно передавать
@usernameили ID — Telethon сам приведёт их к нужному типуInput*. - Имена параметров — как в TL-схеме. В отличие от
tg.client(...), ошибки приходят в формате SDK, а не Telethon.
from telethon import functions
config = await tg.raw(functions.help.GetConfigRequest())tl
staticmethodВозвращает модуль telethon.tl: tg.tl().functions — запросы, tg.tl().types — типы (фильтры, права). Используется вместе с raw() и параметрами filter=.
TelegramAccount.tl()- Статический метод — вызывается без подключения, но
telethonдолжен быть установлен.
Частые вопросы
Чем Telegram-бот отличается от TelegramAccount (юзербота)?
Бот работает через Bot API с токеном от BotFather: он не может первым написать пользователю, а в Bot API нет методов для истории чата и полного списка участников. TelegramAccount работает по MTProto от имени обычного аккаунта, поэтому доступны история, участники, вступление в группы и создание каналов. Для сервиса, который обслуживает много пользователей, подходит бот; для управления своим аккаунтом и группами — TelegramAccount.
Как получить api_id и api_hash Telegram?
Войдите на my.telegram.org со своим номером и заполните форму приложения в разделе API development tools — вы получите api_id (число) и api_hash (строку). Сейчас к одному номеру телефона привязывается один api_id. В SDK их читает TelegramAccount.from_env() из TELEGRAM_API_ID и TELEGRAM_API_HASH.
Как безопасно хранить session string Telethon?
Строка из sign_in() или export_session() содержит ключ авторизации: тот, у кого она есть, входит в аккаунт без кода и пароля. Храните её в базе зашифрованной и не выводите в логи и сообщения об ошибках. При утечке вызовите log_out() или завершите сеанс через reset_session() из другой сессии.
Что делать при ошибке FLOOD_WAIT?
FLOOD_WAIT_X означает, что Telegram требует подождать X секунд. Ожидание до 60 секунд Telethon выполняет сам (вызов просто замедляется); более долгое SDK отдаёт как RateLimitError с retry_after, и решение остаётся за вами. Аккаунты, использующие Telegram API для флуда, спама или накрутки подписчиков и просмотров, блокируются навсегда.
Можно ли опубликовать историю (Stories) в Telegram из Python?
Да, но только от имени аккаунта: send_story() вызывает stories.sendStory в MTProto, а в Bot API публикации историй нет вовсе. Правила Telegram: от имени пользователя нужен Premium, от имени канала — право post_stories и достаточное число «бустов». Срок жизни — 6, 12, 24 или 48 часов (без Premium только 24), медиа вертикальное и не больше 30 МБ. Перед публикацией вызывайте can_send_story().
Как получить всех участников группы Telegram на Python?
await tg.participants("@group", limit=None) возвращает список объектов Telethon User; сузить выборку можно через search и filter. Для списка подписчиков канала нужны права администратора (иначе PermissionError), а в супергруппе администраторы могли скрыть список участников. Заранее проверьте can_view_participants в результате chat_full().