You have set up a SOCKS5 proxy, traffic seems to be going through it, the IP displayed in the browser is correct — but websites still see your real region or your provider starts to suspect something. The reason is almost always the same: DNS requests are sent directly from your computer, bypassing the proxy. In this article, we will explore why this happens, how SOCKS5 differs from SOCKS5h, and how to close this leak in code and in ready-made tools.
What is SOCKS5 and how does it differ from SOCKS5h
SOCKS5 is a proxy protocol that operates at the TCP/UDP connection level and does not inspect the contents of packets, unlike HTTP(S) proxies. This makes it versatile: you can proxy almost any traffic through SOCKS5 — browser, Telegram, torrent client, Python script. However, the classic implementation of SOCKS5 has an important feature: domain name resolution (DNS) is performed by default on the client side, that is, on your computer, rather than on the proxy server side.
SOCKS5h is the same protocol, but with the "h" (hostname) modifier, which instructs the client application not to resolve the domain itself, but to send it as is to the proxy server, which will then perform the DNS request on its behalf. The difference is one letter, but the implications for anonymity and operational stability are significant.
It is important to understand: SOCKS5h is not a separate protocol, but an agreement at the level of a specific library or application on how to format the request to the proxy. The proxy server operates the same way in both cases; the difference is only in who initiates the DNS resolution — the client or the server.
Why DNS requests bypass the proxy
When you access an address like https://example.com, before establishing a connection, the application must find out the IP address of that domain. This process is called DNS resolution. When using a regular SOCKS5, many libraries and system settings perform resolution through the system DNS server — the one configured in your provider's or router's network settings.
As a result, a paradoxical situation arises: the HTTP/TCP traffic goes through the proxy and appears to come from the proxy server's IP, while the DNS request "What is the IP of example.com?" is sent directly from your real IP to the provider's DNS server. This is a DNS leak. A website or service that analyzes network activity at a deeper level (such methods are actively used by anti-fraud systems at Facebook, Google, TikTok) can see a discrepancy between the connection IP and the source of the DNS request.
The reason is that the SOCKS5 protocol was originally developed as a transport layer for already established IP connections, not for name resolution. Developers of libraries and utilities had to separately implement the function of transmitting DNS requests through the tunnel — hence SOCKS5h appeared as a clear indication "resolve the domain yourself, not me."
What are the practical dangers of a DNS leak
For a parser or automation script developer, a DNS leak is not an abstract theory, but a concrete reason for account blocks and bans. Let's explore a few scenarios.
Parsing marketplaces and websites. If you are scraping Wildberries, Ozon, or another resource through a proxy from the desired region, but DNS requests go through the provider, the anti-bot system may detect a discrepancy in geolocation and increase the session's suspicion level — up to captcha or temporary blocking of the proxy IP.
Multi-accounting and traffic arbitration. When working with Facebook Ads, TikTok Ads, or Google Ads across multiple accounts, anti-fraud systems analyze dozens of parameters, including DNS fingerprint. If DNS requests from several "different" accounts suddenly go through the same DNS server of the provider, it signals to merge accounts into one cluster — and as a consequence, a chain of bans (chain-ban).
Automation in Selenium/Playwright. Scripts that emulate user actions in the browser are particularly vulnerable: the browser itself may resolve DNS through the OS's system settings, ignoring the proxy set only for HTTP traffic. As a result, the entire other network fingerprint reveals the real location.
For most of these tasks, it is critical to use residential proxies with correctly configured DNS resolution on the server side — this significantly reduces the risk of detection based on network characteristics.
How to check for a DNS leak
Before fixing the problem, it is worth ensuring that it actually exists. Here are a few quick ways to check.
- Open the site
dnsleaktest.comoripleak.netthrough your proxy connection and run the extended test (Extended test). - Compare the list of DNS servers in the results with what your internet provider actually is. If you see the provider instead of the proxy data center — the leak is confirmed.
- For the command line, use the combination of
tcpdumporWireshark, filtering traffic by port 53 (DNS) — if packets go directly to the provider's server instead of through the proxy tunnel, the problem is on your side. - In Python, you can quickly check resolution manually using
socket.getaddrinfo()before and after enabling the proxy — if the IP matches the result without the proxy, resolution is happening locally.
Fixing in Python (requests, PySocks, urllib3)
The most common mistake in Python scripts is using the requests library together with PySocks without explicitly specifying the socks5h scheme. The difference is one character, but it determines who resolves the domain.
import requests
# BAD: DNS resolves locally, bypassing the proxy
proxies_leak = {
"http": "socks5://user:pass@proxy_host:1080",
"https": "socks5://user:pass@proxy_host:1080",
}
# GOOD: DNS resolves on the proxy server side
proxies_safe = {
"http": "socks5h://user:pass@proxy_host:1080",
"https": "socks5h://user:pass@proxy_host:1080",
}
response = requests.get("https://example.com", proxies=proxies_safe, timeout=10)
print(response.status_code)
print(response.text[:200])
For the socks5h scheme to work correctly through requests, you will need to install the dependency:
pip install "requests[socks]" PySocks
If you are using low-level urllib3 directly, the example will look like this:
from urllib3.contrib.socks import SOCKSProxyManager
proxy = SOCKSProxyManager(
"socks5h://user:pass@proxy_host:1080",
num_pools=10
)
response = proxy.request("GET", "https://example.com")
print(response.status)
For asynchronous scripts using aiohttp, the aiohttp-socks library is used, where the scheme is specified in the same way:
import aiohttp
from aiohttp_socks import ProxyConnector
connector = ProxyConnector.from_url("socks5h://user:pass@proxy_host:1080")
async def fetch():
async with aiohttp.ClientSession(connector=connector) as session:
async with session.get("https://example.com") as resp:
print(await resp.text())
Fixing in curl
In curl, there are also two different flags for SOCKS5 proxies, and confusion between them is a classic cause of DNS leaks in bash scripts.
# BAD: resolving on the local machine
curl --socks5 proxy_host:1080 https://example.com
# GOOD: resolving on the proxy server side
curl --socks5-hostname proxy_host:1080 https://example.com
# With authorization
curl --socks5-hostname user:pass@proxy_host:1080 https://example.com
The --socks5-hostname flag is a direct analog of socks5h in other tools. It tells curl: "do not touch DNS, just pass the domain to the proxy server as is."
Fixing in Selenium and Playwright
With browser automation, the situation is more complicated: Chrome or Firefox may resolve DNS by default through system settings, ignoring the proxy set only at the network request level. For Selenium with Chrome, you need to explicitly enable resolution through the proxy using a browser launch flag.
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--proxy-server=socks5://proxy_host:1080")
# Critically important flag: resolve DNS through the proxy
options.add_argument("--host-resolver-rules=MAP * ~NOTFOUND , EXCLUDE proxy_host")
driver = webdriver.Chrome(options=options)
driver.get("https://example.com")
In Playwright, the situation is simpler: the library resolves DNS through the proxy by default if it is specified in the browser context configuration.
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(
proxy={"server": "socks5://proxy_host:1080"}
)
page = browser.new_page()
page.goto("https://example.com")
print(page.title())
browser.close()
However, it is recommended to always check the actual behavior through dnsleaktest.com after configuration — behavior may vary between versions of Chromium.
Configuration in anti-detect browsers
If you are not writing code but working through anti-detect browsers like Dolphin Anty, AdsPower, Multilogin, or GoLogin — the good news is that most of them already resolve DNS through the proxy server automatically when selecting the SOCKS5 protocol, without the need to specify "h" manually. This is one of their key advantages over custom scripts.
Nevertheless, it is worth checking this in practice: open a profile in the anti-detect browser, go to dnsleaktest.com, and run the extended test right inside the profile. If you see DNS servers corresponding to the region of your proxy, rather than your real provider — the configuration is correct. If not, contact the support of the specific anti-detect browser or switch the proxy type to HTTP(S), where the DNS resolution problem does not arise as sharply, since HTTP proxies always work with full URLs.
For farming accounts on Instagram, TikTok, and managing advertising accounts on Facebook Ads, mobile proxies perform well — due to dynamic IP rotation from cellular operators, they are less likely to raise suspicion from anti-fraud systems, even if a small DNS leak occurred somewhere in the chain.
Comparison table of proxy protocols
| Protocol | Who resolves DNS | Leak risk | Where to apply |
|---|---|---|---|
| SOCKS5 | Client (your computer) | High | Only if DNS is not critical (local tests) |
| SOCKS5h | Proxy server | Low | Parsing, multi-accounting, automation |
| HTTP/HTTPS proxy | Proxy server (by default) | Low | Web traffic, browsers, API requests |
If your task is high-speed data collection without tying to a specific user region, consider data center proxies — they are cheaper per volume of traffic and work great in conjunction with SOCKS5h for scraping, where speed is more important than masquerading as a residential user.
Checklist before launching the project
- Use the
socks5h://scheme, notsocks5://in all libraries and configurations. - For curl, use the
--socks5-hostnameflag, not--socks5. - In Selenium, the
--host-resolver-rulesflag is added or Playwright is used with built-in proxy resolution. - Checked the result on dnsleaktest.com or ipleak.net after configuration, not before.
- Tested the DNS fingerprint inside the anti-detect browser profile, not just the external IP.
- For tasks with high anonymity requirements, consider residential or mobile proxies instead of data center ones.
Conclusion
The difference between SOCKS5 and SOCKS5h is literally one letter, but it determines who resolves the DNS request: your computer or the proxy server. A DNS leak is one of the most inconspicuous yet frequent causes of detection when scraping, multi-accounting, and automating advertising accounts. Checking through dnsleaktest.com and explicitly specifying the socks5h scheme in code, curl commands, or browser automation settings closes this gap in just a few minutes.
If you are just choosing infrastructure for the task — for scraping and working with APIs, data center proxies are more suitable, for multi-accounting and social networks — residential proxies, and for the most natural network fingerprint when working with mobile applications — mobile proxies. In any of these cases, correctly configuring DNS resolution through SOCKS5h remains a mandatory step before launching the project into production.