curl Proxy: Flags, Auth, SOCKS5, and Verification

How to run curl through a proxy: the -x flag, username and password auth, SOCKS5, environment variables, bypassing the proxy, and reading curl's errors.

VoidMob Team
8 min read

To send a request through a proxy, pass -x (or --proxy) with the full proxy URL, credentials included: curl -x "http://user:pass@host:port" https://example.com. Credentials can also go in --proxy-user user:pass. Every other proxy feature in curl (SOCKS5, tunneling, environment variables, bypass rules) is a variation on that one flag.

The basic curl proxy command

curl -x "http://user:[email protected]:8000" https://ipinfo.io/json

The scheme in the proxy URL matters. http:// means "talk HTTP to the proxy" and is the default if you omit it. https:// means the connection to the proxy itself is TLS-encrypted. socks5:// and socks5h:// switch to the SOCKS protocol. The scheme of the target URL is independent: an HTTP proxy can carry HTTPS requests.

On VoidMob's shared pool the flex gateway is proxy.voidmob.com:10092, and the geo and session controls ride in the username as underscore parameters:

curl -x "http://<username>_c_US:<password>@proxy.voidmob.com:10092" https://ipinfo.io/json

The <username> and <password> values come from POST /v1/proxies/:id/flex_credentials, so the snippet only works after the package is provisioned. If you use named proxy lists instead, geo and rotation are set on the list and you connect on port 10000 with the credentials returned for that list.

Two encoding rules break more curl commands than anything else:

  • Country codes are uppercase. _c_US matches, _c_us does not.
  • Quote the whole proxy string. Passwords and parameters contain characters your shell will happily expand or split on. Use double quotes, and percent-encode @ : / ? # if they appear in the password.

Proxy authentication in curl

Three equivalent forms, in decreasing order of how much they leak:

# 1. Inline (shows up in shell history and process list)
curl -x "http://user:[email protected]:10092" https://ipinfo.io/json

# 2. Separate flag
curl -x "http://proxy.voidmob.com:10092" --proxy-user "user:pass" https://ipinfo.io/json

# 3. Password prompt: omit the password, curl asks for it
curl -x "http://proxy.voidmob.com:10092" --proxy-user "user" https://ipinfo.io/json

curl defaults to Basic proxy auth. --proxy-basic, --proxy-digest and --proxy-ntlm force a scheme if the proxy requires one. A 407 Proxy Authentication Required response means the credentials never arrived or were wrong, not that the target blocked you.

HTTPS through an HTTP proxy

When the target URL is https://, curl asks the proxy for a CONNECT tunnel and then negotiates TLS end to end with the target. The proxy sees the hostname and the byte counts, not the plaintext. That is why TLS fingerprints survive a proxy hop untouched: the handshake is yours, which matters if the target profiles clients by JA3 or JA4.

-p / --proxytunnel forces the tunnel even for non-HTTPS targets, which you need when running a non-HTTP protocol over an HTTP proxy. Add -v to watch the exchange: a healthy run shows CONNECT tunnel established, response 200 before the TLS lines.

SOCKS5 with curl

curl -x "socks5h://<username>:<password>@proxy.voidmob.com:$SOCKS_PORT" https://ipinfo.io/json

Use socks5h://, not socks5://. The h sends the hostname to the proxy for resolution; plain socks5:// resolves DNS locally, which leaks the target to your local resolver and often returns the wrong geo-aware answer. --socks5-hostname host:port is the older equivalent.

All VoidMob plans support HTTP and SOCKS5, but the SOCKS port is issued per order with your credentials, so read it from the dashboard rather than assuming a number. If you are choosing between the two protocols for a workload, SOCKS5 vs HTTP vs HTTPS covers the performance difference.

Environment variables and .curlrc

curl reads proxy settings from the environment when no -x is given:

export http_proxy="http://user:[email protected]:10092"
export https_proxy="http://user:[email protected]:10092"
export ALL_PROXY="http://user:[email protected]:10092"
curl https://ipinfo.io/json

One gotcha: http_proxy is honored in lowercase only, while the others accept either case. To make the proxy permanent for your user without exporting variables, put the flag in ~/.curlrc:

proxy = "http://user:[email protected]:10092"

A command-line -x overrides both the file and the environment. -q ignores .curlrc entirely.

Turning the proxy off for one request

curl --noproxy "*" https://ipinfo.io/json          # ignore all proxy settings
curl --noproxy "example.com,10.0.0.0/8" https://api.internal/health
export NO_PROXY="localhost,127.0.0.1"              # same idea, environment form

--noproxy "*" is the fastest way to answer "is it the proxy or the target?" when a request starts failing. If the direct request succeeds and the proxied one does not, the problem is upstream of the target.

Verify the exit IP before you run volume

One request to an IP echo endpoint tells you whether geo targeting, session pinning and auth all worked:

curl -s -x "http://<username>_c_US:<password>@proxy.voidmob.com:10092" https://ipinfo.io/json

Compare that output to what your own machine returns with --noproxy "*". If the country, ASN or carrier is not what you asked for, fix the parameter case before blaming the pool. For ad and pricing checks where the answer depends on the exit being a real local carrier IP, the deeper version of this workflow is in mobile proxies for ad verification.

Check what your current exit IP looks like

Holding one IP across several curl calls

Each curl invocation is a new process, so per-request rotation gives you a different exit IP on every line of a shell script. That breaks anything with a login or a multi-step form. On the flex gateway, add a session parameter to the username and reuse it:

SESS="_s_run1_ttl_30m"
curl -c jar.txt -x "http://<username>_c_US${SESS}:<password>@proxy.voidmob.com:10092" https://example.com/login
curl -b jar.txt -x "http://<username>_c_US${SESS}:<password>@proxy.voidmob.com:10092" https://example.com/account

Same session ID, same device, until the TTL runs out. Without _ttl_, the session expires after 60 minutes of inactivity. Change the string to get a new device. Keep the cookie jar and the session ID paired: a cookie set on one IP and replayed from another is the classic self-inflicted flag. More on window lengths in sticky sessions, and on the rotating half in USA rotating proxies.

Reading curl's proxy errors

curl's exit code tells you which hop failed, which saves guessing.

SymptomWhat it meansFix
exit 5, could not resolve proxyThe proxy hostname did not resolveCheck spelling of the host; confirm your DNS is reachable
exit 7, failed to connect to proxyHost resolved, port refused or filteredConfirm the port (10092 flex, 10000 per-list) and that your egress firewall allows it
HTTP 407Proxy auth missing or rejectedRe-quote the proxy string; percent-encode special characters in the password
exit 56, recv failureTunnel opened then dropped mid-transferRetry with a new session ID; the device likely left the network
Wrong country in the responseGeo parameter was not parsedUppercase the ISO code, check prefix case (_c_ not _C_)

If curl works but a browser automation stack does not, the proxy string is rarely the issue. Compare against the library-specific setup in Playwright proxy setup or Selenium proxy setup, or run the credentials through the Proxy Validator to isolate the variable.

1How do I use curl without a proxy?

Add --noproxy "*" to the command. That overrides -x, environment variables and ~/.curlrc for that single request, which makes it the cleanest way to test whether the proxy or the target is failing.

2How do I pass JSON in curl through a proxy?

The proxy flag is independent of the body. Combine them: curl -x "http://user:pass@host:port" -H "Content-Type: application/json" -d '{"key":"value"}' https://api.example.com. Use single quotes around the JSON so the shell does not expand it, and -d @file.json for larger payloads.

3How do I get my IP with curl?

Request any IP echo endpoint, for example curl -s https://ipinfo.io/json. Run it once with your proxy flag and once with --noproxy "*" and compare; the two answers should be the proxy exit and your own connection.

4How do I configure proxy authentication in curl?

Either put user:pass@ in front of the host inside the -x URL, or keep the URL clean and pass --proxy-user "user:pass". Omit the password from --proxy-user and curl prompts for it, which keeps it out of shell history. curl sends Basic by default; add --proxy-digest or --proxy-ntlm only if the proxy demands it.

5What is the default port for a curl proxy?

curl assumes port 1080 if you give a proxy host with no port. That default matches almost no commercial gateway, so always state the port explicitly. VoidMob's flex gateway is 10092 and per-list connections use 10000.

6Can I set a proxy for curl permanently?

Yes. Put proxy = "http://user:pass@host:port" in ~/.curlrc, or export http_proxy and https_proxy in your shell profile. A -x flag on the command line still wins, and -q makes curl ignore .curlrc for that run.

Run curl through real 4G/5G exits

Pay-per-GB pools with flex geo and session parameters, or dedicated devices you rotate on demand.