ProxyWing

PHP и прокси-сервер: как настроить и проверить запросы

Чтобы отправить запрос PHP через прокси-сервер, укажите его адрес, порт и протокол в HTTP-клиенте. Для доступа с авторизацией добавьте логин и пароль. Ниже приведены примеры cURL, stream-контекста и Symfony, а также проверка выходного IP и разбор ошибок. Настройка применяется к запросам скрипта на той машине, где выполняется PHP.

Опубликовано: 6 августа 2025 г.
Время чтения: 10 мин
Обновлено: 26 октября 2026 г.

Под запросом «PHP прокси сервер» встречаются две задачи: подключить PHP к готовому прокси и написать веб-посредник на PHP. В этой инструкции разобран первый вариант. Примеры не создают отдельный HTTP- или SOCKS5-сервер и не переключают подключение браузера посетителя.

Понадобятся доступ к прокси, разрешённый тестовый URL и расширение cURL для выбранной среды PHP. Сначала выполните один запрос и проверьте результат. Ротацию и параллельные обращения подключайте после этой проверки.

Как настроить прокси в PHP через cURL

Маршрут запроса PHP через прокси к сайту и отдельная область действия настройки cURL
Настройка cURL направляет запрос PHP через прокси и не переключает браузер посетителя.

Проверьте расширение и среду запуска

В командной строке выполните:

php -m
php --ini

В списке модулей должен быть curl. Если появляется Call to undefined function curl_init(), включите расширение для используемой среды. CLI и веб-сервер могут загружать разные файлы php.ini. После изменения конфигурации перезапустите соответствующий процесс.

Для просмотра версии подключённой библиотеки выполните:

php -r 'echo curl_version()["version"], PHP_EOL;'

Отправьте один тестовый запрос

Задайте переменные окружения PROXY_HOST и PROXY_PORT на машине, где выполняется PHP. В PROXY_HOST передайте только выданный хост или IP, без схемы, пути и учётных данных. Для авторизации задайте PROXY_USER и PROXY_PASS. При доступе по белому списку логин можно не задавать.

Сохраните код в proxy-test.php и запустите php proxy-test.php. Пример рассчитан на PHP 8 с cURL и HTTP-прокси, который поддерживает CONNECT к HTTPS-сайтам.

<?php
$host = getenv('PROXY_HOST') ?: '';
$port = (int) getenv('PROXY_PORT');
$user = getenv('PROXY_USER');
$password = getenv('PROXY_PASS');

if ($host === '' || $port < 1 || $port > 65535) {
    throw new RuntimeException('Задайте PROXY_HOST и PROXY_PORT');
}

$ch = curl_init('https://httpbin.org/ip');
$options = [
    CURLOPT_PROXY => $host,
    CURLOPT_PROXYPORT => $port,
    CURLOPT_PROXYTYPE => CURLPROXY_HTTP,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_NOPROXY => '',
    CURLOPT_FOLLOWLOCATION => false,
    CURLOPT_SSL_VERIFYPEER => true,
    CURLOPT_SSL_VERIFYHOST => 2,
];

if ($user !== false && $user !== '') {
    $options[CURLOPT_PROXYUSERNAME] = $user;
    $options[CURLOPT_PROXYPASSWORD] = $password === false ? '' : $password;
}

if (!curl_setopt_array($ch, $options)) {
    throw new RuntimeException('Не удалось задать параметры cURL');
}

$body = curl_exec($ch);
$errno = curl_errno($ch);
$error = curl_error($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$connectStatus = curl_getinfo($ch, CURLINFO_HTTP_CONNECTCODE);
unset($ch);

if ($body === false) {
    throw new RuntimeException(
        "cURL $errno; CONNECT $connectStatus; $error"
    );
}
if ($status < 200 || $status >= 300) {
    throw new RuntimeException("Неожиданный HTTP-статус: $status");
}

echo $body, PHP_EOL;

Тестовый сервис возвращает JSON с адресом, с которого пришёл запрос. Он получает диагностический запрос и видит выходной IP. Для рабочей системы можно использовать собственную точку контроля.

CURLOPT_PROXY задаёт адрес прокси. CURLOPT_PROXYPORT задаёт порт, CURLOPT_PROXYTYPE задаёт тип прокси. CURLOPT_RETURNTRANSFER возвращает тело ответа строкой. Таймаут подключения ограничен 10 секундами, весь запрос 30 секундами. Это параметры примера, их подбирают под задачу.

Пустой CURLOPT_NOPROXY отменяет исключения из NO_PROXY для этого запроса. Это помогает проверить именно маршрут через прокси. Перенаправления в тесте отключены, поэтому неожиданный ответ 3xx нужно разобрать отдельно.

Для HTTPS-назначения cURL создаёт туннель через HTTP-прокси с помощью CONNECT, затем проверяет сертификат сайта. Схема https:// в адресе сайта не означает, что нужен CURLPROXY_HTTPS. Этот тип используют для TLS-подключения к самому прокси.

Авторизация прокси: логин, пароль и белый список

В полном примере логин и пароль читаются из переменных окружения и передаются отдельными опциями CURLOPT_PROXYUSERNAME и CURLOPT_PROXYPASSWORD. Так пароль не попадает в строку URL и его проще исключить из журналов.

Для того же результата cURL поддерживает CURLOPT_PROXYUSERPWD со строкой логин:пароль. Используйте один понятный способ передачи реквизитов. Опции CURLOPT_USERPWD и CURLOPT_HTTPAUTH относятся к авторизации на целевом сайте и не заменяют авторизацию прокси.

Для HTTP-прокси метод авторизации задаёт CURLOPT_PROXYAUTH; по умолчанию используется Basic. Если провайдер требует другой метод, укажите поддерживаемый вариант. Base64 в Basic не шифрует учётные данные. При обычном HTTP-соединении до прокси они могут передаваться без TLS, даже если целевой сайт использует HTTPS.

При доступе по белому списку добавьте публичный исходящий IP машины, на которой запускается PHP. Для скрипта на хостинге это адрес хостинга. Если исходящий адрес изменится, список нужно обновить.

Не записывайте пароль, полный URL с реквизитами и заголовок Proxy-Authorization в общедоступные логи. Ответ 407 означает запрос авторизации прокси; проверьте учётные данные и разрешённый способ доступа.

Как использовать SOCKS5 в PHP

В массиве $options полного примера замените значение CURLOPT_PROXYTYPE:

CURLOPT_PROXYTYPE => CURLPROXY_SOCKS5_HOSTNAME,

Хост, порт и учётные данные возьмите для SOCKS5-подключения из своего заказа. У одного сервиса HTTP и SOCKS5 могут использовать разные порты.

CURLPROXY_SOCKS5_HOSTNAME передаёт разрешение имени целевого сайта прокси-серверу. При CURLPROXY_SOCKS5 имя назначения разрешается на стороне клиента. Имя самого входного прокси всё равно нужно разрешить до подключения.

SOCKS5 сам по себе не шифрует трафик. Защита HTTPS-запроса зависит от TLS до сайта и проверки его сертификата. Для обычного HTTP-назначения такой защиты нет.

file_get_contents с HTTP-прокси

Stream-контекст подходит для простого запроса по HTTP, если включён allow_url_fopen. Пример ниже намеренно использует HTTP-назначение. Для HTTPS через CONNECT, SOCKS5 и авторизации прокси используйте приведённый пример cURL.

<?php
$host = getenv('PROXY_HOST') ?: '';
$port = (int) getenv('PROXY_PORT');
if ($host === '' || $port < 1 || $port > 65535) {
    throw new RuntimeException('Задайте PROXY_HOST и PROXY_PORT');
}

$context = stream_context_create([
    'http' => [
        'proxy' => "tcp://$host:$port",
        'request_fulluri' => true,
        'timeout' => 15,
        'follow_location' => 0,
        'header' => "Connection: close\r\n",
    ],
]);

$body = file_get_contents('http://example.com/', false, $context);
if ($body === false) {
    throw new RuntimeException('HTTP-запрос через прокси не выполнен');
}
echo $body;

В опции proxy нужен транспортный адрес tcp://хост:порт. request_fulluri отправляет полный адрес назначения в строке HTTP-запроса. Пример не передаёт пароли и не создаёт TLS-туннель.

Возврат строки ещё не подтверждает, что получен ожидаемый документ: проверяйте HTTP-статус и содержимое. Не подавляйте предупреждения PHP без собственной обработки и журнала ошибок.

Прокси в Symfony HttpClient и BrowserKit

Для отдельного проекта установите компоненты через Composer:

composer require symfony/http-client symfony/browser-kit

Перед запуском задайте PROXY_URL в окружении: полный URL вашего HTTP-прокси с портом. При авторизации используйте документированный формат реквизитов и кодирование специальных символов. Храните значение как секрет.

<?php
require __DIR__ . '/vendor/autoload.php';

use Symfony\Component\BrowserKit\HttpBrowser;
use Symfony\Component\HttpClient\HttpClient;

$proxyUrl = getenv('PROXY_URL');
if ($proxyUrl === false || $proxyUrl === '') {
    throw new RuntimeException('Задайте PROXY_URL');
}

$http = HttpClient::create([
    'proxy' => $proxyUrl,
    'no_proxy' => '',
    'timeout' => 10,
    'max_duration' => 30,
    'max_redirects' => 0,
]);

$response = $http->request('GET', 'https://httpbin.org/ip');
if ($response->getStatusCode() !== 200) {
    throw new RuntimeException('Проверка IP не завершилась с HTTP 200');
}
echo $response->getContent(), PHP_EOL;

$browser = new HttpBrowser($http);
$browser->request('GET', 'https://example.com/');

Настройка proxy принадлежит HttpClient. HttpBrowser использует переданный клиент для запросов, переходов по ссылкам и отправки форм. BrowserKit не выполняет JavaScript как обычный браузер. Для содержимого, создаваемого скриптами страницы, нужен отдельный подход к тестированию.

В приложении перехватывайте транспортные исключения Symfony и проверяйте HTTP-ответ отдельно. Параметр timeout ограничивает ожидание сетевой активности, а max_duration общую длительность запроса.

Ротация прокси в PHP

Готовый ротируемый шлюз или список серверов

У ротируемого сервиса хост и порт могут оставаться прежними, пока меняется выходной IP. Правило смены задаётся в параметрах продукта. Sticky-сессия удерживает адрес в пределах доступных условий; её формат и срок проверяют у выбранного сервиса.

Если вы используете несколько выданных серверов, скрипт может выбирать очередной адрес из списка. Это переключение точек подключения. Разные точки не гарантируют разные выходные IP.

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

Как менять адрес без повреждения операции

  1. Завершите текущую серию запросов и дождитесь ответов.
  2. Выберите следующую точку подключения или запустите ротацию по правилам своего продукта.
  3. Создайте новое соединение и проверьте выходной IP тем же PHP-клиентом.
  4. Начинайте следующую задачу после успешной проверки.

Для запросов внутри одной авторизованной сессии учитывайте привязку сайта к IP и cookie. Смена адреса не удаляет cookie, не сбрасывает лимиты аккаунта и может вызвать дополнительную проверку.

Повтор после таймаута тоже требует проверки. Сервер мог выполнить действие до обрыва ответа. Нельзя автоматически повторять оплату, создание заказа или другую изменяющую операцию без защиты от дублей.

Для сценария с IP оператора есть практическая инструкция по мобильным прокси и ротации.

Ошибки cURL и HTTP: что проверять

Сетевой сбой и HTTP-ответ проверяются отдельно. curl_exec() может вернуть строку с ответом 403 или 429, поэтому одной проверки на false недостаточно. Для HTTPS через HTTP-прокси код ответа на CONNECT доступен через CURLINFO_HTTP_CONNECTCODE.

Симптом Что проверить
curl_init() не найдена Расширение cURL и php.ini именно той среды, где выполняется запрос
cURL 5 Разрешается ли имя прокси, нет ли опечатки в хосте
cURL 6 Разрешается ли имя назначения; для SOCKS5 проверьте выбранный режим DNS
cURL 7 Адрес, порт, сетевой доступ и соответствие HTTP или SOCKS5
cURL 28 Таймаут, нагрузку, размер ответа и доступность назначения
cURL 60 Цепочку сертификатов, системное время и хранилище доверенных CA
HTTP 407 или CONNECT 407 Авторизацию прокси и белый список
HTTP 401 Авторизацию на целевом ресурсе, если ответ пришёл от него
HTTP 403 Ограничения ответившего сервера, права аккаунта и условия доступа
HTTP 429 Лимит запросов; уменьшите параллельность и соблюдайте Retry-After, если он есть
HTTP 5xx Какой узел вернул ответ и доступен ли целевой сервис

При ошибке сертификата исправьте доверенную цепочку или конфигурацию. Не отключайте CURLOPT_SSL_VERIFYPEER и CURLOPT_SSL_VERIFYHOST ради успешного теста.

Ротация не исправляет неверный пароль, отсутствие расширения или ошибку TLS. Для 403 и 429 сначала разберите причину и допустимую частоту запросов. Новый IP не гарантирует доступ.

Как проверить IP и подготовить скрипт к работе

  1. Выполните диагностический запрос напрямую и запишите наблюдаемый адрес машины с PHP.
  2. Повторите его через прокси тем же клиентом. В примере адрес приходит в JSON-ответе.
  3. Сверьте результат с ожидаемым выходом сервиса. Входной адрес прокси может отличаться от выходного.
  4. Проверьте один разрешённый запрос к рабочему назначению. Совпадение IP в диагностике не подтверждает доступ к каждому сайту.
  5. Отдельно проверьте авторизацию, таймаут и ожидаемое поведение при недоступном прокси.

CURLINFO_PRIMARY_IP показывает адрес узла сетевого соединения. При работе через прокси это обычно входной прокси; такое поле не заменяет проверку адреса, который видит сайт.

Записывайте время, идентификатор конфигурации прокси, код cURL, HTTP-статус и длительность. Исключите пароль, токены, cookie и секретные параметры URL. CURLOPT_VERBOSE используйте только в закрытой диагностике с проверкой содержимого журнала.

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

Если приложение принимает целевой URL от пользователя, добавьте отдельную защиту от SSRF: проверку разрешённых назначений, портов и перенаправлений. Не публикуйте тестовый PHP-файл как открытый сервис для загрузки произвольных адресов.

Где взять прокси для PHP

Для скрипта с постоянным выходным адресом выберите датацентровые IPv4-прокси ProxyWing. Если задача требует пула адресов и управления сессиями, проверьте условия резидентских прокси ProxyWing. Сопоставьте протокол, способ авторизации и правила ротации с вашим PHP-клиентом.

Для резидентских прокси действует промокод WINGRESI10: скидка 10%.

После получения доступа перенесите выданные параметры в окружение приложения. Начните с одного проверочного запроса. Расширяйте нагрузку после проверки ошибок, таймаутов и поведения сессии.

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

Можно ли создать полноценный прокси-сервер этим кодом?

Примеры подключают PHP как клиента к готовому серверу. Веб-скрипт, который загружает URL и возвращает содержимое, решает другую задачу и требует контроля доступа, разрешённых назначений и ресурсов. Он не становится универсальным HTTP- или SOCKS5-прокси.

Почему в браузере IP другой?

PHP выполняется на сервере или в командной строке и имеет собственный маршрут. Прокси браузера и прокси PHP настраиваются отдельно. Проверяйте IP запросом из того же скрипта.

Можно ли использовать HTTPS-сайт через HTTP-прокси?

Да, если прокси разрешает CONNECT к нужному назначению и порту. TLS устанавливается между PHP-клиентом и сайтом внутри туннеля. HTTPS-подключение к самому прокси настраивается отдельно.

Почему новый IP не появляется после ротации?

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

Статью написал:

Alexandre Parfonov

Фулстек AI-инженер

Александр привносит в инженерную команду Proxywing глубокую фулстек-экспертизу — от архитектуры бэкенда и оптимизации производительности до AI-ориентированных процессов разработки. Его практический опыт охватывает Node.js, React, облачную инфраструктуру и RAG-пайплайны, что позволяет одинаково уверенно работать как с внутренней логикой прокси-платформы, так и с пользовательской частью продукта. В Proxywing Александр сосредоточен на проектировании отказоустойчивых систем, устранении узких мест производительности и внедрении современных AI-инструментов в процесс разработки. Вне кода он увлечён исследованием передовых подходов в AI-инженерии и созданием сайд-проектов, расширяющих технические горизонты.

Все статьи автора (58)