curl Cheatsheet

Proxies

Use this curl reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

Setting a proxy

-x / --proxy takes [scheme://]host[:port]. With no scheme curl assumes an HTTP proxy, and with no port it assumes 1080, which trips people who expect 80 or 8080.

curl -x http://proxy.corp:3128 https://api.example.com/
curl -x proxy.corp:3128 https://api.example.com/     # same, http:// implied
curl -x socks5h://127.0.0.1:1080 https://api.example.com/
curl -x '' https://api.example.com/                  # ignore proxy env vars
SchemeProxy type
http:// (or none)HTTP proxy, CONNECT for HTTPS targets
https://HTTPS proxy, the hop to the proxy is itself TLS
socks4://SOCKS4, client-side DNS
socks4a://SOCKS4a, proxy-side DNS
socks5://SOCKS5, client-side DNS
socks5h://SOCKS5, proxy-side DNS

socks5h:// is nearly always the one you want, because socks5:// resolves the hostname locally, which leaks your DNS queries and breaks any name that only the proxy can resolve.

Proxy environment variables

curl reads these when no -x is given. The lowercase spellings are the portable ones, and -x overrides all of them.

VariableApplies to
http_proxyhttp:// URLs, lowercase only by design
https_proxy / HTTPS_PROXYhttps:// URLs
all_proxy / ALL_PROXYAny protocol without a specific variable
no_proxy / NO_PROXYComma list of hosts to bypass
export https_proxy=http://proxy.corp:3128
export no_proxy='localhost,127.0.0.1,.internal.example.com'
curl https://api.example.com/
curl --noproxy '' https://api.example.com/   # override no_proxy for one call

curl deliberately ignores an uppercase HTTP_PROXY, because in a CGI context that name comes from a client-supplied Proxy: header. Only http_proxy in lowercase is honored.

Bypassing with --noproxy

--noproxy overrides no_proxy for a single command. Matching is by domain suffix, so local.com matches local.com, local.com:80, and www.local.com, but not www.notlocal.com.

curl --noproxy '.internal.example.com,localhost' https://api.example.com/
curl --noproxy '192.168.0.0/16' http://192.168.4.7/    # CIDR, curl 7.86.0
curl --noproxy '*' https://api.example.com/            # bypass everything
curl --noproxy '' https://api.example.com/             # force the proxy

The only wildcard is a bare *, which disables the proxy for every host. There is no *.example.com glob, a leading dot already means "and subdomains".

Proxy authentication

The proxy has its own credential set, entirely separate from -u, which belongs to the origin server.

FlagPurpose
-U / --proxy-user <u:p>Proxy credentials
--proxy-basic / --proxy-digest / --proxy-ntlm / --proxy-negotiateProxy auth scheme
--proxy-anyauthProbe and pick the strongest the proxy offers
--proxy-header <h>Header sent to the proxy only
-p / --proxytunnelTunnel with CONNECT even for non-HTTPS
--suppress-connect-headersHide the CONNECT response from -i/-v
curl -x proxy.corp:3128 -U 'ada:s3cret' https://api.example.com/
curl -x proxy.corp:3128 -U 'ada:p%40ss' https://api.example.com/
curl -x proxy.corp:3128 -U ada:s3cret -u api:key https://api.example.com/

curl URL-decodes the credentials inside -x and -U, so a literal @ is %40 and a literal : is %3a. That is the escape people miss when a proxy password contains punctuation.

TLS through a proxy

Two separate TLS relationships exist: curl to the proxy (only with an https:// proxy) and curl to the origin through the tunnel. Each has its own flag family, and mixing them up is the classic mistake.

Origin flagProxy equivalent
--cacert--proxy-cacert
--capath--proxy-capath
-E / --cert--proxy-cert
--key--proxy-key
-k / --insecure--proxy-insecure
--tlsv1.2--proxy-tlsv1
--ciphers--proxy-ciphers
curl -x https://proxy.corp:3129 \
     --proxy-cacert /etc/ssl/proxy-ca.pem \
     --cacert /etc/ssl/corp-root.pem \
     https://api.example.com/

A corporate MITM proxy that re-signs certificates means the origin chain is signed by the proxy's CA, so --cacert proxy-ca.pem is the right fix. Reaching for -k hides the problem and turns off verification for the real target too.

Debugging a proxy path

curl -v -x proxy.corp:3128 https://api.example.com/ 2>&1 | head -20
# > CONNECT api.example.com:443 HTTP/1.1
# < HTTP/1.1 200 Connection established

curl -sx proxy.corp:3128 -o /dev/null \
  -w 'proxy=%{http_connect} code=%{http_code} t=%{time_connect}\n' \
  https://api.example.com/

- %{http_connect} is the proxy's CONNECT status. A 407 there means proxy auth, not origin auth. - Exit 7 with a proxy set is a failure reaching the proxy, not the target. - --unix-socket <path> is not a proxy option. It replaces the TCP connection entirely and is how you talk to a local daemon.

curl --unix-socket /var/run/docker.sock http://localhost/v1.45/containers/json