Перейти к содержанию
Innovialabs

Как делать рассылки по пользователям бота без блокировок

Практика4 мин

Коротко

Отправляйте рассылку через очередь с ограничением скорости, на ошибку 429 ждите ровно retry_after, пользователей с ошибкой 403 помечайте неактивными, а результат считайте по статусам каждого сообщения и переходам по ссылкам.

Короткий ответ

Рассылка без проблем — это очередь с ограничением скорости, а не цикл for user in users: send(). Что нужно:

  • Скорость. Telegram в своем FAQ советует не отправлять массовые уведомления быстрее примерно 30 сообщений в секунду и не больше одного сообщения в секунду в один чат. Держите запас ниже этой границы.
  • Ошибка 429. Если Telegram ответил Too Many Requests, ждите столько секунд, сколько указано в retry_after, и повторяйте.
  • Ошибка 403. Пользователь заблокировал бота или удалил аккаунт. Пометьте его неактивным и больше не пишите.
  • Учет. Каждое сообщение получает статус: отправлено, ошибка, заблокировано.

Для больших объемов у Telegram есть платные рассылки: параметр allow_paid_broadcast позволяет превысить бесплатный лимит за Telegram Stars. Подробности и стоимость — в документации Bot API.

Как устроить отправку

  1. Создайте кампанию в базе: текст, кнопки, сегмент, время старта.
  2. Сформируйте список получателей — по одной записи на пользователя со статусом pending.
  3. Воркер берет записи пачками и отправляет с паузой между сообщениями.
  4. Результат каждой отправки записывается в ту же таблицу: sent, blocked, failed и ID сообщения.
  5. Повтор выполняется только для pending и временных ошибок. Перезапуск воркера не должен отправлять сообщения второй раз.

Для очереди подойдет любой привычный инструмент: Redis, Celery, arq, RabbitMQ или просто таблица в PostgreSQL с блокировкой строк. Важнее, чтобы состояние хранилось в базе, а не в памяти процесса.

Минимальная логика на aiogram 3:

import asyncio
from aiogram.exceptions import (
    TelegramForbiddenError,
    TelegramRetryAfter,
    TelegramBadRequest,
)

async def send_one(bot, user_id: int, from_chat_id: int, message_id: int) -> str:
    while True:
        try:
            await bot.copy_message(user_id, from_chat_id, message_id)
            return "sent"
        except TelegramRetryAfter as e:
            await asyncio.sleep(e.retry_after)
        except TelegramForbiddenError:
            return "blocked"
        except TelegramBadRequest:
            return "failed"

async def run_campaign(bot, recipients, from_chat_id, message_id, rate=20):
    for user_id in recipients:
        status = await send_one(bot, user_id, from_chat_id, message_id)
        await save_status(user_id, status)
        await asyncio.sleep(1 / rate)

copyMessage удобен для рассылок: вы готовите пост в служебном чате, проверяете его вид, а бот копирует его без пометки «переслано».

Ошибки и что с ними делать

Ответ TelegramПричинаДействие
429 Too Many RequestsПревышена скоростьПауза на retry_after, затем повтор
403 ForbiddenБот заблокирован, аккаунт удаленПометить is_active = false
400 Bad RequestЧат не найден, неверная разметка, битая ссылка в кнопкеЗаписать ошибку, не повторять бесконечно
5xx, таймаутВременный сбойПовторить с задержкой, ограничить число попыток

Если вы получаете 429 постоянно, это сигнал снизить общую скорость, а не просто ждать дольше.

Сегментация

Не отправляйте все всем. Сегменты повышают отклик и уменьшают число блокировок:

  • Активность: писал боту за последний месяц, давно не заходил.
  • Действия: оставил заявку, купил, бросил оформление на середине.
  • Источник: пришел по конкретной рекламной ссылке со start-параметром.
  • Язык интерфейса или выбранный в боте.
  • Согласие: пользователь не отключил уведомления в настройках бота.

Дайте пользователю простой способ отписаться: кнопку или команду. Это лучше, чем блокировка бота, после которой вы теряете контакт полностью.

Как измерить результат

  • Доставка: доля sent от всех получателей, число новых blocked.
  • Переходы: ссылки с UTM-метками или deep link вида t.me/bot?start=camp42, по которому бот понимает, из какой рассылки пришел человек.
  • Нажатия на inline-кнопки: callback с ID кампании.
  • Целевые действия: заявки и оплаты, связанные с кампанией.
  • Отписки и блокировки в течение нескольких дней после рассылки.

Факт прочтения Bot API не сообщает, поэтому ориентируйтесь на действия пользователей.

Частые ошибки

  • Рассылка из обработчика команды: процесс блокируется, при перезапуске часть людей получает сообщение дважды.
  • Параллельная отправка в много потоков без общего ограничителя скорости.
  • Игнорирование 403: база «мертвых» пользователей растет, и каждая рассылка тратит на них время.
  • Одинаковый текст для всей базы без учета языка и интересов.

Подробнее о лимитах — в FAQ Telegram для разработчиков ботов.

Частые вопросы

Каждый бот может писать только своим пользователям, поэтому дробление базы между ботами обычно не решает задачу. Надежнее — общий ограничитель скорости и, если нужно, платные рассылки.

Поможем с этим

Если хотите не разбираться самим, а получить результат — этим мы занимаемся каждый день.

Обсудить проект

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.