How to Use a Proxy With cURL (-x, Auth, SOCKS5 and Rotation)
You are at a terminal and you need one command to route a cURL request through a proxy, right now, copy-paste. This guide gives you exactly that: the curl proxy flags, all three protocols, authentication, environment variables, a permanent config, rotation, and a real error-to-fix table - tested on curl 8.x in August 2026. No padding and no vendor sales funnel. If you already know cURL and just want the proxy syntax plus the gotchas the other pages skip, you are in the right place.
Last updated: 24 August 2026. Tested on curl 8.x; these flags have been stable across recent curl releases, but run curl --version to confirm yours.
TL;DR: the one-liner
Pass your proxy to cURL with -x (or its identical twin --proxy):
curl -x http://USER:PASS@HOST:PORT https://example.com
-x and --proxy are the same flag. If you leave off the scheme, cURL assumes http://; if you leave off the port, it assumes 1080. Every command below is a variation on that one line.
What you need before you start
To run any command here you need four values, which every proxy provider hands you in its dashboard:
HOST:PORT # the endpoint, e.g. p.webshare.io:80
USERNAME:PASSWORD # your proxy credentials
Those four values are all cURL needs. If you do not have a live endpoint to test against, grab one before you read on - the commands are worthless without a real proxy behind them. Webshare has a genuine free tier (10 proxies, no card) that is quick to claim for exactly this kind of testing, and it hands you a plain host:port:user:pass string that drops straight into -x. You can grab free proxies to test with in a couple of minutes. (Webshare is an affiliate partner; see our affiliate disclosure. It changes neither the price you pay nor the commands below.)
In my own curl testing I paste the sticky-session endpoint straight from the Webshare dashboard rather than hand-build a rotating gateway line, so the host, port, and credentials come as one ready string that drops into -x. I have not pinned this to one specific curl version - any reasonably recent curl handles these flags the same way - so use whatever ships with your system.
Basic cURL proxy syntax: the -x / --proxy flag
The two forms are interchangeable, so pick whichever you can remember:
# These two lines are identical
curl -x http://HOST:PORT https://example.com
curl --proxy http://HOST:PORT https://example.com
cURL fills in two defaults that surprise people. Omit the scheme and it assumes an HTTP proxy; omit the port and it assumes 1080:
# No scheme -> HTTP proxy is assumed
curl -x HOST:PORT https://example.com
# No port -> 1080 is assumed (so this targets HOST:1080)
curl -x http://HOST https://example.com
Be explicit in scripts. Writing the full http://HOST:PORT avoids the "why is it hitting port 1080?" surprise later.
HTTP, HTTPS and SOCKS5 proxies with cURL
The scheme in front of HOST:PORT tells cURL how to talk to the proxy. This is separate from whether your target URL is https.
| Proxy type | Flag example |
|---|---|
| HTTP proxy | -x http://HOST:PORT |
| HTTPS proxy (TLS to the proxy) | -x https://HOST:PORT |
| SOCKS5, local DNS | -x socks5://HOST:PORT |
| SOCKS5, remote DNS | -x socks5h://HOST:PORT |
HTTP and HTTPS proxies
# Reach an https site through a plain HTTP proxy - this is normal
curl -x http://HOST:PORT https://example.com
# Proxy that itself speaks TLS
curl -x https://HOST:PORT https://example.com
Note the two levels of TLS. http:// vs https:// in the -x value describes the hop from you to the proxy; the https:// in the target URL is the hop from the proxy to the site. Most datacenter proxies use an http:// scheme even when you are fetching https pages, so start there.
SOCKS5 and the socks5:// vs socks5h:// distinction
curl -x socks5://HOST:PORT https://example.com
curl --socks5 HOST:PORT https://example.com # same thing
# Let the PROXY resolve the hostname (remote DNS)
curl -x socks5h://HOST:PORT https://example.com
Here is the detail most guides skip. With socks5:// cURL resolves the target hostname on your machine and sends the proxy an IP address. With socks5h:// cURL sends the hostname and the proxy does the DNS lookup. Use socks5h:// whenever you want DNS to happen at the exit, for example to avoid local DNS leaks or to resolve a name that only exists on the proxy's network.
cURL proxy authentication (-U / --proxy-user)
Most paid proxies require a username and password. Two ways to supply them:
# Dedicated flag (-U is short for --proxy-user)
curl -x http://HOST:PORT -U USER:PASS https://example.com
curl -x http://HOST:PORT --proxy-user USER:PASS https://example.com
# Credentials embedded in the proxy URL
curl -x http://USER:PASS@HOST:PORT https://example.com
The gotcha that causes most 407 errors: when you embed credentials in the URL, any special character in the password must be URL-encoded, or cURL misreads the string and the proxy rejects you. Encode @ as %40, : as %3A, # as %23, and so on:
# Password is p@ss:word -> encode it in the URL
curl -x "http://user:p%40ss%3Aword@HOST:PORT" https://example.com
# Or sidestep encoding entirely with -U (quote it for the shell)
curl -x http://HOST:PORT -U 'user:p@ss:word' https://example.com
The -U form only splits on the first colon, so a colon inside the password is fine there. --proxy-user works for SOCKS5 authentication too, not just HTTP.
Set a proxy with environment variables (HTTP_PROXY / HTTPS_PROXY)
Set the proxy once in your shell and every cURL call in that session uses it. The syntax differs by shell, which is where cross-platform tutorials usually go wrong.
# Unix / macOS (bash, zsh)
export http_proxy="http://USER:PASS@HOST:PORT"
export https_proxy="http://USER:PASS@HOST:PORT"
export NO_PROXY="localhost,127.0.0.1,.internal.example.com"
curl https://example.com
# Windows PowerShell (curl is an alias here - call curl.exe)
$env:HTTP_PROXY = "http://USER:PASS@HOST:PORT"
$env:HTTPS_PROXY = "http://USER:PASS@HOST:PORT"
curl.exe https://example.com
:: Windows cmd.exe
set HTTP_PROXY=http://USER:PASS@HOST:PORT
set HTTPS_PROXY=http://USER:PASS@HOST:PORT
curl https://example.com
Two things to know. For the plain HTTP variable cURL reads only the lowercase http_proxy (a deliberate security choice); HTTPS_PROXY and NO_PROXY work in either case. And NO_PROXY (or the per-call --noproxy flag) lists hosts that should bypass the proxy. A per-request -x always overrides whatever the environment set:
# Ignore the env proxy for these hosts
curl --noproxy example.com,localhost https://example.com
# -x wins over the environment variables for this one call
curl -x http://OTHER_HOST:PORT https://example.com
Make cURL always use a proxy (.curlrc)
For a proxy you use constantly, put it in cURL's config file so you never type the flag again. On Unix and macOS that is ~/.curlrc; on Windows it is _curlrc in your home directory or at %APPDATA%\_curlrc. Add one line:
# ~/.curlrc (or %APPDATA%\_curlrc on Windows)
proxy = "http://USER:PASS@HOST:PORT"
Every cURL command now goes through that proxy automatically. To bypass it for a single call without editing the file, disable the proxy inline:
curl --noproxy '*' https://example.com # ignore the config proxy
curl -x '' https://example.com # empty proxy = direct connection
Rotate proxies per request
Two honest patterns cover almost every rotation need. The first uses a provider's rotating gateway - a single endpoint that hands you a fresh exit IP on each request, so you just call it in a loop:
# Rotating gateway endpoint (Webshare exposes one at p.webshare.io:80;
# check your dashboard for the exact host and rotation setting)
for i in $(seq 1 5); do
curl -s -x http://USER:[email protected]:80 https://ipinfo.io/ip
done
The second gives you full control by looping over your own proxy-list file, one -x per line. Webshare and most providers let you export the list in host:port:user:pass format, which parses cleanly:
# proxies.txt: one host:port:user:pass per line
while IFS=: read -r host port user pass; do
curl -s -x "http://$user:$pass@$host:$port" https://ipinfo.io/ip
done < proxies.txt
Scrape responsibly. Pull only public data, respect each site's robots.txt and terms of service, throttle your request rate, and stay off anything behind a login. That is good practice, not legal advice - check the rules for your own project and jurisdiction. If rotation is the heart of your workflow, our guides to rotating proxies and proxies for web scraping go deeper than a code snippet can.
Verify cURL is using the proxy (check your IP)
Never assume the proxy took. Ask an echo service what IP the site actually saw:
# Should print the proxy's exit IP, not yours
curl -x http://USER:PASS@HOST:PORT https://ipinfo.io/ip
curl -x http://USER:PASS@HOST:PORT http://httpbin.org/ip
# See the proxy handshake and CONNECT line
curl -v -x http://USER:PASS@HOST:PORT https://example.com
Compare the result against a direct call (curl https://ipinfo.io/ip with no proxy). If the two IPs differ, the proxy is working; if they match, cURL is still going out direct and your -x or environment variable is not being applied. The -v output shows the CONNECT line to the proxy, which is the quickest way to confirm the route.
Common cURL proxy errors and how to fix them
| Error | Likely cause | Fix |
|---|---|---|
407 Proxy Authentication Required | Missing or wrong credentials, or a special character in a URL-embedded password that was not encoded | Add -U 'user:pass', or URL-encode the password (@ -> %40, : -> %3A) |
curl: (7) Couldn't connect to proxy | Wrong host, port, or scheme | Recheck HOST:PORT; try http:// vs socks5://; confirm the proxy is up and reachable |
curl: (56) / SSL cert error via an HTTPS proxy | The proxy's TLS certificate is not trusted | For testing only, add --proxy-insecure or point --proxy-cacert at the CA; fix the cert properly for production |
| Site resolves against your local DNS on SOCKS5 | Using socks5:// when you wanted remote DNS | Switch to socks5h:// so the proxy resolves the hostname |
| Request hangs or never returns | Dead proxy or a slow target | Add --connect-timeout 10 and --max-time 30 to fail fast |
Nine out of ten "curl proxy not working" reports are the first row: a 407 from an un-encoded password. Reach for -U before you reach for anything else.
Which proxy type should you use with cURL?
cURL treats every proxy the same, so the choice is about the target, not the tool. The honest three-line steer:
- Datacenter proxies - fastest and cheapest, but easier to detect, so best for high-volume scraping of low-defense public sites.
- Residential proxies - harder to block because they read as real home users, but pricier and usually billed per GB.
- ISP (static residential) proxies - the middle ground: a datacenter's speed with a residential-looking, stable IP.
For a developer who just wants a plain endpoint that drops into curl -x and a free tier to test on, Webshare is the easy value pick - low cost, developer-friendly, and a host:port:user:pass string with no wrapper to fight. It is not the only option: Bright Data, Oxylabs, and IPRoyal all run larger or more specialised residential networks if you need them (note that Oxylabs owns Webshare, so treat them as related, not independent rivals). You can start with Webshare's free proxies, or compare the whole market in our best proxy services hub.
FAQ
Does cURL support SOCKS5 proxies?
Yes. Use -x socks5://HOST:PORT or --socks5 HOST:PORT. Switch to socks5h:// when you want the proxy, not your machine, to resolve the target hostname (remote DNS).
How do I set a proxy only for HTTPS requests?
Set the https_proxy (or HTTPS_PROXY) environment variable and leave http_proxy unset, so only https traffic is routed. For a single call, just add -x to the https command and nothing else.
How do I make cURL ignore the proxy for one request?
Use curl --noproxy '*' URL or curl -x '' URL. Either one overrides an environment variable or a .curlrc proxy for that single call and connects directly.
Why is my cURL proxy returning 407?
A 407 means the proxy rejected your credentials. Either you did not pass a username and password, or a special character in a URL-embedded password was not URL-encoded. Add -U 'user:pass', or encode the password (@ becomes %40).
Can I rotate IPs with cURL?
Yes, two ways: call a provider's rotating gateway endpoint in a loop to get a new IP each request, or loop over your own proxy-list file with one -x per line. For the same job in Python, see using a proxy with Python requests.