You have a proxy address from your provider and want to know whether it works before it goes into a scraper, a cron job or a CI pipeline. cURL is the quickest check: one command sends a request through the proxy and prints the IP address the target site sees, and the same command then drops straight into a shell script.
This article covers the -x option, credentials, SOCKS5, proxy settings for every command, a download script with retries and the exact error messages. Every command was run with curl 8.21 against a local test proxy; the options are documented in the curl man page.
What is cURL?
cURL (pronounced "curl") is a command-line tool that transfers data with URLs: it downloads pages and files, sends forms and API requests, and prints or saves the response. The work is done by libcurl, a transfer library that PHP and other languages also use.
Every command has the same form:
curl [options] [URL]There are more than 250 options. -o page.html saves the response to a file, -I fetches only the headers, -L follows redirects and -x uses a proxy. Options are case sensitive: -x sets a proxy, -X sets the HTTP method.
cURL ships with macOS, with Windows 10 and 11 as curl.exe, and with most Linux distributions; minimal container images may need it installed (apt install curl on Debian and Ubuntu). Run curl --version: if the Features: line contains HTTPS-proxy, your build can also reach a proxy over TLS.
Which protocols does cURL support?
cURL works only with protocols that can be written as a URL. The current release lists DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. curl --version shows what your build supports; RTMP, found in older lists, is gone.
Without a scheme, cURL guesses from the host name (ftp.example.com means FTP, most names HTTP). For proxies this matters in one way: an HTTP proxy carries HTTP and HTTPS; other protocols pass only through a CONNECT tunnel (-p) and only if the proxy allows that port. SOCKS5 carries any TCP connection, so FTP or SMTP through a proxy usually means SOCKS5.
Why use cURL with a proxy?
- Visible steps.
-vprints the connection to the proxy, the CONNECT request and both answers, so you see where a request fails. - Every proxy type in one option. HTTP, HTTPS, SOCKS4, SOCKS4a, SOCKS5 and SOCKS5h all go through
-x. - Scripting. Exit codes,
--retry, timeouts and--write-outlet a shell script handle failures, and PHP'scurl_*functions take the same options. - Many URLs in one command. URL globbing such as
page[1-20].htmlor{a,b,c}expands into several requests, all through the same proxy.
Typical jobs: checking an exit IP's country before a data scraping run, testing price monitoring targets from another market, and downloads in scheduled jobs. Node.js equivalents are in cURL in JavaScript, PHP ones in PHP Web Scraping.
How does cURL send a request through a proxy?
- cURL connects to the proxy, not to the target.
- HTTP target, HTTP proxy: cURL sends the request with the full URL (
GET http://example.com/ HTTP/1.1). The proxy can read it. - HTTPS target, HTTP proxy: cURL sends
CONNECT example.com:443, with aProxy-Authorizationheader if you gave credentials. After the proxy answers200, TLS to the target runs inside that tunnel, so the proxy sees only the host and port. The CONNECT method is defined in RFC 9110. - SOCKS5 proxy: cURL logs in (with username and password, if given) and asks the proxy to connect to the target (RFC 1928). With
socks5://it sends an IP it resolved itself; withsocks5h://it sends the host name. - The target answers to the proxy's IP. Your IP does not reach it, but your DNS queries can if cURL resolves names locally.
How to set a proxy in cURL: the -x option
curl --help proxy lists every proxy option. The main one:
-x, --proxy <[protocol://]host[:port]> Use this proxy-x and --proxy are the same option:
curl -x "http://user:pass@pr.proxynet.io:8000" https://httpbin.org/iphttpbin.org/ip returns the IP your request came from, so with a working proxy it shows the proxy's exit IP.
- No scheme means HTTP.
-x "user:pass@pr.proxynet.io:8000"behaves like thehttp://form. - Always write the port. Without it cURL picks a default: in our curl 8.21 test 80 for
http://, 443 forhttps://and 1080 for SOCKS (the manual still says 1080). None of these is likely to be your provider's port, so the connection fails or times out. - Quote the address so the shell does not interpret
&,?or!. -xis per command and overrides proxy environment variables. The next command goes out directly again.
On Proxynet's residential and mobile products, one gateway serves HTTP and SOCKS5 on separate ports, and the panel's Endpoint Generator builds the username with the country, city and session you pick.
How do you use cURL with an HTTP or HTTPS proxy?
An HTTP proxy carries both kinds of target:
# HTTPS target: CONNECT tunnel, the page stays encrypted
curl -x "http://user:pass@pr.proxynet.io:8000" https://httpbin.org/ip
# HTTP target: the proxy forwards the plain request
curl -x "http://user:pass@pr.proxynet.io:8000" http://httpbin.org/ipAn HTTPS proxy (https://) also encrypts the connection to the proxy itself. Use it only if the port speaks TLS; https:// pointed at a plain HTTP port fails in the handshake (SEC_E_INVALID_TOKEN on Windows, typically wrong version number with OpenSSL).
Certificate options are split between the two connections:
-k(--insecure) skips certificate checks for the target site only. With anhttp://target it does nothing.--proxy-insecureskips the check of an HTTPS proxy's certificate.--proxy-cacert file.pemis safer: it trusts a company proxy's CA without disabling checks.
Keep -k for quick tests, never in scripts that send tokens. For non-HTTP protocols through an HTTP proxy, add -p (--proxytunnel). See the HTTPS Proxy page for how encrypted traffic passes a proxy.
How do you pass a proxy username and password?
Both forms send the same Proxy-Authorization header:
curl -x "http://user:pass@pr.proxynet.io:8000" https://httpbin.org/ip
curl -x "http://pr.proxynet.io:8000" -U "user:pass" https://httpbin.org/ipInside the address, special characters in the password must be percent-encoded: @ as %40, : as %3A, # as %23. cURL decodes them before sending; in our test p%40ss reached the proxy as p@ss. With -U (--proxy-user) no encoding is needed. Basic authentication is the default; company proxies may need --proxy-ntlm, --proxy-digest or --proxy-anyauth.
Passwords on the command line land in the shell history. In scripts, read them from a private config file (-K file) or use an IP whitelist instead (Proxynet accepts up to 10 IPs). Proxy Authentication: User:Pass vs IP Whitelist compares both and explains the 407 error.
How do you use cURL with a SOCKS5 proxy?
Write the SOCKS version as the scheme:
curl -x "socks5h://user:pass@pr.proxynet.io:1080" https://httpbin.org/ip| Scheme | Who resolves the host name | Username and password | Use it for |
|---|---|---|---|
http:// | The proxy | Yes | Web scraping, APIs, most tools |
https:// | The proxy | Yes | A proxy port that speaks TLS |
socks5h:// | The proxy | Yes | SOCKS5 with location-correct DNS |
socks5:// | Your machine | Yes | Targets only your DNS can resolve |
socks4a:// | The proxy | User ID only | Old SOCKS4 servers |
socks4:// | Your machine | User ID only | Old SOCKS4 servers |
With socks5://, your DNS server sees every host you visit and geo-aware sites answer for your location; socks5h:// avoids both (WebRTC and DNS Leaks explains why that matters). The older --socks5-hostname host:port equals socks5h://, with credentials in -U.
For the protocol differences, see SOCKS vs. HTTP Proxy and What Is a SOCKS5 Proxy?. Proxynet's SOCKS5 Proxy runs on its own port next to the HTTP port.
How do you set a proxy for every cURL command?
| Method | Scope | Example |
|---|---|---|
-x | One command | curl -x "http://user:pass@host:port" URL |
| Environment variable | The shell session | export https_proxy="http://user:pass@host:port" |
.curlrc | Every run of that user | proxy = "http://host:port" |
Environment variables. cURL reads http_proxy for HTTP targets, https_proxy or HTTPS_PROXY for HTTPS and ALL_PROXY as a fallback. http_proxy works only in lowercase (a protection for CGI programs), so HTTP_PROXY is ignored on Linux and macOS. In PowerShell: $env:HTTPS_PROXY = "http://user:pass@host:port". wget, pip and git read the same variables; see Using a Proxy with wget and the everything curl page on proxy variables.
The config file. cURL reads ~/.curlrc (Windows: %USERPROFILE%\.curlrc or _curlrc) before every run:
proxy = "http://pr.proxynet.io:8000"
proxy-user = "user:pass"curl -q URL, with -q first, skips it for one run.
Exceptions. --noproxy "localhost,.internal.example" or the NO_PROXY variable sends those hosts directly. A name also matches its subdomains, CIDR ranges like 192.168.0.0/16 work, and the only wildcard is a lone *. NO_PROXY applies even with -x.
cURL has no JavaScript engine, so it cannot run PAC files. If your network uses one, read it (What Is a PAC File?) and pass the proxy it returns with -x.
How do you check that cURL is using the proxy?
Run curl https://api.ipify.org without and with -x: a different address in the expected country means the proxy works. A healthy HTTPS request through an HTTP proxy shows these -v lines:
* Establishing HTTP proxy tunnel to httpbin.org:443
> CONNECT httpbin.org:443 HTTP/1.1
> Proxy-Authorization: Basic dXNlcjpwYXNz
< HTTP/1.1 200 Connection Established
* CONNECT tunnel established, response 200The Proxy-Authorization value is only Base64; remove it before sharing. In scripts, -w prints the result on one line:
curl -s -o /dev/null -x "http://user:pass@pr.proxynet.io:8000" \
-w "%{http_code} connect=%{http_connect} proxy_used=%{proxy_used}\n" https://httpbin.org/iphttp_connect is the proxy's answer to CONNECT; proxy_used (curl 8.7+) is 1 when a proxy was used. For location, speed and leak checks, see How to Test a Proxy.
Example: downloading a URL list through a proxy with retries
This script downloads the URLs in urls.txt four at a time through the proxy, retries temporary failures and prints each status and duration. It needs cURL and a POSIX shell (Linux, macOS or Git Bash):
#!/usr/bin/env bash
# fetch.sh: download every URL in urls.txt through the proxy, 4 at a time
set -u
PROXY="${PROXY:-http://user:pass@pr.proxynet.io:8000}"
sed 's/^/url = /' urls.txt | curl \
--parallel --parallel-max 4 \
--proxy "$PROXY" \
--connect-timeout 10 --max-time 30 \
--retry 3 --retry-connrefused \
--fail --silent --show-error \
--create-dirs --output-dir pages --remote-name-all \
--write-out "%{http_code} %{time_total}s %{url}\n" \
--config ---config -reads theurl = …lines fromsedand must come last, because--remote-name-allapplies only to URLs added after it.--retry 3retries timeouts and HTTP 408, 429, 500, 502, 503, 504, 522 and 524, waiting 1, 2 and 4 seconds and honouringRetry-After.--max-timestops a stalled transfer;--failturns HTTP errors into exit code 22.- Keep
--parallel-maxlow when all URLs are on one site; too many parallel requests can bring 429 responses.
In our test, four pages were saved and a 503 URL was retried three times before the script exited with code 22.
Repeat a request against api.ipify.org to see whether your gateway rotates: a rotating gateway returns a new IP each time, a sticky session keeps one IP for 1 to 60 minutes on Proxynet. What Is IP Rotation? explains when to use each; Residential Proxy supports both.
Common cURL proxy errors and how to fix them
Messages as printed by curl 8.21 in our tests:
curl: (5) Could not resolve proxy: …The proxy host name is wrong: check spelling and stray quotes.curl: (7) Failed to connect to … over proxy …Nothing answers on that port (or cURL fell back to a default port because none was given), or a firewall blocks it.curl: (7) CONNECT tunnel failed, response 407Wrong credentials, unencoded special characters or an IP not on the whitelist. Older versions printcurl: (56) Received HTTP code 407 from proxy after CONNECT; forhttp://targets you simply get status 407. See HTTP Status Codes in Web Scraping.curl: (56) Proxy CONNECT abortedThe proxy closed the connection; in our test, anhttp://address pointed at a SOCKS5 port.curl: (97) Received invalid version in initial SOCKS5 response.Asocks5://address points at an HTTP port.User was rejected by the SOCKS5 servermeans wrong SOCKS credentials.curl: (28) Connection timed out after … millisecondsNo answer in time; see Proxy Server Not Responding.curl: (35) …orSSL_ERROR_SYSCALLThe TLS handshake failed:https://on a plain proxy port, or a device cutting TLS connections.curl: (60) SSL certificate problem: unable to get local issuer certificateOften a company proxy inspecting TLS. Install its CA certificate instead of using-k.- The proxy is ignored. Look for
NO_PROXY, uppercaseHTTP_PROXYor another.curlrc;-vshows which address cURL tries first. Python's version of these failures is covered in Max Retries Exceeded With URL.
Decision guide
| Need | Recommendation |
|---|---|
| Test a new proxy once | curl -x "http://user:pass@host:port" https://httpbin.org/ip |
Password contains @, : or # | -U "user:pass", or percent-encode it |
| DNS resolved at the proxy | socks5h://, not socks5:// |
| FTP, SMTP or another non-HTTP protocol | SOCKS5, or -p with an HTTP proxy |
| Proxy for a shell session | export https_proxy=… and lowercase http_proxy |
| Proxy for every run | proxy = "…" in ~/.curlrc |
| No password in scripts | IP whitelist in the panel |
| Same IP for a login flow | Sticky session from the Endpoint Generator |
Frequently asked questions
Does cURL use the system proxy settings on Windows or macOS?
No. cURL takes a proxy only from -x, from environment variables and from .curlrc. A proxy set in Windows Settings or macOS System Settings does not affect it.
How do I make cURL ignore the proxy for one request?
Add --noproxy "*" or -x "". Either sends that command directly even when https_proxy or .curlrc sets a proxy.
Why does my cURL proxy command fail in PowerShell?
In Windows PowerShell 5.1, curl is an alias for Invoke-WebRequest, which does not know -x. Type curl.exe to run the real cURL. PowerShell 7 no longer has this alias.
What is the difference between socks5 and socks5h in cURL?
With socks5:// your machine resolves the host name; with socks5h:// the proxy does, so DNS matches the proxy's location.
Can I use a proxy with cURL in PHP?
Yes. PHP's cURL functions use libcurl: CURLOPT_PROXY sets the address, CURLOPT_PROXYUSERPWD the credentials and CURLOPT_PROXYTYPE the SOCKS type. Examples are in PHP Web Scraping.
Can cURL rotate proxies on every request?
cURL uses one proxy per command. A rotating gateway assigns a new exit IP per connection, so a loop of commands gets a different IP each time. Several URLs in one command usually reuse one connection and share its IP.
Summary
To use cURL with a proxy, add -x with the full address: scheme, credentials, host and port. Use http:// for most jobs and socks5h:// for SOCKS5 with remote DNS, put the proxy in https_proxy or .curlrc when every command needs it, and keep -k for tests. When a command fails, the exit code and -v output show whether the address, the credentials or the target is at fault. For residential, mobile and SOCKS5 endpoints that work with these commands, see Proxynet proxies.




