SOCKS5 Works With an IP But Fails With a Hostname — How to Diagnose It

Key takeaways

  • SOCKS5 has two resolution modes: resolve the hostname on your machine and send an IP, or send the hostname and let the proxy resolve it. Most "SOCKS5 is broken" reports are the wrong mode, not a broken proxy.
  • curl --socks5 resolves locally. curl --socks5-hostname makes the proxy resolve. The -x socks5:// and -x socks5h:// schemes are the same distinction in URL form.
  • Python requests needs socks5h://, not socks5:// — and the SOCKS support is an extra install, so a missing dependency and a wrong scheme produce different errors worth telling apart.
  • Resolving locally is a DNS leak: your resolver sees every hostname you visit and the destination is picked from your real location, which quietly defeats the point of using the proxy at all.
  • Instant failure means device-side. A timeout means config or network. That one split separates most causes before you change anything.
  • A single proxy failing SOCKS5-with-hostname in about 0.03 seconds with connection code 000, while plain HTTP works and SOCKS5 to a literal IP works, is a stale resolver cache on the device — not a configuration error.
  • That specific fault is cleared by one rotation, which forces the connection to be rebuilt and the resolver state along with it.

A SOCKS5 proxy that works perfectly when you give it an IP address and fails the moment you give it a hostname looks like a broken proxy. It usually is not.

SOCKS5 has two entirely different ways of handling a destination name, and the protocol allows both. Which one you get depends on a flag, a URL scheme, or a checkbox — something small enough that most people have never consciously chosen it. When the mode is wrong, the proxy is fine, your credentials are fine, the destination is fine, and nothing works.

This page separates that case from the ones that genuinely are faults, mostly using elapsed time. An instant failure and a timeout mean different things, and knowing which you have removes most of the guesswork before you change a setting.

The two SOCKS5 modes, and why nobody notices until it breaks

SOCKS5 can carry either an IP address or a domain name in its connect request. In local mode your machine resolves the hostname and sends the resulting address. In remote mode you send the name and the proxy resolves it. Both are valid SOCKS5, and they fail in completely different circumstances.

The protocol's connect request carries an address-type field: IPv4 address, IPv6 address, or domain name. Clients that resolve locally use the first two; clients that pass the name through use the third. The convention that grew up around this is the trailing hsocks5h means hostname, so the proxy resolves. It is a client-side convention rather than a separate protocol; the proxy sees a standard SOCKS5 request either way.

The distinction hides well because for most destinations both modes work. Your machine resolves example.com, gets an address, the proxy connects to it, and you never learn which mode you were in. It surfaces only when your local resolver cannot resolve the name, when the address it returns is unreachable or wrong from the proxy's position, or when resolution has broken on the proxy side. Then one mode works, the other does not, and it looks arbitrary.

Client formWho resolves the hostnameLeaks the domain to your resolver?
curl --socks5 host:portYour machineYes
curl --socks5-hostname host:portThe proxyNo
curl -x socks5://host:portYour machineYes
curl -x socks5h://host:portThe proxyNo
curl -x http://host:portThe proxy — CONNECT carries the nameNo

That last row is why people report that "HTTP works but SOCKS5 doesn't". An HTTP proxy has no local-resolution mode to get wrong — the CONNECT request contains the hostname by definition, one of several differences covered in SOCKS5 vs HTTP proxies. The HTTP path was never testing the same thing.

curl: --socks5 versus --socks5-hostname

These two flags differ by exactly one behaviour, and the naming is unhelpfully subtle. --socks5 resolves the destination on your machine and hands the proxy an address. --socks5-hostname hands over the name. If your proxy tests pass with one and fail with the other, you have found your answer in a single command.

Run both against the same destination and compare:

curl -s -o /dev/null --socks5-hostname USER:PASS@host:PORT \
  https://api.ipify.org -w "hostname-mode  code=%{http_code}  t=%{time_total}\n"

curl -s -o /dev/null --socks5 USER:PASS@host:PORT \
  https://api.ipify.org -w "local-mode     code=%{http_code}  t=%{time_total}\n"

The URL-scheme form does the same thing and is what most libraries and config files use:

curl -s -x socks5h://USER:PASS@host:PORT https://api.ipify.org
curl -s -x socks5://USER:PASS@host:PORT  https://api.ipify.org

Read %{http_code} and %{time_total} together. A code of 000 means curl never received an HTTP response, so there is no status to report, not a server error, the absence of a conversation. Paired with the elapsed time it tells you where the conversation failed to start.

A useful third data point is a literal IP:

curl -s -o /dev/null --socks5 USER:PASS@host:PORT \
  https://1.1.1.1 -w "literal-ip  code=%{http_code}  t=%{time_total}\n"

If the literal IP succeeds while both hostname forms fail, resolution is the problem and the transport is healthy. That one fact eliminates the entire "is my proxy down" branch, which is where people usually spend the first hour. If the literal IP also fails, you have a connection problem or an authentication problem instead, and this is the wrong page.

Python, Node, and the socks5h:// trap

Python's requests library will accept socks5:// without complaint and resolve every hostname locally. The fix is one character: use socks5h://. Node's common SOCKS agent follows the same scheme convention. Because both accept the wrong form silently, the failure surfaces as a mysterious connection error rather than a configuration warning.

The working Python form:

import requests

proxies = {
    "http":  "socks5h://USER:PASS@host:PORT",
    "https": "socks5h://USER:PASS@host:PORT",
}
r = requests.get("https://api.ipify.org", proxies=proxies, timeout=30)
print(r.status_code, r.text)

Two distinct failures get confused here, and they have different messages:

In Node, the widely used SOCKS agent honours the same convention: socks5:// performs the lookup in the Node process, socks5h:// passes the hostname to the proxy. Same one-character fix.

Elsewhere the setting is a checkbox rather than a scheme. Firefox has an explicit "Proxy DNS when using SOCKS v5" option. proxychains has a proxy_dns directive. Anti-detect browsers vary and rarely label it clearly — anything resembling "remote DNS" or "resolve through proxy" is this setting.

The DNS leak: what local resolution gives away

Local resolution means your own resolver looks up every hostname you visit. Your ISP or DNS provider sees the complete list of domains, timed and ordered, even though the traffic goes through the proxy. The destination address is also chosen from your real location rather than the proxy's.

The privacy half is the obvious half. The proxy hides the source of your connections; the DNS queries preceding them do not go through the proxy at all, and they are a near-perfect log of your activity.

The functional half matters more often and gets noticed less. Large sites answer DNS queries based on where the query came from, so a resolver in your country returns the edge node nearest you. Your traffic then leaves the proxy's network aimed at an endpoint chosen for a location you are not connecting from. The result is rarely an outright failure — it is slower connections, an inconsistent geographic story, or content served for the wrong region while your visible IP claims another. When a proxy "works but the site behaves as if I am somewhere else", this is a leading suspect.

Remote resolution is the correct default for almost every proxy use case. Use local resolution only for a specific reason — resolving an internal name only your side knows about, and know you are accepting the leak in exchange.

Verify rather than assume: run a DNS leak test through the proxy in both modes. In remote mode the resolvers reported should sit on the proxy's network path, not yours.

Instant failure versus timeout: the split that names the cause

This is the diagnostic worth memorising. A hostname failure returning in hundredths of a second and one hanging for seconds are different faults. Instant means nothing left the machine, or the far end refused immediately — a device or client problem. A timeout means something waited for an answer that never came — config or network.

The reasoning is mechanical. Timeouts exist because a packet went out and no reply came back. A request failing faster than a network round trip could complete means no such attempt happened: something local refused, or something at the proxy end answered "no" without doing any work.

One field signature is worth knowing precisely, because it is identifiable on sight:

A single proxy fails SOCKS5-with-hostname in about 0.03 seconds with connection code 000, while plain HTTP through the same proxy works and SOCKS5 to a literal IP works.

That combination is diagnostic. Plain HTTP working proves the transport, the port and the credentials are all healthy. SOCKS5 to a literal IP working proves the SOCKS5 path itself is healthy. Only the name-resolution step fails, and it fails instantly — meaning it was refused rather than attempted.

The cause is stale resolver state on the proxy device. Not a configuration error, not a client bug, and not something you can fix from your side by changing flags. The fix is one rotation, which forces the device's connection to be re-established and the resolver state rebuilt along with it. Expect a short interruption while the radio re-attaches, and normal behaviour afterwards. If you are unsure whether your rotation actually did anything, a rotation that reports success in about two seconds did not.

What you seeElapsedMost likely causeWhat fixes it
Hostname fails 000, IP works, HTTP works~0.03sStale resolver state on the deviceOne rotation
Hostname fails, IP works, HTTP worksSeconds, then timeoutWrong mode, or DNS unreachable from the proxySwitch to the socks5h form; check the proxy's DNS path
Hostname fails, IP also fails, HTTP worksEitherSOCKS5 port or protocol not enabled on that credentialCheck which protocol your credentials are for
Everything fails instantlyInstantPort closed, wrong port, or refusedConnection refused
Everything fails with an auth errorInstantCredentials or IP allowlist407 error

That third row catches people more often than it should. Where a provider issues separate credentials per protocol, a SOCKS5 username pointed at an HTTP port, or the reverse — fails in ways that look like resolution but are not. Confirm which protocol and port each credential belongs to. If symptoms are overlapping, the general proxy checklist is the faster starting point.

When this becomes an infrastructure problem

Everything above you can run yourself in about two minutes. It stops being a client-side question when the diagnosis lands on the device: a stale resolver, reachable only by rebuilding the connection, on hardware you do not control. The useful question becomes not "which flag did I get wrong" but "can I fix this myself".

On a shared pool you usually cannot. The device holding the stale state is serving other tenants, you have no way to identify which one you are on, and rotation — the operation that clears it — either is not exposed or affects people who did not ask for it. The symptom is genuinely device-specific, so a support queue is the only path, and by the time anyone looks, the address may have moved on.

A dedicated device changes the economics of that specific fault. One tenant, one device, rotation on demand: you observe the 0.03-second signature, you rotate, it clears, and the whole loop is under a minute without anybody else being involved. That is the shape QuantumProxy sells — one real device per customer, both protocols available, rotation exposed as an endpoint you call rather than a favour you request.

The honest limitation: this does not stop resolver state from going stale. It shortens the distance between noticing and fixing. The underlying fault is a device-level condition on real cellular hardware, it will happen again, and any provider claiming to have engineered it out of existence is describing equipment they do not operate.

A two-minute diagnostic to run first

Before changing library code or opening a ticket, run these four lines in order and read the elapsed times.

P=USER:PASS@host:PORT
curl -s -o /dev/null -x http://$P     https://api.ipify.org -w "http      %{http_code} %{time_total}\n"
curl -s -o /dev/null --socks5 $P      https://1.1.1.1       -w "s5-ip     %{http_code} %{time_total}\n"
curl -s -o /dev/null --socks5 $P      https://api.ipify.org -w "s5-local  %{http_code} %{time_total}\n"
curl -s -o /dev/null --socks5-hostname $P https://api.ipify.org -w "s5-remote %{http_code} %{time_total}\n"

Read it as a pattern rather than four separate results. If the first three succeed and only the last fails — instantly, with 000 — you have the device-side resolver fault and a rotation is the fix. If the last two both fail slowly, resolution is failing somewhere in the path and the mode is not the issue. If only the third fails, your local resolver is the problem and remote resolution is your answer, permanently.

And if none of it fails but the site still treats you as suspicious, the transport was never the problem — that is a detection question, not a DNS one.

Frequently asked questions

What is the difference between socks5 and socks5h?

With socks5, your own machine resolves the hostname to an IP address and sends that address to the proxy. With socks5h, your machine sends the hostname itself and the proxy performs the lookup. The "h" means hostname. Functionally the difference decides who does the DNS query, and therefore whose network sees the domain you are visiting.

Why does my SOCKS5 proxy work with an IP address but not a hostname?

Two common reasons. Either your client is resolving locally and your local resolver cannot resolve that name, or the proxy side is failing to resolve it. Check the elapsed time: an instant failure points at the device or the client, while a several-second timeout usually points at configuration or a DNS path that is not reachable.

Why does Python requests fail with socks5:// but work with socks5h://?

Because socks5:// tells PySocks to resolve the hostname locally before connecting, and socks5h:// tells it to pass the name through to the proxy. If your local environment cannot resolve the destination, or resolves it to an address the proxy path cannot reach, only the socks5h form will work. Note that SOCKS support in requests is an optional dependency.

Does SOCKS5 leak DNS?

It does when you use the local-resolution mode. Every hostname you request is looked up by your own resolver, so your ISP or DNS provider sees the full list, and the destination address is chosen from your real geographic position rather than the proxy's. Using the remote-resolution form removes both problems.

What does connection code 000 mean in curl?

It means curl never received an HTTP response, so there is no status code to report. Combined with a very short elapsed time it tells you the failure happened before any real network conversation took place, which is a strong signal that the fault is local to the client or the proxy device rather than out on the network.

How do I fix a SOCKS5 hostname failure that happens instantly?

If plain HTTP works and SOCKS5 to a literal IP works, but SOCKS5 with a hostname fails in hundredths of a second, the resolver state on the proxy device is stale. One rotation forces the connection to be re-established and rebuilds it. That is a device-side fix; no amount of client configuration will reach it.

Dedicated mobile proxies, one dashboard

Real 4G/5G devices on US carrier SIMs. Sticky IP per customer, rotation on demand.

See plans