curl with a proxy: -x, -U, SOCKS5, socks5h, environment variables and debugging
Every curl option that matters for proxies, tested on curl 8.19: the -x syntax and its default port, credentials with special characters, SOCKS5 and socks5h, headers, environment variables, .curlrc, bypassing the proxy, and what each exit code means.

curl takes a proxy with -x (long form --proxy). For most jobs this one line is all you need:
curl -x http://USERNAME:[email protected]:8080 https://api.ipify.orgIf it prints an IP that is not yours, traffic is going through the proxy. The rest of this guide covers every curl option that matters for proxies: the -x syntax and its defaults, credentials with awkward characters, SOCKS5 and socks5h, headers, environment variables, config files, bypassing the proxy, and how to read curl's errors. All examples were checked on curl 8.19.
The -x syntax
The format is:
[scheme://][user:password@]host[:port]The scheme says how curl talks to the proxy, not to the site:
http://or no scheme: an HTTP proxy. HTTPS sites still work, through aCONNECTtunnel that the proxy cannot read.https://: TLS between you and the proxy itself. Only use it if the proxy port speaks TLS; on a plain HTTP port curl fails with exit code 35.socks5://andsocks5h://: a SOCKS5 proxy, covered below.socks4://andsocks4a://also exist.
Always write the port. When it is missing, curl assumes 1080, the traditional SOCKS port, for both HTTP and SOCKS proxies (only https:// proxies default to 443). -x http://geo.gw.nyxon.sh would therefore try to speak HTTP to the SOCKS5 port.
-x also overrides any proxy set in environment variables, and -x "" turns an environment proxy off for one command.
Credentials: -U and special characters
Credentials can go in the URL or in a separate option:
curl -x http://geo.gw.nyxon.sh:8080 -U "USERNAME-country-us:PASSWORD" https://api.ipify.org-U (long form --proxy-user) needs no encoding, which makes it the easy answer for passwords with @, :, / or # in them. In the URL those characters must be percent-encoded: @ is %40, : is %3A, / is %2F, # is %23. curl URL-decodes the user and password it finds in the proxy string. Pasted raw, a password like p@ss:w/rd#1 broke the URL in our test, and curl failed with curl: (5) Could not resolve proxy because it read part of the password as the hostname.
Quote the whole value either way. In bash and zsh, single quotes stop $, ! and & from being interpreted; in PowerShell single quotes work too; in Windows cmd.exe use double quotes.
The curl manual also points out that command-line arguments can be visible to other users of the same machine, if only briefly, in the process list. On shared servers, put credentials in a config file instead (see below).
SOCKS5 and socks5h
Same credentials, the product's SOCKS5 port, and a different scheme:
curl -x socks5h://USERNAME:[email protected]:1080 https://api.ipify.orgThe h decides where DNS happens. With socks5://, curl resolves the hostname on your machine and sends the proxy an IP address. With socks5h://, it sends the hostname and the proxy resolves it on the exit side. We watched both on a test proxy: socks5:// arrived as a bare IP, socks5h:// as api.ipify.org. Use socks5h: local lookups reveal to your DNS resolver which sites you visit, and can point you at a CDN node near you instead of near the exit.
The older flags --socks5 and --socks5-hostname do the same as the two schemes; the manual calls --socks5-hostname superfluous now that socks5h:// exists.
An HTTP proxy always receives the hostname, so it has no equivalent of this problem. The SOCKS5 vs HTTP comparison explains the other differences.
Headers: -H versus --proxy-header
For an HTTPS site, curl sends two sets of headers: one to the proxy in the CONNECT request, and one to the site inside the tunnel.
-Hadds headers for the site.-Asets the user agent the site sees.--proxy-headeradds headers for the proxy only, in theCONNECTrequest.
When you test a real target, set a browser user agent. curl's default, curl/8.19.0, is blocked on sight by many sites, and that has nothing to do with the proxy:
curl -x http://USERNAME:[email protected]:8080 -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36" https://example.comEnvironment variables
curl reads these, so scripts pick up a proxy without changes:
http_proxy: proxy for http:// URLs. Lowercase only, per the curl manual.HTTPS_PROXYorhttps_proxy: proxy for https:// URLs.ALL_PROXYorall_proxy: used when no scheme-specific variable is set.NO_PROXYorno_proxy: hosts that go direct.
export https_proxy="http://USERNAME:[email protected]:8080"
export http_proxy="$https_proxy"
curl https://api.ipify.orgThe lowercase-only rule for http_proxy trips people up: on Linux and macOS, curl ignores HTTP_PROXY in capitals. On Windows, environment variable names are not case-sensitive, so there HTTP_PROXY and http_proxy are the same variable.
ALL_PROXY accepts SOCKS URLs too, so this sends everything through SOCKS5:
export ALL_PROXY="socks5h://USERNAME:[email protected]:1080"Bypassing the proxy
NO_PROXY takes a comma-separated list of hosts that skip the proxy, and per the manual it wins even over -x:
NO_PROXY="localhost,127.0.0.1,.internal.example" curl -x http://USERNAME:[email protected]:8080 http://127.0.0.1:3000/healthFor a single command, --noproxy does the same. --noproxy '*' disables the proxy for every host, and --noproxy "" overrides a NO_PROXY variable. Entries match the host and its subdomains, and IP ranges can be written in CIDR form, such as 192.168.0.0/16.
Config files
Options can live in a file, one per line, without the leading dashes:
proxy = "http://geo.gw.nyxon.sh:8080"
proxy-user = "USERNAME-country-us:PASSWORD"Use it for one command with -K file, or save it as .curlrc in your home directory and curl reads it every time. On Windows curl checks %USERPROFILE%\.curlrc and %APPDATA%\.curlrc, among other places, and also accepts the name _curlrc. A proxy in .curlrc applies to every curl call on the machine, including other people's scripts; -q as the very first option skips the file for one run.
Debugging
See the conversation with the proxy. -v prints the CONNECT request and the proxy's answer:
> CONNECT example.com:443 HTTP/1.1
> Proxy-Authorization: Basic ...
< HTTP/1.1 407 Proxy Authentication Required
* CONNECT tunnel failed, response 407That Proxy-Authorization value is your username and password in base64, which anyone can decode. Remove it before you share verbose output.
Tell proxy errors from site errors. %{http_connect} is the proxy's answer to CONNECT, %{http_code} is the site's:
curl -s -o /dev/null -x http://USERNAME:[email protected]:8080 -w "proxy: %{http_connect} site: %{http_code}\n" https://example.comproxy: 200 site: 403 means the proxy worked and the site refused you. proxy: 407 site: 000 means the proxy refused you. The proxy error codes guide covers every combination.
Time each step.
curl -s -o /dev/null -x http://USERNAME:[email protected]:8080 -w "connect %{time_connect}s tls %{time_appconnect}s first byte %{time_starttransfer}s total %{time_total}s\n" https://example.comtime_connect measures the connection to the proxy, and time_appconnect includes the TLS handshake with the site through the tunnel.
Read the exit code. These are the ones proxy users meet, with the messages curl 8.19 printed in our tests:
5: could not resolve the proxy hostname, for examplecurl: (5) Could not resolve proxy: .... Check for a typo, or a password that needs encoding.7: failed to connect, for examplecurl: (7) Failed to connect to ... Could not connect to server. Wrong port, or a firewall blocks it.28: timeout, for examplecurl: (28) Operation timed out after ... milliseconds with 0 bytes received.35: SSL connect error. Oftenhttps://written in front of a plain HTTP proxy.56: failure receiving data. Covers a refused tunnel,curl: (56) CONNECT tunnel failed, response 407, and the HTTP scheme on a SOCKS port,curl: (56) Proxy CONNECT aborted.97: proxy handshake error.curl: (97) Received invalid version in initial SOCKS5 response.means SOCKS5 on an HTTP port;curl: (97) User was rejected by the SOCKS5 server (1 1).means wrong SOCKS5 credentials.
Run echo $? in bash, or $LASTEXITCODE in PowerShell, right after curl to see the code.
PowerShell: use curl.exe
In Windows PowerShell 5.1, curl is an alias for Invoke-WebRequest, a different tool. curl -x ... fails there with A parameter cannot be found that matches parameter name 'x'. Type curl.exe to run the real curl, which ships with Windows 10 and 11.
FAQ
How do I use curl with a SOCKS5 proxy? Use the socks5h:// scheme and the SOCKS5 port of your plan: curl -x socks5h://host:port -U USERNAME:PASSWORD URL.
Why does curl ignore my HTTP_PROXY variable? On Linux and macOS curl only reads the lowercase http_proxy for http:// URLs. HTTPS URLs use https_proxy or HTTPS_PROXY.
How do I skip the proxy for one host? Add it to NO_PROXY, or pass --noproxy host.
How do I check where the exit is? Request https://ipinfo.io/json through the proxy and read country, city and org. The 60-second proxy test walks through it.
Try it
Every command here works with any NyxonProxies plan; swap in the host and port shown on your Generate page. For the same examples in Python and Node.js, see the quickstart. New accounts can sign up and link Discord under Freebies for 250MB of free traffic.