Буква «h» в socks5h:// означает, что клиент должен передать прокси имя сайта, а не пытаться сам определять его IP адрес. Без неё DNS запрос уходит с вашей машины на ваш собственный резолвер, и тот в итоге знает каждый сайт, который вы открываете через прокси.
Однако одна лишь схема рассказывает только половину истории: что будет с обычным socks5://, зависит от клиента. В октябре 2026 года мы прогнали через наш собственный SOCKS5 сервер 22 HTTP клиента, библиотеки и браузера, по три прогона каждый, и записали, что именно отправлял каждый из них. 8 из 22 при socks5:// резолвили имя локально. Остальные 14, включая все браузеры, которые мы проверили, передавали имя прокси даже без «h».
Короткий ответ
- curl, PHP cURL, Python requests и urllib3, Node.js socks-proxy-agent (с http, axios или got), а также реле proxy-chain сливают DNS при
socks5://. Укажитеsocks5h://, и утечка исчезнет у каждого из них. - Python httpx, aiohttp-socks, Go net/http и Node undici с fetch-socks отправляют имя прокси даже с обычным
socks5://. aiohttp-socks вообще не принимаетsocks5h://и падает с ValueError. - Chrome, Chromium, Puppeteer, Playwright, Firefox и Camoufox не сливали DNS. В Firefox утечка появляется только если выключить
network.proxy.socks5_remote_dns. - proxychains-ng безопасен с конфигурацией по умолчанию, где включён
proxy_dns. Уберите эту строку, и появится утечка.
Как исправить: настройки, которые отправляют имя прокси
Каждый пример ниже запускался на нашем тестовом сервере с логином и паролем, и во всех случаях прокси получал имя сайта, а не IP. Замените user:pass@host:port на данные вашего прокси.
curl
curl -x socks5h://user:pass@host:port https://example.com
curl --socks5-hostname host:port --proxy-user user:pass https://example.com
export ALL_PROXY=socks5h://user:pass@host:port
PHP cURL
$ch = curl_init("https://example.com");
curl_setopt($ch, CURLOPT_PROXY, "host:port");
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME);
curl_setopt($ch, CURLOPT_PROXYUSERPWD, "user:pass");
URL прокси тоже подходит: установите CURLOPT_PROXY в socks5h://user:pass@host:port.
Python requests и urllib3
pip install "requests[socks]"
import requests
proxy = "socks5h://user:pass@host:port"
requests.get("https://example.com", proxies={"http": proxy, "https": proxy})
from urllib3.contrib.socks import SOCKSProxyManager
http = SOCKSProxyManager("socks5h://user:pass@host:port")
Python httpx и aiohttp
Оба и так отправляют имя при socks5://. Оставляйте эту схему: aiohttp-socks падает на socks5h://.
pip install "httpx[socks]" aiohttp-socks
import httpx
client = httpx.Client(proxy="socks5://user:pass@host:port")
from aiohttp_socks import ProxyConnector
connector = ProxyConnector.from_url("socks5://user:pass@host:port")
# aiohttp.ClientSession(connector=connector)
Node.js: axios, got, http
import axios from "axios"
import got from "got"
import { SocksProxyAgent } from "socks-proxy-agent"
const agent = new SocksProxyAgent("socks5h://user:pass@host:port")
await axios.get("https://example.com", { httpAgent: agent, httpsAgent: agent, proxy: false })
await got("https://example.com", { agent: { http: agent, https: agent } })
Puppeteer или Playwright с SOCKS5 логином через proxy-chain
import puppeteer from "puppeteer"
import { anonymizeProxy, closeAnonymizedProxy } from "proxy-chain"
const proxyUrl = await anonymizeProxy("socks5h://user:pass@host:port")
const browser = await puppeteer.launch({ args: [`--proxy-server=${proxyUrl}`] })
// ...
await browser.close()
await closeAnonymizedProxy(proxyUrl, true)
Firefox
По умолчанию включено. Если в профиле это выключено, верните настройку в about:config или в user.js профиля:
user_pref("network.proxy.socks5_remote_dns", true);
proxychains-ng
Проверьте, что proxy_dns есть в конфиге и не закомментирован:
strict_chain
proxy_dns
[ProxyList]
socks5 host port user pass
Go и браузеры
Менять ничего не нужно. В нашем тесте Go net/http, Chrome, Chromium, Puppeteer без реле, Playwright и Camoufox отправляли имя при обычном socks5://.
Что меняет буква «h»
Когда клиент просит SOCKS5 прокси открыть соединение, он указывает назначение одним из двух способов: IP адресом или доменным именем (RFC 1928 называет это типами адреса). При доменном имени адрес ищет прокси на своей стороне. При IP адресе поиск уже произошёл на вашей машине, через DNS резолвер вашей сети.
socks5h это способ curl сказать «отправь имя», и библиотеки для Python и Node повторили эту конвенцию. На проводе в обоих случаях используется один и тот же SOCKS5, отличается только тип адреса в одном конкретном запросе.
Как мы тестировали
Мы написали небольшой SOCKS5 сервер, который записывает, что именно каждый клиент кладёт в запрос на соединение: имя или IP. Каждый тест открывал свой уникальный хостнейм вида <test>-<random>.127.0.0.1.sslip.io. Наш сервер извлекал целевой адрес прямо из этого имени без какого либо DNS запроса, поэтому любой DNS запрос для этого имени, который появлялся в нашем дампе пакетов, мог исходить только от клиента.
Каждый клиент открывал страницу один раз за раунд, три раунда подряд, 21 октября 2026 года. Для каждого клиента и каждой настройки результат совпал во всех трёх раундах.

Утекающие запросы не оставались на машине. В curl с обычным socks5:// A и AAAA запросы для тестового имени уходили к DNS резолверу нашего хостинг провайдера, то есть к стороне, которая не является прокси и не должна видеть, какие сайты вы открываете через него.

Результаты: кто отправляет имя прокси
| Клиент | Что мы задавали | Отправлено прокси | Локальный DNS запрос |
|---|---|---|---|
| curl | -x socks5://, --socks5, ALL_PROXY=socks5:// | IP | Да |
| curl | -x socks5h://, --socks5-hostname | Имя | Нет |
| PHP cURL | CURLOPT_PROXY socks5://, CURLPROXY_SOCKS5 | IP | Да |
| PHP cURL | CURLOPT_PROXY socks5h://, CURLPROXY_SOCKS5_HOSTNAME | Имя | Нет |
| Python requests | socks5:// | IP | Да |
| Python requests | socks5h:// | Имя | Нет |
| Python urllib3 | socks5:// | IP | Да |
| Python urllib3 | socks5h:// | Имя | Нет |
| Python httpx | socks5:// или socks5h:// | Имя | Нет |
| Python aiohttp + aiohttp-socks | socks5:// | Имя | Нет |
| Python aiohttp + aiohttp-socks | socks5h:// | Ошибка: схема не принимается | |
| Go net/http | socks5:// или socks5h:// | Имя | Нет |
| Node.js http, axios, got + socks-proxy-agent | socks5:// | IP | Да |
| Node.js http, axios, got + socks-proxy-agent | socks5h:// | Имя | Нет |
| Node.js undici + fetch-socks | type 5 | Имя | Нет |
| proxy-chain (Apify) | socks5:// с логином | IP | Да |
| proxy-chain (Apify) | socks5h:// с логином | Имя | Нет |
| proxychains-ng | конфиг по умолчанию (proxy_dns) | Имя | Нет |
| proxychains-ng | без proxy_dns | IP | Да |
| Google Chrome | --proxy-server=socks5:// | Имя | Нет |
| Chromium, Puppeteer | --proxy-server=socks5:// | Имя | Нет |
| Playwright: Chromium, Firefox, WebKit | proxy: { server: 'socks5://…' } | Имя | Нет |
| Firefox, Firefox ESR | SOCKS v5 в настройках соединения | Имя | Нет |
| Firefox | network.proxy.socks5_remote_dns = false | IP | Да |
| Camoufox | proxy: socks5:// | Имя | Нет |
Версии: curl 8.5.0, PHP 8.5.12 с libcurl 8.22.0, Python 3.15 с requests 2.34.2, urllib3 2.8.0, httpx 0.28.1, aiohttp 3.14.5 и aiohttp-socks 0.12.0, Go 1.27.3, Node.js 24.22 с socks-proxy-agent 10.1.0, axios 1.20.0, got 16.1.0, undici 8.12.3, fetch-socks 1.3.3 и proxy-chain 3.0.1, proxychains-ng 4.17, Google Chrome 156, Firefox 158 и Firefox ESR 153, Playwright 1.62.1, puppeteer-core 25.15.0, Camoufox 0.5.8.
curl и всё, что построено на libcurl
curl это источник socks5h, и здесь всё видно особенно чётко. -x socks5://, флаг --socks5 и переменная окружения ALL_PROXY=socks5://… заставляли curl резолвить имя самостоятельно и отправлять прокси IP. -x socks5h:// и --socks5-hostname отправляли имя.
Расширение cURL в PHP использует ту же библиотеку и ведёт себя так же. В PHP тип прокси часто задают константой, а не URL, поэтому исправление там это CURLPROXY_SOCKS5_HOSTNAME вместо CURLPROXY_SOCKS5.
Python: зависит от библиотеки
requests и urllib3 работают через PySocks и следуют конвенции curl: socks5:// резолвился локально при каждом запуске, socks5h:// отправлял имя. Это самый распространённый вариант в скрейпинге, и именно его повторяет большинство туториалов.
httpx и aiohttp-socks отправляли имя даже с socks5://. Подвох в другую сторону: aiohttp-socks отвергает socks5h:// с ошибкой ValueError: Invalid scheme component, поэтому строка прокси, которая корректна для requests, ломает aiohttp скрейпер. Там оставляйте socks5://, прокси и так резолвит на своей стороне.
Go и Node.js
Go net/http отправлял имя и с socks5://, и с socks5h://, поэтому Go программы, которые берут прокси из URL или из HTTP_PROXY, безопасны в обоих вариантах.
В Node.js socks-proxy-agent это обычный способ подключить SOCKS5 прокси к встроенному модулю http, axios или got, и он следует curl: socks5:// резолвился локально, socks5h:// отправлял имя. undici с fetch-socks, где прокси задаётся объектом, а не URL, отправлял имя.
Браузеры не сливали DNS
Каждый браузер, который мы прогнали, отправлял имя прокси: Google Chrome и Chromium с --proxy-server=socks5://, Puppeteer, все три движка Playwright, Firefox и Firefox ESR с SOCKS v5 в настройках соединения, а также Camoufox. Chromium под Puppeteer также проксировал по имени собственные фоновые запросы, например к аккаунтам Google.
В Firefox есть две настройки с похожими именами, и многие руководства до сих пор указывают не ту. network.proxy.socks_remote_dns больше ничего не меняет для SOCKS5: мы ставили её в false, и Firefox всё равно отправлял имя. Важна настройка network.proxy.socks5_remote_dns, она включена по умолчанию. Выключение её было единственным способом заставить Firefox допустить утечку.
Браузеры под управлением Playwright и Camoufox не принимали SOCKS5 прокси с логином и паролем: запуск падал с сообщением «Browser does not support socks5 proxy authentication». Большинство ротационных резидентских прокси и мобильных прокси требуют авторизацию, и это приводит к следующей проблеме.
Ловушка: реле для SOCKS5 с паролем
Обычный обход этого ограничения это локальное реле, которое принимает подключение браузера без пароля и пересылает его на SOCKS5 прокси с паролем. Популярный вариант для Puppeteer и Playwright это proxy-chain от Apify.
Если передать socks5://user:pass@host:port, proxy-chain сам резолвил имя и отдавал прокси IP, хотя браузер за ним отправлял имя. Если передать socks5h://user:pass@host:port, он передавал имя. Получается, браузер, который сам по себе никогда не течёт, начинает течь в тот момент, когда вы ставите перед ним это реле с неправильной схемой.
proxychains-ng
proxychains-ng, который принудительно гонит любую программу через прокси, поставляется с включённым proxy_dns в конфиге по умолчанию, и с ним имя уходило прокси. Конфиги, скопированные из старых руководств, иногда не содержат этой строки или держат её закомментированной. Без неё программа за proxychains резолвила имя локально.
Почему локальный резолв важен
Локальный резолв уходит к резолверу вашей сети, поэтому он видит каждый сайт, который вы открываете через прокси, а тест на DNS утечки покажет ваш реальный резолвер рядом с IP прокси.
Запрос также выполняется из вашей локации: сайт за CDN может отдать вашей машине адрес сервера рядом с вами, а не рядом с прокси, и запрос в итоге попадёт на сервер, выбранный для другой страны.
Как проверить свою конфигурацию
Для curl сравните страницу теста DNS утечки, открытую с -x socks5:// и с -x socks5h://, список резолверов должен отличаться. Для библиотеки надёжная проверка та же, что использовали мы: направьте клиента на SOCKS5 сервер, который вы контролируете, и логируйте, несёт ли запрос на соединение имя или IP. Если вам нужно лишь увидеть выходной IP прокси и его локацию, наш прокси-чекер покажет это в браузере.
О других различиях между SOCKS5 и HTTP прокси, включая скорость, UDP и WebRTC, читайте в нашем тесте SOCKS5 против HTTPS прокси на 11 реальных прокси.
FAQ
- В чём разница между socks5 и socks5h?
- В случае socks5h клиент передаёт прокси доменное имя сайта, а прокси сам выполняет резолв адреса. При socks5 curl и библиотеки, которые копируют его поведение, резолвят адрес на вашей машине и отправляют прокси только IP, поэтому ваш DNS-резолвер видит каждый сайт, который вы открываете. Некоторые клиенты передают имя даже с socks5: в нашем тесте 22 клиентов это делали httpx, aiohttp-socks, Go, undici с fetch-socks и все браузеры.
- Протекает ли DNS через socks5://?
- В 8 из 22 протестированных нами клиентов да: curl, PHP cURL, Python requests и urllib3, Node.js socks-proxy-agent с http, axios и got, а также релей proxy-chain. Во всех этих случаях socks5h:// перекрывал утечку.
- socks5h это другой протокол?
- Нет. Это тот же SOCKS5. Буква h лишь говорит клиенту подставлять в запрос на подключение доменное имя, а не IP-адрес. Подойдёт любой SOCKS5-прокси, который принимает доменные имена.
- Утекает ли DNS в браузерах через SOCKS5-прокси?
- В нашем тесте нет. Google Chrome, Chromium, Puppeteer, Playwright с Chromium, Firefox и WebKit, Firefox, Firefox ESR и Camoufox всегда отправляли имя на прокси. Firefox начал протекать только после того, как мы отключили network.proxy.socks5_remote_dns.
- Какая настройка Firefox управляет удалённым DNS для SOCKS5?
- network.proxy.socks5_remote_dns, по умолчанию включена. Более старая network.proxy.socks_remote_dns, которую упоминают во многих гайдах, никак не влияла на SOCKS5 в Firefox 158 и Firefox ESR 153.
- Почему aiohttp отклоняет socks5h://?
- aiohttp-socks не знает схему socks5h и выбрасывает ValueError: Invalid scheme component. Используйте с ним socks5://, в нашем тесте он и так отправлял имя на прокси.
- Как использовать SOCKS5-прокси с паролем в Puppeteer или Playwright без утечки DNS?
- Chromium, Firefox и WebKit в Playwright не принимают логин и пароль для SOCKS5, поэтому обычно перед ними ставят локальный релей вроде proxy-chain. Укажите релею socks5h://user:pass@host:port. С socks5:// proxy-chain сам резолвил имена и отправлял прокси IP-адреса.