Key Takeaways
A practical curl proxy-routing guide covering environment-variable precedence, NO_PROXY overrides, safe diagnostics, failure classification, and credential hygiene.
curl can select a proxy from environment variables even when the command line contains no --proxy option. That is useful for developer shells, CI runners, containers, and service processes—but it also means two machines can run the same curl command and take different network paths.
This guide shows how curl evaluates http_proxy, HTTPS_PROXY, ALL_PROXY, and NO_PROXY, how command-line options interact with them, and how to prove which route was actually used without exposing proxy credentials.
Direct answer
For curl:
- use lowercase
http_proxyfor HTTP target URLs; - use
https_proxyorHTTPS_PROXYfor HTTPS target URLs; - use
ALL_PROXYorall_proxyonly as a fallback when no protocol-specific proxy variable applies; - use
NO_PROXYorno_proxyto bypass the proxy for selected destinations; - use
--proxywhen you want to select a proxy explicitly for one command; - remember that
NO_PROXYcan still bypass an explicitly supplied--proxyunless you override the no-proxy list; - do not depend on uppercase
HTTP_PROXY: curl intentionally acceptshttp_proxyonly in lowercase.
These are curl/libcurl rules, not a universal standard. Other clients can differ in case handling, precedence, wildcard matching, and CIDR support.
How curl chooses the route
The target URL scheme decides which protocol-specific proxy variable curl checks. An https:// target therefore uses the HTTPS proxy setting, even when the selected proxy itself is an ordinary http:// proxy.
| Configuration | What curl does | Important boundary |
|---|---|---|
http_proxy | Selects a proxy for HTTP target URLs | Accepted in lowercase only |
https_proxy / HTTPS_PROXY | Selects a proxy for HTTPS target URLs | The variable name describes the target scheme, not necessarily the client-to-proxy transport |
all_proxy / ALL_PROXY | Fallback when no scheme-specific proxy variable applies | A matching protocol-specific variable takes precedence |
no_proxy / NO_PROXY | Bypasses proxy use for matching destinations | Can also suppress a proxy supplied with --proxy |
--proxy | Selects a proxy explicitly | Overrides proxy-selection environment variables, but does not automatically cancel NO_PROXY |
--noproxy | Sets the no-proxy list explicitly | --noproxy "" overrides an inherited NO_PROXY exclusion |
That distinction matters during debugging. If --proxy appears to be ignored, inspect NO_PROXY before assuming the proxy option failed.
Why http_proxy is lowercase-only
CGI environments historically translate incoming HTTP request headers into environment variables prefixed with HTTP_. An incoming Proxy header can therefore become HTTP_PROXY inside a CGI process.
If an HTTP client trusted that uppercase variable, request-controlled input could influence an outbound proxy setting. curl avoids that class of problem by recognizing http_proxy only in lowercase. curl's current proxy documentation describes this exception, and RFC 3875 documents CGI's HTTP_ meta-variable convention.
Operational rule: do not “fix” curl proxy routing by exporting uppercase HTTP_PROXY. Set lowercase http_proxy, or use an explicit --proxy option for a controlled test.
Safe baseline: inspect configuration without dumping secrets
Do not start with env, set, or a complete CI environment dump. Proxy variables frequently contain credentials.
First check only whether relevant variables exist:
Then record the curl build you are actually debugging:
This matters because behavior such as CIDR matching in no-proxy lists is version-dependent.
Test proxy selection with one controlled request
Use documentation placeholders and an authorized target:
proxy.example.net and the credentials above are placeholders. Use the timeout values as starting guardrails, then tune them from behavior you observe in your own environment rather than treating them as BytesFlows performance targets.
For account-specific BytesFlows hostnames, ports, usernames, GEO selectors, and session controls, copy the current values from the Dashboard rather than reconstructing them from an article or screenshot.
Prove the effect of NO_PROXY
Suppose the environment contains:
This request is expected to bypass the proxy because the destination matches NO_PROXY:
Adding --proxy alone does not necessarily cancel that bypass:
To perform a controlled test that explicitly clears the no-proxy exclusion for that command, curl documents an empty --noproxy value:
Conversely, to suppress an environment-selected proxy for one request, use an empty proxy value:
These are diagnostic boundaries. Do not leave temporary overrides in production configuration after the cause is understood.
NO_PROXY matching rules worth testing explicitly
curl supports comma-separated exclusions including hostnames, domain entries, numerical IP addresses, a single * that matches all hosts, and CIDR notation in curl 7.86.0 and later.
Example:
Before deploying a list like this, record:
- the exact curl version;
- the target hostname exactly as curl receives it;
- whether the target is a hostname, IPv4 address, or IPv6 address;
- whether a domain entry is intentionally broad;
- whether a CIDR rule is supported by every deployed curl version;
- whether the direct route is intended in every environment.
Avoid assuming shell glob syntax such as *.internal.example is portable proxy-exclusion syntax. A broad NO_PROXY=* disables proxy use for all matching requests and should be treated as a high-impact configuration change.
Use a route matrix instead of guessing
When development works but CI or production does not, compare one variable at a time.
| Test | Purpose | Evidence to record |
|---|---|---|
| Environment only | Reproduce inherited routing | curl exit code, HTTP status, sanitized route evidence |
--proxy '' | Force direct routing for comparison | Whether the failure changes before/after proxy removal |
Explicit --proxy | Remove ambiguity from proxy-selection variables | Selected proxy endpoint, sanitized |
Explicit --proxy • --noproxy '' | Rule out inherited NO_PROXY bypass | Whether proxy routing is restored |
Known intended NO_PROXY entry | Verify a deliberate direct-route exception | Destination and direct-route result |
Change only one routing input between runs. Otherwise a successful retry does not tell you whether the cause was proxy selection, DNS, authentication, target behavior, or an unrelated network change.
Failure classification
| Observation | Likely stage | Next check |
|---|---|---|
| Proxy hostname cannot resolve | Client-side proxy endpoint DNS | Check the configured hostname and resolver path |
| Connection refused or timeout before HTTP | Network/proxy endpoint reachability | Record exact curl exit code; check route and port |
407 Proxy Authentication Required | Proxy authentication | Verify current account credentials and auth method |
| Request unexpectedly goes direct | Proxy selection / no-proxy exclusion | Inspect NO_PROXY, --noproxy, and inherited service environment |
HTTP 403, 429, or application error after connection | Target or policy layer | Do not classify it as an environment-variable failure without additional evidence |
A returned HTTP status is not the same thing as a curl process exit code. Preserve both when debugging.
Keep proxy credentials out of evidence bundles
Proxy URLs can contain usernames and passwords. Environment variables can leak through CI logs, crash reports, shell history, support bundles, process inspection, screenshots, or accidental debug output.
Prefer secret injection for credentials and keep non-secret endpoint configuration separate where practical. Do not commit real proxy URLs to repositories or copy complete environment dumps into tickets.
A useful sanitized evidence record is:
Never include a proxy password, Proxy-Authorization value, session token, full account username, or raw environment dump.
Common mistakes
Setting only HTTP_PROXY
curl intentionally does not treat uppercase HTTP_PROXY as the HTTP proxy environment variable. Use lowercase http_proxy.
Expecting http_proxy to proxy an HTTPS target
Proxy-variable selection follows the target URL scheme. For an HTTPS target, inspect https_proxy / HTTPS_PROXY rather than assuming http_proxy applies.
Assuming HTTPS_PROXY means “HTTPS proxy”
It means “the proxy selected for HTTPS target URLs.” The proxy URL itself determines whether the client-to-proxy connection uses HTTP, HTTPS, SOCKS, or another supported proxy scheme.
Assuming --proxy always defeats NO_PROXY
Current curl documentation states that NO_PROXY can disable proxy use even when --proxy is supplied. Use --noproxy '' when you intentionally need to clear the inherited exclusion for a diagnostic run.
Treating NO_PROXY=* as harmless
A single * matches all hosts and can silently convert a proxied workload into direct traffic.
Printing the whole environment
That can leak credentials and account identifiers. Record presence and sanitized configuration instead.
Production checklist
http_proxy.NO_PROXY / no_proxy values in shells, containers, CI, and service managers.--proxy '', --noproxy '', NO_PROXY=*, and verbose tracing after diagnosis.FAQ
Does --proxy override HTTPS_PROXY or ALL_PROXY?
Yes for proxy selection: an explicit --proxy takes precedence over proxy-selection environment variables. However, a matching NO_PROXY can still result in a direct connection unless the no-proxy list is explicitly overridden.
How do I temporarily ignore NO_PROXY?
For a controlled curl command, use --noproxy ''. Do not permanently remove organization-wide exclusions without understanding why they exist.
How do I temporarily ignore all proxy environment variables?
Use --proxy '' for that request. This is useful as a direct-route control during troubleshooting.
Does HTTPS_PROXY=http://proxy.example.net:8000 make the proxy connection HTTPS?
No. HTTPS_PROXY is chosen because the target URL uses HTTPS. The proxy URL's own scheme determines how curl connects to the proxy.
Can I copy NO_PROXY rules from another language runtime?
Do not assume identical behavior. NO_PROXY is widely used but matching semantics vary between clients and runtimes. Test the exact curl version deployed in your environment.
Does a successful curl request prove the requested proxy geography or session behavior?
No. It proves only what the captured evidence demonstrates. Verify exit IP, requested versus observed GEO, and session behavior separately when those properties matter.
Related BytesFlows guides
For account-specific endpoint, port, GEO, authentication, and session settings, use the BytesFlows proxy setup guide. For credential lifecycle work, see Rotate Proxy Credentials Safely. Avoid using a generic proxy-route result as proof of target permission or compatibility.
References
- curl official proxy environment-variable documentation↗: scheme-specific variables,
ALL_PROXY,NO_PROXY, CIDR support, and the lowercase-onlyhttp_proxyrule. - curl official manual↗:
--proxy,--noproxy, environment-variable precedence, explicit empty overrides, proxy schemes, and no-proxy matching. - RFC 3875, CGI/1.1↗: CGI request meta-variable conventions that explain the security background for uppercase
HTTP_PROXY.
Treat the commands as diagnostic examples rather than performance evidence. Validate them with your own authorized endpoint and target before drawing conclusions about availability, compatibility, latency, geography, or production behavior.
Alex Vance
Lead Proxy Network Architect
Reviewed by the BytesFlows engineering team. Examples are written for compliant public-web data collection, QA, SEO monitoring, and market research workflows. Results can vary by target site, country, client runtime, and request rate.