Перенос рабочего парсера на новый сервер — рутинная задача. Но одна глупая ошибка может стоить вам прогретого аккаунта. Я случайно запустил один и тот же файл .session (Telethon) одновременно на старом и новом серверах. Итог: Telegram мгновенно убил сессию с ошибкой AuthKeyDuplicatedError, а при попытке перелогиниться выдал UPDATE_APP_TO_LOGIN. Аккаунт улетел в теневой бан.

В этой статье я покажу, как я вытаскивал парсер (Python 3.11, Telethon) из серого списка Telegram. Мы разберем реверс-инжиниринг десктопного клиента, дамп памяти tdata, обход конфликтов PEP 604 и жесткий спуфинг (маскировку) сессии, чтобы антифрод принял наш Ubuntu-сервер за официальный клиент на macOS. В итоге: парсер спасен, аккаунт жив, бизнес не потерял ни одного лида.

Точка А: Триггер антифрода и смерть сессии

В протоколе MTProto авторизация жестко привязана к криптографическому ключу AuthKey, который генерируется при входе. Когда мой скрипт запустился на двух серверах одновременно, Telegram зафиксировал классический race condition: с двух разных IP-адресов в одну секунду пошли запросы, подписанные одним ключом.

Система безопасности Телеграма расценила это как кражу ключа. Ключ был мгновенно инвалидирован, сессии убиты.

Дави спокуху. Пишу стандартный скрипт для повторной авторизации через client.send_code_request(), чтобы получить СМС. И ловлю RPCError 406: UPDATE_APP_TO_LOGIN.

Под капотом проблемы: Для аккаунтов, попавших в серый список, Telegram отключает возможность получения кодов через старые слои API (API Layers). Библиотека Telethon использует слой 167, тогда как официальные клиенты работают на слоях 180+. Telegram принудительно требует входа через официальное приложение. Использовать стандартный флоу Telethon для этого аккаунта стало технически невозможно.

Инженерное решение: QR-Bypass и дамп памяти

Раз я не могу запросить код через API, план такой: авторизоваться в официальном десктопном клиенте (через QR-код, чтобы обойти запрос СМС), расшифровать его локальную базу данных, вытащить AuthKey и упаковать его в SQLite-базу формата Telethon.

Грабли 1: Зоопарк клиентов на macOS

На Mac существует два официальных клиента, и у них кардинально разная архитектура:

  1. Telegram for macOS (Swift, из App Store): Хранит ключи в защищенных базах внутри песочницы ~/Library/Group Containers/.... Дамп ключей отсюда — та еще боль.

  2. Telegram Desktop (C++/Qt, с сайта): Хранит ключи в проприетарном бинарном формате в папке tdata. Это то, что мне нужно.

Чтобы не скопировать пустую или старую сессию, я нашел активную директорию, проверив время изменения файлов (сразу после входа по QR-коду):

code Bash

# Ищем, какая из папок была активна в последние 30 минут:
echo "=== Версия с сайта ===" && \
find ~/Library/Application\ Support/Telegram\ Desktop/tdata -mmin -30 2>/dev/null | wc -l && \
echo "=== Версия из App Store ===" && \
find ~/Library/Containers/org.telegram.desktop/Data/Library/Application\ Support/Telegram\ Desktop/tdata -mmin -30 2>/dev/null | wc -l

Грабли 2: Unix-матрешка при копировании

При попытке скопировать папку tdata на Рабочий стол командой cp -r я словил классическую проблему. Так как папка-приемник уже существовала (от предыдущей неудачной попытки), новая папка скопировалась внутрь неё. Скрипт конвертации смотрел в корень, не находил файлов и падал.

Фикс: Обязательно сносим старый слепок перед копированием:

code Bash

rm -rf ~/Desktop/my_tdata
cp -r "$HOME/Library/Application Support/Telegram Desktop/tdata" "$HOME/Desktop/my_tdata"
cd ~/Desktop && zip -r my_tdata.zip my_tdata

Грабли 3: Ад зависимостей и PEP 604

Я попытался расшифровать tdata прямо на Маке. Старая библиотека opentele не сработала — в последних версиях Telegram Desktop изменил алгоритмы локального шифрования.

Я перешел на современный форк — opentele2. И тут скрипт падает с ошибкой:

code Text

TypeError: unsupported operand type(s) for |: 'type' and 'type'

Причина: Библиотека написана с использованием стандартов PEP 604 (синтаксис bytes | bytearray). На моем Mac по умолчанию стоял системный Python 3.9 от Apple, который этот синтаксис не понимает (он появился только в 3.10).

Вместо того чтобы городить виртуальные окружения на Маке, я просто закинул архив tdata.zip на боевой Ubuntu-сервер, где из коробки стоит Python 3.10+.

Финальный босс: Серверная конвертация и маскировка (Spoofing)

Вот тут начинается самое жесткое мясо. Если просто сконвертировать сессию и запустить её, Telethon отправит на серверы Telegram запрос InitConnection. Для аккаунта в сером списке вход нового неофициального устройства с IP-адреса дата-центра — это моментальный пермач (бан).

Мне нужно было заставить Telethon клонировать существующий AuthKey и притвориться тем самым официальным клиентом.

Шаг 1. Конвертация без создания новой сессии

Пишу скрипт convert_server.py на Ubuntu:

code Python

import os
import asyncio
from opentele2.td import TDesktop
from opentele2.api import UseCurrentSession

async def main():
    tdata_path = "./my_tdata"
    session_path = "./reserve_session.session"
    
    print("[*] Загрузка tdata через opentele2...")
    try:
        tdesk = TDesktop(tdata_path)
    except Exception as e:
        print(f"[!] Ошибка чтения папки: {e}")
        return

    if not tdesk.isLoaded():
        print("[!] Ошибка: Папка пуста или не авторизована.")
        return
    
    try:
        # КРИТИЧЕСКИ ВАЖНО: Флаг UseCurrentSession предотвращает отправку 
        # запроса InitConnection и защищает от мгновенного бана.
        # Мы клонируем ключ, а не создаем новое устройство.
        client = await tdesk.ToTelethon(session=session_path, flag=UseCurrentSession)
        
        await client.connect()
        if await client.is_user_authorized():
            me = await client.get_me()
            print(f"[+] УСПЕХ! Сессия создана. Аккаунт: @{me.username or 'Hidden'}")
        else:
            print("[!] Ошибка: Сессия не авторизована.")
            
        await client.disconnect()
        
    except Exception as e:
        print(f"[!] Ошибка конвертации: {e}")

if __name__ == "__main__":
    asyncio.run(main())

Шаг 2. Жесткий спуфинг при инициализации

Чтобы иллюзия была полной, при запуске боевого парсера я жестко захардкодил параметры официального Telegram Desktop. Если оставить дефолтные параметры Telethon, антифрод увидит, что ключ выдан для Desktop-клиента, а запросы идут от неизвестного приложения.

code Python

import asyncio
from telethon import TelegramClient

async def main():
    session_name = "reserve_session"
    
    # Официальные ключи Telegram Desktop (API ID 2040)
    # Использование кастомных ключей с десктопной сессией приведет к бану!
    api_id = 2040
    api_hash = "b18441a1ff607e10a989891a5462e627"
    
    # Инициализация с жестким спуфингом параметров устройства
    client = TelegramClient(
        session_name, 
        api_id, 
        api_hash,
        device_model="PC 64bit",
        system_version="Windows 10",
        app_version="4.8.1"
    )
    
    print("[*] Подключение к серверам Telegram...")
    await client.connect()
    
    is_authorized = await client.is_user_authorized()
    if is_authorized:
        print(f"\n[+] ТЕСТ ПРОЙДЕН УСПЕШНО! Telethon видит сессию.")
    else:
        print("\n[!] КРИТИЧЕСКАЯ ОШИБКА: Сессия мертва.")
        
    await client.disconnect()

if __name__ == "__main__":
    asyncio.run(main())

Точка Б

Подменяю файл сессии в боевом парсере, перезапускаю службу и смотрю логи:

code Text

# journalctl -u reserve_parser.service -n 20
Jun 29 12:05:58 server systemd[1]: Started reserve_parser.service - Telegram Reserve Parser.
Jun 29 12:05:59 server bash[94626]: INFO - Connecting to 149.154.167.51:443/TcpFull...
Jun 29 12:05:59 server bash[94626]: INFO - Connection to 149.154.167.51:443/TcpFull complete!
Jun 29 12:06:05 server bash[94626]: INFO - Конфиг обновлен. Чатов: 25, Ключей: 63, Интентов: 58
Jun 29 12:06:05 server bash[94626]: INFO - === ЗАПУСК АКТИВНОГО PULL-ПАРСЕРА ===

Сеть пробита, парсер работает.

Важное архитектурное ограничение: Так как серверная сессия и десктопный клиент на Mac теперь делят один криптографический ключ, нажатие кнопки "Log Out" на Mac приведет к отправке запроса на уничтожение ключа. Серверный парсер умрет в ту же секунду. Клиент на Mac можно только закрывать (kill process), но не разлогинивать.


P.S. Работа с Telegram API в 2026 году — это постоянная борьба с антифродом. Одно неверное движение, и ваш бизнес остается без лидов.


Больше жестких разборов по автоматизации и реверс-инжинирингу я публикую в своем Telegram-канале. Если вам нужно разработать отказоустойчивый парсер, вытащить данные из сложных источников или настроить безопасную инфраструктуру — пишите в личку Telegram, обсудим задачу на языке цифр и архитектуры.

Комментарии (0)