PHP на сервере LinuxWindows 28

PHP cURL: Operation timed out / Connection timed out

  • Обновлено
  • Чтение ≈ 4 минуты
  • Нужны права администратора

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

Ошибка cURL «Operation timed out» в PHP означает, что удалённый сервер не ответил вовремя. Проверьте доступность хоста с сервера, DNS, файрвол, увеличьте CURLOPT_TIMEOUT и CONNECTTIMEOUT, добавьте повторные попытки и логируйте время фаз запроса.

В этой статье
  1. Что означает код 28
  2. Причины
  3. Порядок
  4. Диагностика в расширенном режиме
cURL error 28
cURL error 28: Operation timed out after 30001 milliseconds with 0 bytes received
По-русскиВремя ожидания ответа истекло.

#Что означает код 28

CURLE_OPERATION_TIMEDOUT (28) возникает, когда cURL не успел завершить операцию за заданное время. Различайте два случая: не удалось установить соединение (Connection timed out after N milliseconds) — проблема сети, файрвола, DNS или недоступного хоста; соединение установлено, но ответ не пришёл (with 0 bytes received) — медленный или зависший сервер, тяжёлый запрос, блокировка на стороне получателя. Подход к исправлению зависит от этого.

#Причины

Возможная причинаКак узнатьЧто делать
Сервер не отвечаетАвария, перегрузка.Не открывается и из браузера.Подождите, свяжитесь с владельцем.
Файрвол блокируетИсходящие порты.nc не соединяется.Откройте порт.
Проблемы DNS или IPv6Нет маршрута IPv6.Долгая фаза namelookup.Принудительно IPv4.
Слишком малый таймаут1–5 секунд для тяжёлого API.Обрывы на длинных запросах.Увеличьте CURLOPT_TIMEOUT.
Ограничение частоты запросовRate limit.Ответы замедляются.Снизьте частоту.
Хостинг режет исходящиеОбщий хостинг.Часть адресов недоступна.Запросите доступ у поддержки.

#Порядок

  1. Проверьте доступность адреса командой curl прямо с сервера, где работаетЭто проверка для разработчика или администратора сервера, где выполняется PHP. Подключитесь по SSH к этому серверу, откройте терминал и выполните curl -I --max-time 15 https://api.example.com/, заменив URL фактическим адресом; -I использует HEAD и подходит не для каждого API, поэтому при ответе 405 проверьте разрешённый GET на тестовом адресе. Если даже обычный curl не подключается, ошибка не в настройке PHP, а в сети или доступности сервиса. Не публикуйте ключи доступа в командной строке и отчёте.
  2. Определите, на какой фазе тратится времяЧтобы понять место задержки, в терминале выполните curl -o /dev/null -sS -w 'dns=%{time_namelookup} tcp=%{time_connect} tls=%{time_appconnect} first=%{time_starttransfer} total=%{time_total}\n' https://api.example.com/ с реальным URL. dns — разрешение имени, tcp — начало соединения, tls — согласование шифрования, first — ожидание первых данных. Сравнивайте значения по нескольким запросам, а не по одному запуску; если сервер возвращает 429/503, увеличение таймаута не решит ограничения API.
  3. Проверьте DNS и IPv6На сервере Linux выполните getent ahosts api.example.com (имя заменить) и посмотрите доступные IPv4/IPv6. По отдельности проверьте curl -4 --max-time 10 -I URL и curl -6 --max-time 10 -I URL; если IPv6 не настроен, его проверка закономерно завершится ошибкой. Не фиксируйте CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4 во всём приложении без доказательства проблемы IPv6: это лишит его IPv6-only адресов.
  4. Проверьте исходящие правила файрвола и ограничения хостингаЕсли соединение не устанавливается, на сервере проверьте nc -zv хост 443 (действительные адрес и порт); при отсутствии nc используйте curl -v. На управляемом хостинге узнайте у поддержки, разрешён ли исходящий порт. Администратор проверяет локальные правила и облачные списки доступа; не открывайте все исходящие направления и не отключайте межсетевой экран ради проверки. Успех TCP не подтверждает корректный TLS или успешный ответ API.
  5. Увеличьте таймауты в коде, если сервер действительно медленныйЕсли DNS и соединение работают, а сервер отвечает медленно, откройте PHP-файл с curl_init() и настройте отдельно CURLOPT_CONNECTTIMEOUT => 5 (секунды подключения) и CURLOPT_TIMEOUT => 20 (предел всей операции). Выбирайте числа по требованиям вашего API и допустимой задержке страницы. При ошибке curl_exec() записывайте curl_errno, curl_error и время запроса в закрытый журнал без токенов; проверьте, какой этап превышает предел.
  6. Добавьте повторы с задержкойПовторяйте запрос только для временных сбоев (например, cURL error 28 или ответ 429/503), с ограниченным числом попыток и возрастающей задержкой. Для операций создания платежа, заказа или другой записи повторы допустимы лишь при поддержке ключа идемпотентности — иначе одна операция может выполниться дважды. Не повторяйте ошибки сертификата или отказ авторизации: сначала устраните первопричину. Проверьте, что вся цепочка попыток укладывается в общий лимит времени.
  7. Если API ограничивает частоту запросов, соблюдайте лимитыЕсли API возвращает HTTP 429, откройте в выводе запроса вкладку заголовков или используйте curl -i и найдите Retry-After (если передан). Уменьшите параллелизм и частоту задач в очереди или планировщике, а задержку считайте по документации провайдера; не выбирайте произвольный быстрый цикл повторов. После правки повторите несколько запросов и убедитесь, что не появляются новые 429/таймауты.
  8. Команды для отдельных ситуацийВыберите только подходящий вариант. Это не одна последовательность: часть команд диагностирует проблему, а часть меняет настройки или данные.
    Выберите подходящий вариант — это не команды для последовательного выполнения
    Вариант 1Проверка с сервера: время по фазам (замените URL)
    Linux · Терминал (Bash)Команда
    Проверка с сервера: время по фазам (замените URL)
    curl -o /dev/null -s -w "dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} start=%{time_starttransfer} total=%{time_total}\n" https://api.example.com/
    Вариант 2Проверка DNS и IPv4/IPv6 отдельно
    Linux · Терминал (Bash)Команда
    Проверка DNS и IPv4/IPv6 отдельно
    dig +short api.example.com
    curl -4 -I --max-time 10 https://api.example.com/
    curl -6 -I --max-time 10 https://api.example.com/
    Вариант 3Исходящие правила и порты
    Linux · Терминал (Bash)КомандаНужен sudo
    Исходящие правила и порты
    nc -zv api.example.com 443
    sudo iptables -L OUTPUT -n | head -20
    Вариант 4Диагностический GET с ограниченными таймаутами; не отключайте TLS и не повторяйте меняющие состояние запрос…
    PHPКоманда
    Диагностический GET с ограниченными таймаутами; не отключайте TLS и не повторяйте меняющие состояние запросы вслепую
    <?php
    // Пример лишь для безопасного на повторение запроса GET.
    $ch = curl_init('https://api.example.com/'); // замените URL
    curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 5,
    CURLOPT_TIMEOUT => 20,
    ]);
    $result = curl_exec($ch);
    if ($result === false) {
    error_log('cURL error '.curl_errno($ch).': '.curl_error($ch));
    } else {
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    if ($status >= 400) error_log('API returned HTTP '.$status);
    }
    curl_close($ch);

#Диагностика в расширенном режиме

Включите подробный вывод cURL: curl_setopt($ch, CURLOPT_VERBOSE, true) с записью в файл через CURLOPT_STDERR. В журнале видно, где остановился обмен: после Trying 203.0.113.5:443... — соединение не устанавливается; после SSL connection using — ждёт ответ приложения. Сравните результат с запросом из командной строки: если консольный curl быстрый, а PHP медленный, проверьте настройки прокси в php.ini и переменные окружения http_proxy.

Так эту ошибку тоже называют

Источники и обновления

Последнее обновление статьи: 2 ноября 2026. Версии программ и интерфейсы меняются — если шаги не совпадают с вашей версией, сверяйтесь с документацией производителя.