Перейти к содержанию
12 минут чтения
Тема: Диагностика Linux · Bash · curl

Таймаут при обращении к api.telegram.org: что проверить на сервере

Бот перестал отправлять сообщения, а в логах — Connection timed out или cURL error 28. Разберём, на каком этапе остановился запрос и что делать с результатом проверки.

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

Таймаут означает, что клиент не дождался завершения операции за отведённое время. По одной этой ошибке нельзя установить блокировку Telegram или неисправность бота. Проверьте запрос из той же среды, где работает приложение, затем последовательно отделите проблему соединения от ошибки API.

Для начала токен не нужен. Для проверки самого бота используйте getMe: он ничего не отправляет в чаты и не меняет webhook.

Перед началом: проверяйте там, где возникает ошибка

Успешный запрос с ноутбука мало говорит о доступности Telegram с вашего хостинга. Запускайте проверки на сервере приложения, а при использовании Docker — внутри того контейнера, который обращается к API. У контейнера, PHP-FPM и фонового обработчика могут отличаться сеть, DNS и переменные окружения.

Команды ниже предназначены для Bash на Linux. Они не устанавливают пакеты и не меняют настройки сервера. Понадобятся curl, а для отдельной проверки DNS — getent. Узнать версию клиента можно командой curl --version. На Windows синтаксис скрытого ввода и переноса строк будет другим.

  • Запишите время ошибки с часовым поясом, метод API, длительность ожидания и среду запуска.
  • Отделите код ошибки curl от HTTP-статуса. 28 — ошибка клиента, 429 — ответ HTTP.
  • Перед отправкой логов удалите токен из пути /bot…/, API-ключи и содержимое сообщений.

1. Проверяем соединение без токена

Обратитесь к корню домена и сохраните только статус и время прохождения этапов:

Bash · без токена
curl -q --silent --show-error --output /dev/null \
  --connect-timeout 5 --max-time 15 \
  --write-out 'http=%{http_code}\nip=%{remote_ip}\ndns=%{time_namelookup}\ntcp=%{time_connect}\ntls=%{time_appconnect}\nfirst_byte=%{time_starttransfer}\ntotal=%{time_total}\n' \
  https://api.telegram.org/

-q первым аргументом отключает чтение пользовательского файла настроек curl. Переменные прокси при этом продолжают действовать. --connect-timeout 5 ограничивает установление соединения, включая DNS и TLS; --max-time 15 — всю операцию. Это ориентиры для диагностики небольшого запроса, а не универсальные настройки для загрузки файлов. Подробнее о таймаутах curl ↗

Числа времени указаны в секундах от начала запроса: складывать их не нужно. Например, промежуток между tcp и tls приблизительно показывает время TLS-рукопожатия для этого нового соединения. Нулевое значение само по себе не доказывает причину: учитывайте полный текст ошибки и последний завершённый этап. Описание измерений ↗

РезультатКак его понимать
Есть HTTP-ответ, например 200 или 302Получен ответ по HTTPS. Это ещё не проверка токена, методов API или постоянной доступности.
http=000curl не получил HTTP-статус. Причину ищите в сообщении curl: DNS, соединение, TLS или ожидание ответа. Это не статус Telegram.
curl: (6)Не удалось разрешить имя узла.
curl: (7)Не удалось подключиться к узлу или прокси.
curl: (28)Истёк один из лимитов времени; ошибка возможна на разных этапах.
curl: (35) или (60)Ошибка TLS-соединения или проверки сертификата. Сначала разберите сопутствующее сообщение.

Коды приведены по справочнику libcurl. Ответ корпоративного прокси или сетевого фильтра также может иметь HTTP-статус — при сомнениях важны сертификат и источник ответа.

2. Уточняем сетевую причину

DNS: получает ли среда адрес узла?

Bash · системное разрешение имени
getent ahosts api.telegram.org

Если адресов нет, проверьте настройки резолвера в этой среде и доступность DNS у провайдера. Если адреса есть, но curl сообщает ошибку разрешения имени, сравните среду запуска и способ разрешения DNS в клиенте. Результат getent не гарантирует, что библиотека приложения использует тот же механизм.

IPv4 и IPv6: одинаково ли работает маршрут?

Bash · два независимых запроса
curl -q -4 --silent --show-error --output /dev/null \
  --connect-timeout 5 --max-time 15 \
  --write-out 'IPv4 http=%{http_code} total=%{time_total}\n' \
  https://api.telegram.org/

curl -q -6 --silent --show-error --output /dev/null \
  --connect-timeout 5 --max-time 15 \
  --write-out 'IPv6 http=%{http_code} total=%{time_total}\n' \
  https://api.telegram.org/

Если IPv4 работает, а IPv6 нет, проверьте наличие IPv6-адреса назначения и IPv6-связности сервера. Отсутствие IPv6 в среде само по себе нормально. Разница в результатах — повод изучить выбор адреса клиентом; она не доказывает, что именно IPv6 вызвал исходный сбой.

Прокси и TLS: тем ли путём идёт запрос?

Проверьте наличие HTTPS_PROXY, ALL_PROXY, NO_PROXY и их вариантов в нижнем регистре. Не публикуйте значения: URL прокси может содержать пароль. Для сравнения с прямым соединением можно добавить --noproxy '*' в первый запрос, если прямой выход разрешён в вашей инфраструктуре. При использовании прокси смысл сетевых измерений меняется. Как curl выбирает прокси ↗

При ошибке сертификата проверьте системное время, доверенные CA и настройки TLS в контейнере или PHP. Не оставляйте -k или отключённую проверку сертификата как исправление: тогда клиент перестаёт надёжно проверять сервер, которому отправляет токен. Проверка сертификатов curl ↗

Если DNS работает, но соединение не устанавливается, сравните запрос с другой доверенной машины. Соберите время, адрес назначения и текст ошибки для хостинга. Возможны проблемы маршрута, исходящего firewall, прокси или внешней сети; одного таймаута недостаточно, чтобы выбрать между ними.

3. Проверяем сам Bot API и токен

Когда соединение устанавливается, вызовите getMe. Метод не требует параметров и возвращает сведения о боте. Он подходит для проверки без тестовых сообщений пользователям.

В примере токен вводится скрыто и передаётся curl через стандартный ввод, чтобы не помещать его прямо в историю команд и аргументы процесса. Выполняйте команды в доверенной консоли; запись терминальной сессии и отладочная трассировка могут раскрывать секреты.

Bash · введите токен своего бота по приглашению
set +x
read -rsp 'Telegram Bot Token: ' TG_TOKEN
printf '\n'
printf 'url = "https://api.telegram.org/bot%s/getMe"\n' "$TG_TOKEN" |
  curl -q --config - --silent --show-error \
    --connect-timeout 5 --max-time 15 \
    --write-out '\nHTTP=%{http_code}\n'
unset TG_TOKEN
  • "ok": true и ожидаемый бот в result — этот запрос прошёл, токен принят.
  • JSON-ответ с ошибкой — изучите error_code и description. Проверьте токен и URL при ошибке авторизации; при 429 учитывайте parameters.retry_after, если он есть.
  • HTML от промежуточного сервера, 5xx или новый таймаут — исследуйте источник ответа и маршрут. Не считайте любой такой ответ ошибкой токена.

Успешный getMe не проверяет отправку большого файла, права бота в конкретном чате или доставку webhook. Эти сценарии проверяются отдельно.

4. Если curl работает, а приложение — нет

Сравните тот же метод, адрес, маршрут и время запуска. Проверка из SSH и запрос из PHP-FPM могут отличаться конфигурацией, даже если находятся на одном сервере.

  • Окружение. Совпадают ли DNS, прокси, доступ к сети и хранилище сертификатов у веб-процесса, контейнера и фонового worker?
  • Настройки клиента. В PHP CURLOPT_CONNECTTIMEOUT ограничивает подключение, а CURLOPT_TIMEOUT — всю операцию. SDK может задавать собственные значения. Справочник PHP ↗
  • Размер и метод запроса. Быстрый getMe не воспроизводит загрузку видео. Для файла важны размер, скорость исходящего канала и общий лимит времени.
  • Внешние ограничения. У PHP-FPM, очереди и Nginx могут быть свои таймауты. Если браузер получил 504, это ещё не значит, что исходящий запрос PHP уже остановлен.
  • Нагрузка. Посмотрите, возникает ли задержка до отправки HTTP-запроса: задача может ждать в очереди, а процесс — свободного соединения.

Для Laravel фиксируйте отдельно время ожидания задачи и время HTTP-запроса. Согласуйте лимиты worker и клиента, чтобы worker не обрывал ещё выполняющийся запрос. Не увеличивайте все таймауты одновременно: сначала определите, какой из них срабатывает.

После таймаута результат отправки может быть неизвестен

Telegram мог принять sendMessage, а ответ не дошёл до приложения. Автоматический повтор способен создать дубликат. Повторять диагностический getMe безопаснее; для операций отправки нужна отдельная политика повторов, учёт задач и обработка неопределённого результата.

Если проблема во входящих обновлениях, исследуйте webhook отдельно: посмотрите getWebhookInfo, доступность вашего обработчика и его HTTP-ответы. Не меняйте webhook и не включайте getUpdates только ради проверки исходящего соединения.

5. Выбираем решение по результатам

Что установилиСледующий шаг
Ошибка DNS или сертификата в одной средеИсправить резолвер, время или доверенные CA именно в этой среде.
Сбой выбранного сетевого маршрутаОбратиться к хостингу с результатами проверок; оценить другой исходящий маршрут или прокси.
API отвечает ошибкой авторизации или параметровИсправить токен, адрес или запрос. Смена маршрута не исправит содержимое запроса.
Ошибки связаны с лимитамиУправлять частотой и очередью, учитывать указания API о времени повторной попытки.
Нужен постоянный альтернативный путь к TelegramСравнить собственный прокси, перенос исходящего обработчика и готовый API-шлюз.

Собственный прокси даёт контроль над инфраструктурой, но требует настройки, обновления и мониторинга. Готовый шлюз снимает часть этой работы, добавляя зависимость от сервиса и его контракта. Выбирайте с учётом поддерживаемых методов, конфиденциальности, лимитов, стоимости и необходимой доступности.

Как убедиться, что проблема решена

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

  1. Повторите несколько getMe с паузами из той же среды, затем проверьте проблемный сценарий приложения.
  2. Для отправки используйте отдельный тестовый чат; убедитесь в получении сообщения и отсутствии дубликатов. Для файлов и webhook проведите свои проверки.
  3. Посмотрите длительности и долю ошибок за характерный период нагрузки. Убедитесь, что очередь не растёт, а таймауты не просто стали длиннее.
  4. Сохраните причину, изменение и результаты до/после. В обращение в поддержку включите время, метод, код ошибки и среду, без токенов и пользовательских данных.

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

Когда для этой задачи подходит BotGate

BotGate можно рассмотреть, если проблема связана с прямым доступом вашего сервера к Telegram и нужен готовый маршрут через зарубежную proxy-ноду. Сам BotGate при этом должен быть доступен из вашей среды. Сервис не исправляет неверный токен, ошибку обработчика или ограничения Telegram и не гарантирует отсутствие любых сбоев.

Подключение включает регистрацию, добавление бота и использование API-ключа BotGate. Меняются адрес и авторизация. getUpdates не поддерживается: входящие обновления доставляются через webhook. Параметры поддерживаемых методов остаются в формате Telegram; лимиты и особенности описаны в документации BotGate.

После добавления бота сравните прямой getMe с тем же методом через шлюз. Ни один из этих запросов не отправляет сообщения.

Bash · Bot ID из кабинета и API-ключ BotGate
set +x
BOT_ID='bot_ваш_идентификатор'
read -rsp 'BotGate API key: ' BOTGATE_API_KEY
printf '\n'
printf 'url = "https://bot-gate.ru/api/v1/bots/%s/getMe"\nheader = "Authorization: Bearer %s"\n' "$BOT_ID" "$BOTGATE_API_KEY" |
  curl -q --config - --request POST --silent --show-error \
    --connect-timeout 5 --max-time 15 \
    --write-out '\nHTTP=%{http_code}\n'
unset BOTGATE_API_KEY BOT_ID

Если через шлюз запрос проходит, а напрямую в то же время нет, это показывает различие в работоспособности двух путей. Причину сбоя прямого пути всё равно устанавливают отдельно. Для ошибок BotGate сверяйте HTTP-статус и тело ответа с таблицей ошибок.

Перейти к инструкции подключения

Источники и границы примеров

Материал опирается на официальные справочники curl, libcurl, PHP и Telegram Bot API. Ссылки на конкретные настройки приведены в соответствующих шагах.

Это последовательность диагностики, а не отчёт о сбое конкретного провайдера. Указанные таймауты — примеры для небольших диагностических запросов. Команды с вашим токеном и особенности вашей сети требуют проверки в вашей среде.