Authenticating Curl Through a Proxy: Commands That Work
The command that works, the libcurl equivalent, what --proxy-anyauth is for, and what to try when the proxy refuses Basic authentication.
!Hands adjusting proxy network hardware
Need the working command right now? Here it is: curl -x http://proxy:8080 -U user:pass https://example.com. That single line handles curl proxy authentication for most HTTP and HTTPS proxies. If the proxy doesn't accept Basic auth outright and needs to negotiate, add --proxy-anyauth and let curl figure out the scheme. If you already know the scheme, skip the guesswork and force it with --proxy-basic, --proxy-ntlm, --proxy-digest, or --proxy-negotiate.
For libcurl, the C API equivalent takes three calls: set CURLOPT_PROXY to your proxy URL, set CURLOPT_PROXYUSERPWD to "user:pass", and optionally set CURLOPT_PROXYAUTH to CURLAUTH_ANY or a specific bitmask like CURLAUTH_NTLM.
- CLI:
curl -x http://proxy:8080 -U user:pass https://example.com - Force a scheme: add
--proxy-ntlm,--proxy-digest, or--proxy-basic - libcurl:
CURLOPT_PROXY,CURLOPT_PROXYUSERPWD,CURLOPT_PROXYAUTH
Pro Tip: -U authenticates you to the proxy. -u authenticates you to the destination server. Mixing them up is the single most common mistake in curl proxy setup, and it produces a 407 that looks identical to a bad password.
Key Takeaways
Curl proxy authentication comes down to matching the right flag (-U, --proxy-anyauth, or a forced scheme) to what the proxy actually supports, and never leaving credentials exposed in plain text.
| Point | Details | | --- | --- | | Use -U, not -u | -U sends credentials to the proxy; -u sends them to the destination server, and mixing them causes silent 407 failures. | | Force schemes when known | Skip --proxy-anyauth's extra round-trip by using --proxy-ntlm or --proxy-digest once you know the proxy's scheme. | | Encode special characters | Percent-encode colons and at-signs in embedded proxy credentials so curl doesn't misparse the URL. | | Diagnose with -v | curl -v reveals the Proxy-Authenticate header on a 407, telling you exactly which scheme to force. | | Manage credentials centrally | Node4 handles HTTP and SOCKS5 authentication through a dashboard and API, replacing scattered per-script credentials with instant, trackable provisioning. |
Table of Contents
- [Curl Proxy Authentication Command Examples for Common Scenarios](#curl-proxy-authentication-command-examples-for-common-scenarios)
- [Setting Proxy Authentication in Libcurl (C API)](#setting-proxy-authentication-in-libcurl-c-api)
- [HTTP vs SOCKS Proxies and Which Auth Scheme to Use](#http-vs-socks-proxies-and-which-auth-scheme-to-use)
- [Environment Variables and Encoding Rules You Need to Know](#environment-variables-and-encoding-rules-you-need-to-know)
- [How to Fix a 407 Proxy Authentication Required Error](#how-to-fix-a-407-proxy-authentication-required-error)
- [What Most Curl Proxy Guides Get Wrong](#what-most-curl-proxy-guides-get-wrong)
- [A Managed Alternative to Ad-Hoc Proxy Configuration](#a-managed-alternative-to-ad-hoc-proxy-configuration)
- [Sources](#sources)
Curl Proxy Authentication Command Examples for Common Scenarios
Every proxy auth scenario in curl boils down to combining -x (set the proxy) with a credential flag. Here are the patterns you'll actually use.
- Basic auth over HTTP proxy.
curl -x http://proxy.example.com:8080 -U myuser:mypass https://api.example.com. This is the default: curl tries Basic first unless told otherwise. - Avoid exposing the password in your shell history. Run
curl -x http://proxy.example.com:8080 -U myuser https://api.example.comand curl prompts for the password interactively, keeping it out ofpsoutput and shell logs. - Force a specific scheme. If you already know the proxy expects NTLM, skip negotiation entirely:
curl -x http://proxy.example.com:8080 --proxy-ntlm -U 'DOMAIN\user:pass' https://api.example.com. Swap in--proxy-digestor--proxy-basicas needed. - Let curl negotiate.
curl -x http://proxy.example.com:8080 --proxy-anyauth -U user:pass https://api.example.comasks the proxy which schemes it supports before committing. It works reliably, but it costs an extra round-trip compared to specifying the scheme upfront, which matters if you're firing thousands of requests through a scraping pipeline. - SOCKS5 proxy.
curl --socks5 proxy.example.com:1080 -U user:pass https://example.comor equivalentlycurl -x socks5://user:pass@proxy.example.com:1080 https://example.com.
On the security note: credentials passed via -U or embedded in a -x URL are visible to anyone who can read your shell history or process list on a shared machine. Prefer the interactive prompt, a .netrc file, or an environment variable set in a script that isn't logged.
Most of these commands eventually have to move out of a terminal and into application code, and that translation is where the proxy argument is most often dropped or mistranslated between libraries. The curl converter takes a working command and emits the equivalent Python, Node.js, PHP or Go, proxy flags included, which is a faster route to a correct first request than rewriting the invocation from memory. It sits alongside the rest of the free developer tools.
Setting Proxy Authentication in Libcurl (C API)
If you're building the request in C rather than shelling out to the curl binary, the mapping from CLI flags to curl_easy_setopt calls is direct. You set three options and you're done.
CURLOPT_PROXYaccepts the proxy URL, either bare (http://proxy.example.com:8080) or with embedded credentials (http://user:pass@proxy.example.com:8080).CURLOPT_PROXYUSERPWDtakes a"username:password"string as an alternative to embedding credentials in the URL, and curl URL-decodes this string, so a literal colon in your username needs to be encoded as%3Aor it will be misread as the separator.CURLOPT_PROXYAUTHsets the allowed authentication bitmask:CURLAUTH_BASIC,CURLAUTH_NTLM,CURLAUTH_DIGEST, orCURLAUTH_ANYto let curl pick.
Setting
CURLOPT_PROXYAUTHtoCURLAUTH_ANYtell libcurl which HTTP proxy authentication methods to allow, and lets curl query the proxy to pick one it supports. That flexibility isn't free: it triggers an extra request/response cycle before the real transfer starts, the same latency cost you see with--proxy-anyauthon the command line.
A minimal pattern looks like this:
curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy.example.com:8080");
curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, "myuser:mypass");
curl_easy_setopt(curl, CURLOPT_PROXYAUTH, (long)CURLAUTH_ANY);libcurl copies the string you pass to CURLOPT_PROXYUSERPWD internally, so you don't need to keep the buffer alive after the call, and calling the option again simply overwrites the previous value.
HTTP vs SOCKS Proxies and Which Auth Scheme to Use
Not every proxy speaks the same protocol, and not every scheme fits every situation. Here's how curl handles the split.
- HTTP proxies are set with
-x http://host:portand handle CONNECT tunneling for HTTPS traffic, negotiating auth at the proxy layer before your request ever reaches the origin server. - SOCKS proxies use
-x socks5://host:portor--socks5, and operate at a lower network layer with simpler, mostly username/password authentication, no header-based challenge involved. - Basic auth sends credentials in a Base64-encoded header on every request; it's simple but offers no protection if the connection isn't encrypted.
- Digest avoids sending the password itself, using a challenge-response hash instead, which makes it marginally safer over plain HTTP.
- NTLM and Negotiate show up in enterprise and Windows-integrated environments; on SSPI-enabled curl builds, passing
-U :lets curl authenticate as the currently logged-in Windows user without typing a password at all. - Run
curl -vagainst the proxy first. TheProxy-Authenticateheader in the 407 response lists exactly which schemes the proxy will accept, so you're not guessing.
Environment Variables and Encoding Rules You Need to Know
curl reads http_proxy, https_proxy, and ALL_PROXY automatically, and it honors NO_PROXY to bypass the proxy entirely for listed hosts. ALL_PROXY acts as a catch-all when protocol-specific variables aren't set, but an explicit https_proxy always wins over it for HTTPS traffic.
http_proxymust be lowercase. An uppercaseHTTP_PROXYhas historically been exploitable in CGI environments, since it can be set by an attacker-controlled request header.- Credentials embedded in a proxy URL are URL-decoded by curl, so characters like
@and:inside a username or password must be percent-encoded, or curl misparses where the credentials end and the host begins. - Never hardcode proxy credentials directly in a script that gets checked into version control.
Pro Tip: Store proxy credentials in a .netrc file with 600 permissions, or pull them from an environment variable set at runtime. Both keep secrets out of your shell history and out of curl -v transcripts you might paste into a support ticket.
How to Fix a 407 Proxy Authentication Required Error
A 407 means the proxy rejected your credentials or received none at all. Work through this in order.
- Run
curl -vagainst the target. The verbose output shows the exactProxy-Authenticateheader the proxy sent back, telling you which schemes it supports before you waste time guessing. - Force the reported scheme. If the header says
NTLMbut you used default Basic auth, add--proxy-ntlmand retry. - Double-check the proxy URL itself. A missing
socks5://prefix, wrong port, or typo in the hostname produces failures that look like auth problems but aren't. - Check
NO_PROXYif you expected bypass behavior. A host that should skip the proxy but doesn't (or vice versa) usually traces back to a mismatchedNO_PROXYpattern. - Test with known-good credentials on a trivial request first.
curl -v -x http://proxy:8080 -U user:pass https://example.comisolates whether the problem is your credentials, your encoding, or the proxy configuration itself.
If step one shows no Proxy-Authenticate header at all, the proxy isn't asking for auth. Something else is wrong, likely a network or firewall issue rather than curl.
What Most Curl Proxy Guides Get Wrong
Most tutorials treat --proxy-anyauth as the safe default, and for a one-off request, it is. But teams running curl at any real volume, thousands of scrapes an hour, a CI pipeline hitting an internal proxy on every build, pay for that convenience in latency. Every negotiated request costs an extra round-trip, and at scale that adds up to real time lost to a handshake you could have skipped by just knowing your proxy's scheme in advance.
The bigger gap I see is in credential handling. Developers get the -U and -x flags right, then paste the password straight into a shell script that lands in a git repo. The mechanics of curl proxy authentication are genuinely simple. The discipline around where those credentials live is where most setups actually fail. Prioritize that first: pick one credential storage method (.netrc, a secrets manager, environment injection at runtime) and standardize it across your team before you worry about which auth scheme shaves off milliseconds.
If your infrastructure is stable, force the scheme every time. Reserve --proxy-anyauth for exploratory work against a proxy you don't control yet.
A Managed Alternative to Ad-Hoc Proxy Configuration
Getting -U, --proxy-anyauth, and CURLOPT_PROXYAUTH right is one problem. Keeping credentials, IP pools, and uptime consistent across a team running thousands of requests a day is another. Node4 runs on fully owned infrastructure across IP blocks we own, supporting both HTTP and SOCKS5 endpoints with flexible authentication you manage from a dashboard or REST API instead of scattering credentials across scripts.
That owned-infrastructure model is what removes the ad-hoc troubleshooting this article just walked through: no chasing down which scheme a shared proxy supports, no guessing whether a 407 means bad credentials or a dead endpoint. Real-time analytics and role-based access control mean your team provisions new proxy users instantly rather than passing around a shared password file. Whether you need dedicated datacenter proxies for consistent, high-throughput scraping or residential proxies for geo-targeted access, provisioning is instant and authentication stays predictable across every request your team sends. Check current plans and spin up your first proxy user on the Node4 dashboard to see how it fits your stack.
Sources
Recommended
Related reading
- Proxy authentication methods covers the
same credentials outside curl, including header and IP-whitelist auth.
- Proxy error codes explained is the place to
start when a command that looks right still fails.