# socks5 and socks5h: where Chrome resolves the name

> In curl, socks5h sends the hostname to the proxy and socks5 resolves it locally. Chrome's socks5 already sends the name; the leak is elsewhere.

Source: https://mosaicbrowser.com/blog/socks5-and-socks5h-in-chrome

## socks5 and socks5h: where Chrome resolves the name

In curl, socks5h sends the hostname to the proxy and socks5 resolves it locally. Chrome's socks5 already sends the name; the leak is elsewhere.

![socks5h: socks5 and socks5h: where Chrome resolves the name](https://mosaicbrowser.com/covers/socks5-and-socks5h-in-chrome.webp)

The difference between socks5 and socks5h is who looks up the hostname. With `socks5://` in curl, your computer resolves `example.com` through your own DNS resolver and sends the proxy an IP address. With `socks5h://`, curl sends the proxy the name and the proxy resolves it at the exit. The `h` is for hostname. Chrome has no `socks5h://`, because its `socks5://` already sends the name.

## socks5 vs socks5h in curl

The SOCKS5 protocol lets a client name its destination in three ways: an IPv4 address, an IPv6 address, or a domain name for the proxy to resolve. curl picks with the scheme. `socks5://` means "resolve here, send an address", and `socks5h://` means "send the name". The same split exists one version down: `socks4://` resolves locally, because SOCKS4 can only carry an IPv4 address, and `socks4a://` is the extension that lets it carry a name.

That is why guides about DNS leaks tell you to use `socks5h://`. With plain `socks5://` in curl, every lookup goes to the resolver your ISP gave you, with your real address on it, before the connection to the proxy even opens. The traffic leaves through the exit while the lookups name the sites from home.

## What Chrome does with socks5://

Chromium's own [proxy documentation](https://chromium.googlesource.com/chromium/src/+/HEAD/net/docs/proxy.md) answers it directly: when the scheme is SOCKSv5, name resolution is always done on the proxy side, even though the protocol allows the client to do it. For an HTTP proxy, name resolution is likewise deferred to the proxy. SOCKSv4 is the one Chrome resolves locally.

So `--proxy-server=socks5://host:1080` in Chrome is curl's `socks5h://`. Typing `socks5h://` into Chrome does not get you anything extra, and a proxy list copied from a tool that writes `socks5h` can be read as `socks5` without changing what happens. That is what Mosaic's proxy importer does when it meets the word.

Mosaic is a desktop app

Email yourself the link and open it on your computer.

[How it works: Provider minting](https://mosaicbrowser.com/features/proxy-providers)

## The lookups that never go through the proxy

The page's requests are not the whole browser. The same Chromium documentation warns that other components may issue DNS lookups directly and bypass the proxy, and suggests a host resolver rule that maps every name to nothing, with an exception for the proxy itself. A browser can send every page request through a SOCKS5 exit and still show your ISP's resolver to a DNS leak test, because one background feature asked the system resolver for a name.

The other gap is UDP. Chromium uses SOCKSv5 only for TCP URL requests, and WebRTC wants UDP. Without a policy telling it otherwise, WebRTC can open UDP paths that never touch the proxy, so a site can see an address the proxy was supposed to hide. That is not a DNS problem, but it is the same shape: traffic the proxy setting does not cover.

So for a browser, the question is not socks5 against socks5h. It is which lookups and packets fall outside the proxy, and whether anything stops them.

## How Mosaic closes both

By default a Mosaic profile with a proxy does not hand the proxy's address to Chrome at all. The browser talks to a local relay on `127.0.0.1`, started for that profile's launch, and the relay speaks SOCKS5 to a SOCKS gateway. It sends the destination as a domain name, address type 3 in the protocol, so the lookup happens at the exit. Its SOCKS4 path sends the name the SOCKS4a way. Why the relay exists, and what it had to stop doing so the gateway saw a browser rather than a script, is in [our relay write-up](https://mosaicbrowser.com/blog/the-relay-that-looked-like-a-script).

Behind the relay, the browser is given `--host-resolver-rules` that map every name except `127.0.0.1` to `~NOTFOUND`. That is Chromium's own suggestion, applied whenever a proxy is attached: any code path that tries to resolve a name itself gets an error instead of a leak. It is a per-profile privacy switch, `dnsOverProxy`, and it is on by default. One name is mapped before the wildcard, the companion extension's own loopback host, because rules apply in order and the first version of this swallowed the extension's calls.

For WebRTC, a profile with a proxy runs with `--webrtc-ip-handling-policy=disable_non_proxied_udp`, so WebRTC cannot send UDP around the proxy.

## Which resolver the site sees

Sending the name to the exit does not make DNS invisible. The exit resolves it through some resolver, and a leak test reports that resolver. We measured it through a residential session with plain `curl` and no browser at all: the lookups went out through Google resolvers in Germany and then the Netherlands, while the exit itself was a Verizon address in the United States. The same machine resolving directly showed its real Austrian ISP. The Austrian line proves the lookups went through the proxy. The German and Dutch lines are a property of the exit, and in our runs Whoer took 30 points off for exactly that, a DNS server in a different country from the IP.

No browser setting reaches that, so Mosaic's proxy check reports it instead. Through the exit it loads `edns.ip-api.com`, which redirects to a one-time subdomain and then names the resolver that looked it up. If that resolver sits in another country from the exit, the check banner turns amber and says another pool is the only fix. If the redirect fails, the fields stay empty rather than reading as a match, because "we did not find out" is not good news. The other things the check reads before a profile opens are listed in [how to check a proxy before you use it](https://mosaicbrowser.com/guides/how-to-check-a-proxy-before-you-use-it). The seller at the far end of the relay sees the hostnames either way, and what else it can read is in [what your proxy provider can see](https://mosaicbrowser.com/blog/what-a-proxy-provider-can-see).

## Questions

### What is the difference between socks5 and socks5h?

In curl and the tools that copy its URL scheme, socks5:// looks the hostname up on your machine and sends the proxy an IP address, while socks5h:// sends the hostname and lets the proxy resolve it. The h stands for hostname.

### Does Chrome support socks5h?

Chrome has no socks5h scheme and does not need one. Chromium's proxy documentation says that with a SOCKSv5 proxy, name resolution is always done on the proxy side, so Chrome's socks5:// already behaves like curl's socks5h://.

### Can a SOCKS5 proxy in Chrome still leak DNS?

The page's own requests do not, but Chromium's documentation warns that other parts of the browser can resolve names directly. It suggests a host resolver rule that maps every other name to nowhere, which is what Mosaic sets by default.

### What is the difference between socks4 and socks4a?

The same split one version earlier. SOCKS4 can only carry an IPv4 address, so the client resolves the name; SOCKS4a adds a way to send the hostname instead. Chrome's socks4:// resolves on your machine.

## Related

[How to check a proxy before you use it](https://mosaicbrowser.com/guides/how-to-check-a-proxy-before-you-use-it): Check that a proxy answers and tunnels, where its exit really is, whether the address is residential or blocklisted, and that the browser stays behind it.

[What your proxy provider can and cannot see](https://mosaicbrowser.com/blog/what-a-proxy-provider-can-see): Over HTTPS a proxy provider sees each hostname, port, time and byte count, never the pages or passwords. Over plain HTTP it sees everything you send.

[Our proxy relay told the gateway it was a script](https://mosaicbrowser.com/blog/the-relay-that-looked-like-a-script): Chrome sends Proxy-Connection: keep-alive, lower case, to every proxy. Our relay sent Keep-Alive, no User-Agent and Connection: close, until we copied Chrome.

[Residential proxy: an exit on a home internet connection](https://mosaicbrowser.com/glossary/residential-proxy): A residential proxy sends your traffic out through an address an ISP assigned to a home connection, so sites see a household rather than a data center.

[A CONNECT to a raw IP means your machine resolved the name](https://mosaicbrowser.com/blog/a-numeric-connect-means-dns-leaked): To check if DNS goes through your proxy, read what the proxy is asked for. CONNECT example.com:443 means it resolved the name; a raw IP means you did.

[DNS prefetching, the lookup that skips your proxy](https://mosaicbrowser.com/blog/dns-prefetch-and-proxies): Chrome's DNS prefetcher resolves names through your own resolver even with a proxy set. Mapping every name to NOTFOUND makes the leak fail closed.

[A proxy that answers HTTP and refuses CONNECT](https://mosaicbrowser.com/blog/proxy-http-works-https-fails): A proxy that works for HTTP but not HTTPS is refusing CONNECT, the tunnel every HTTPS page needs. A check that fetches a plain-HTTP page cannot see it.

[Chrome opens connections before your test starts](https://mosaicbrowser.com/blog/chrome-preconnects-before-you-measure): We counted 1, 0 and 0 CONNECTs in three launches and thought Chrome was bypassing the proxy for HTTPS. Our counter was reset after Chrome had started.

## Mosaic, on your own computer

The browser this blog is about: its own Chromium, fingerprints from real machines and a proxy exit per profile. Free holds 3 profiles. Pro is $49 a month for any number.

Mosaic is a desktop app

Email yourself the link and open it on your computer.
