Quick verdict: Use -u user:pass for HTTP Basic Authentication on the server you are talking to. Use --proxy-user user:pass for the proxy in front of you. For modern APIs use -H "Authorization: Bearer TOKEN" instead. Never put real passwords in shell history — use a .netrc file or read from stdin with -u user: (no password) which prompts.
curl -u alice:secret123 https://api.example.com/dataThis sends the header Authorization: Basic YWxpY2U6c2VjcmV0MTIz — the base64-encoded "alice:secret123". Note: base64 is encoding, not encryption. Always pair Basic auth with HTTPS or the credentials are visible to anyone on the network.
Empty password: use -u alice: — the trailing colon is required, otherwise cURL prompts.
Empty username: use -u :secret — some APIs use just a token in the password slot (Stripe, Postmark, etc.) where the username is empty.
Special characters: if your password contains a colon, the first colon splits user from password, so escape with --user-special or use -u "user:pass:withcolon" (works correctly because cURL splits on the first colon only).
Putting passwords on the command line is bad practice — they end up in ~/.bash_history, ps aux output, and CI logs. Three cleaner options:
1. Prompt for password:
curl -u alice https://api.example.com/data
Enter host password for user 'alice':2. Read from environment variable:
export API_PASS="secret123"
curl -u "alice:$API_PASS" https://api.example.com/data3. Use .netrc:
# ~/.netrc (chmod 600)
machine api.example.com
login alice
password secret123curl -n https://api.example.com/dataThe -n (or --netrc) flag tells cURL to look up credentials in ~/.netrc matching the hostname. Use --netrc-file PATH for a custom location.
Modern APIs use bearer tokens, not Basic auth. Send via the Authorization header:
curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR..." https://api.github.com/userOr use cURL's shorthand (cURL 7.61+):
curl --oauth2-bearer eyJhbGciOiJIUzI1NiIsInR... https://api.github.com/userThe shorthand is identical to the explicit header but reads cleaner in scripts.
If your cURL request goes through a proxy that requires auth, that is a different field:
curl --proxy http://gw.spyderproxy.com:8000 --proxy-user USER:PASS https://api.example.com/dataOr use the inline syntax:
curl --proxy http://USER:[email protected]:8000 https://api.example.com/dataThe proxy credentials become the Proxy-Authorization header (Basic encoding by default). Server credentials (-u) become Authorization. Both can coexist in the same request:
curl --proxy http://PUSER:[email protected]:8000 -u alice:secret123 https://api.example.com/dataThis auths to both the proxy and the upstream API. SpyderProxy supports auth via username/password as shown, or by IP whitelisting from the dashboard. See proxy authentication methods for the trade-offs.
Beyond Basic, cURL supports several other auth schemes:
| Flag | Auth scheme | Common use |
|---|---|---|
--basic | HTTP Basic (default) | Most APIs, dev tools |
--digest | HTTP Digest | Old enterprise systems |
--ntlm | NTLM | Windows servers, Exchange |
--negotiate | SPNEGO/Kerberos | Active Directory environments |
--anyauth | cURL picks | When server returns WWW-Authenticate |
--anyauth sends an unauthenticated request first, reads the WWW-Authenticate header from the 401 response, and picks the strongest scheme the server supports. Useful when you do not know what the server uses.
API keys come in three common forms:
1. Header:
curl -H "X-API-Key: abc123def" https://api.example.com/data2. Query string:
curl "https://api.example.com/data?api_key=abc123def"3. Basic with key as password:
curl -u "abc123def:" https://api.example.com/dataThe third pattern (key as username, empty password) is what Stripe uses. Quote it carefully — the trailing colon must be inside the quotes.
The Basic auth header is Authorization: Basic BASE64(username:password). Watch this:
$ curl -v -u alice:secret123 https://example.com 2>&1 | grep Auth
> Authorization: Basic YWxpY2U6c2VjcmV0MTIz
$ echo -n "alice:secret123" | base64
YWxpY2U6c2VjcmV0MTIzSame string. If you ever need to construct the header manually:
TOKEN=$(echo -n "alice:secret123" | base64)
curl -H "Authorization: Basic $TOKEN" https://api.example.com/data-v output for the WWW-Authenticate header.--proxy-user or supplied the wrong proxy creds. Different from 401 (which is from the upstream).@, #, or ? when using inline syntax (http://user:pass@host). For -u user:pass, only colons and shell-special chars need quoting.Related: cURL timeout settings, curl vs wget comparison, cURL alternatives in JavaScript.