The SOCKS5 protocol lets a client ask the proxy to connect either to an IP address or to a hostname. Which one it sends is the client's decision, and the URL scheme is how you tell many clients:
socks5://resolves the hostname on your machine and sends the proxy an IP address.socks5h://sends the hostname and lets the proxy resolve it. Thehstands for hostname.
The protocol is the same in both cases; only the lookup moves.
Why it matters
Resolving locally has three costs:
- A DNS leak. Your own resolver sees every hostname you visit.
- The wrong server. CDNs answer DNS with an edge node near the resolver asking. Resolve in London, exit in Tokyo, and you reach a London node through a Japanese IP, which can change the content and looks odd to the site.
- Names the proxy knows but you do not fail to resolve locally.
For scraping through a proxy, socks5h is almost always what you want.
Using it
curl and Python requests (with requests[socks] installed) both accept the scheme:
curl -x socks5h://USERNAME:PASSWORD@HOST:PORT "https://api.ipify.org?format=json"
proxy = "socks5h://USERNAME:PASSWORD@HOST:PORT"
requests.get(url, proxies={"http": proxy, "https": proxy})
curl also has the flag form --socks5-hostname HOST:PORT. Other tools use a setting instead of a scheme: Firefox calls it "Proxy DNS when using SOCKS v5", as the Firefox guide shows. Check your library's documentation, because some treat socks5:// as remote resolution already and some do not accept socks5h at all.
Common confusion
socks5h is not a separate protocol or a separate port. It is the same SOCKS5 proxy, asked to do the DNS lookup.