Blog

SOCKS5 vs SOCKS5h: What the h Changes

socks5 vs socks5h: with socks5h the proxy resolves DNS, with socks5 your machine does. How curl, Python, Go, Chrome and Firefox handle it.

6 min read

SOCKS5 vs SOCKS5h comes down to one thing: who looks up the domain name. With socks5://, your own machine resolves the name and sends the proxy an IP. With socks5h://, the "h" means hostname: your client sends the name and the proxy resolves it.

The proxy protocol is the same in both cases. Only the DNS step moves. If you want lookups to happen at the exit, use socks5h:// or check that your client already does it.


Key takeaways

  • socks5 = DNS on your machine. socks5h = DNS on the proxy.
  • The "h" is a client setting, not a different proxy. Elusive proxies accept domain names, so socks5h works with them.
  • Some clients ignore the difference and always send the name: Chrome, Go and httpx do this.
  • Firefox resolves on the proxy for SOCKS5 by default, and locally for SOCKS4.
  • socks5h does not add UDP support and does not change WebRTC.

What the "h" changes

Before your client can connect to example.com, someone has to turn that name into an IP address.

SOCKS5 lets the client send the target in two ways. It can send an IP address, or it can send a domain name and let the proxy do the lookup. This is part of the protocol itself, in RFC 1928.

The URL scheme tells your client which way to go:

  • socks5:// : the client resolves the name locally, then sends the IP to the proxy.
  • socks5h:// : the client sends the name as is. The proxy resolves it.

curl's manual puts it plainly: --socks5-hostname means "let the proxy resolve the hostname". Python Requests documents the same split in its SOCKS section.


Why it matters

The lookup happens near the exit. Many sites run several servers and pick one based on where the lookup came from. A lookup from the proxy's location points to a server that suits that location. A lookup from your home network may not.

Your local resolver is not in the path. With plain socks5, your ISP or office DNS answers every lookup. It may answer for your location, or not resolve some names at all. With socks5h, the lookup happens at the exit.

Domain-only targets work. Some names only resolve inside the proxy's network, or give different answers by region. If your machine cannot resolve the name, socks5 fails before it starts.

Location checks line up. Leak tests compare the DNS servers they see with the IP they see. If the two disagree, it looks odd. Our DNS leak check guide shows how to test this, and proxy shows the wrong location covers the other mismatches.

This is about correctness and consistency. It does not make anything invisible.


How each client handles it

This is the part that trips people up. The scheme means different things in different tools.

curl

Use -x socks5h://USER:PASS@HOST:PORT or the older flag --socks5-hostname HOST:PORT. The manual says socks5:// and socks5h:// request a specific SOCKS version, and socks5h lets the proxy resolve the hostname.

Python requests

Install requests[socks]. The docs say the socks5 scheme causes DNS to happen on the client, and socks5h resolves on the proxy server. Use socks5h.

Python httpx

Install httpx[socks]. The httpx source accepts both socks5 and socks5h. Its SOCKS layer (httpcore) hands the hostname to the proxy in both cases, so the "h" makes no difference there. Use socks5h anyway so the intent is clear, and so your URL also works in other tools.

Node: socks-proxy-agent

The agent treats socks5:// as local lookup and socks5h:// (and socks4a) as proxy lookup. Use socks5h://.

Go

Go's net/http treats socks5 and socks5h the same. Its docs say "socks5" is treated the same as "socks5h". With golang.org/x/net/proxy, a host name that is not an IP is sent to the proxy as a domain name. So Go resolves remotely either way.

Chrome

Chromium's proxy docs say that when the scheme is SOCKS5, name resolution is always done on the proxy side. Chrome does not support authentication for SOCKS5, so you cannot give it a username and password. See Chrome won't take a SOCKS5 password.

Firefox

Current Firefox has two settings. network.proxy.socks5_remote_dns covers SOCKS5 and is true by default, so Firefox acts like socks5h out of the box. network.proxy.socks_remote_dns covers SOCKS4 and is false by default. Older Firefox versions used one setting for both, and it was off. If lookups still happen on your machine, check both in about:config, and the "Proxy DNS when using SOCKS v5" box in the connection settings.

Playwright

With Chromium, Chrome's rule applies: remote resolution. Its docs say username and password are for HTTP(S) proxies, so SOCKS5 with a login needs a workaround. See Playwright and Puppeteer SOCKS5 auth.

proxychains

Add proxy_dns to the config. The sample file says it starts a thread that serves DNS requests and hands back an IP, so names are resolved through the proxy. Entries look like socks5 HOST PORT USER PASS. The sample config notes that proxychains only takes numeric IPv4 addresses for the proxy itself.


What socks5h does not do

It does not carry UDP. The "h" only affects how the target is named. UDP needs a separate SOCKS5 command, UDP ASSOCIATE, and the proxy has to support it. Some Elusive proxies do, and the catalog marks them. Read does SOCKS5 support UDP for the details.

It does not change WebRTC. WebRTC runs in the browser and can open its own connections, outside the proxy. DNS settings do not touch that. See the WebRTC leak test.

It does not change the exit IP. The IP you get depends on the proxy, not the scheme.


Common errors

**You use socks5 and the DNS test shows your ISP.** Switch to socks5h, or turn on remote DNS in your client.

A name works in the browser but fails in code. Your code may resolve locally with a resolver that cannot see the name. Use socks5h.

**Your tool rejects socks5h.** Some older libraries only know socks5. Check what yours does with names, or use a client from the list above.

The password breaks the URL. Characters like @, : and / must be percent-encoded in the proxy URL. p@ss becomes p%40ss.

The proxy times out. Check the host, port and login first. A sticky proxy also lasts up to 24 hours and can go offline earlier, so an old one may simply be gone.


Test it

Ask an IP service for your address through the proxy, then run a DNS leak test in the same setup. The code in SOCKS5 proxy in Python, Node and Go prints the exit IP for each language. To find a proxy to test with, open the catalog.


FAQ

What is the difference between socks5 and socks5h?

With socks5, the client resolves DNS and sends the proxy an IP. With socks5h, the client sends the hostname and the proxy resolves it.

Should I use socks5 or socks5h?

Use socks5h unless you have a reason to resolve locally. It keeps lookups at the exit and works with domain-only targets.

Does Chrome use socks5 or socks5h?

Chrome always resolves on the proxy side for a SOCKS5 proxy, per Chromium's docs. It has no separate "h" scheme.

Does Firefox send DNS through the SOCKS5 proxy?

Yes, in current versions. network.proxy.socks5_remote_dns is true by default. For SOCKS4 the matching setting is off.

Does socks5h support UDP?

No. The scheme only decides who resolves names. UDP needs a proxy that supports UDP ASSOCIATE.

Get a proxy for your profiles

SOCKS5 with a username and password, ready to paste as HOST:PORT:USER:PASS. Sticky IPs for up to 24 hours, Static ISP for 7 to 90 days, or Rotating by the GB.