spyderproxy

cURL Basic Authentication: Username, Password & Tokens

D

Daniel K.

|
Published date

Sun May 10 2026

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.

HTTP Basic Auth: -u flag

curl -u alice:secret123 https://api.example.com/data

This 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).

Hide Passwords from Shell History

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/data

3. Use .netrc:

# ~/.netrc (chmod 600)
machine api.example.com
  login alice
  password secret123
curl -n https://api.example.com/data

The -n (or --netrc) flag tells cURL to look up credentials in ~/.netrc matching the hostname. Use --netrc-file PATH for a custom location.

Bearer Tokens (OAuth, JWT)

Modern APIs use bearer tokens, not Basic auth. Send via the Authorization header:

curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR..." https://api.github.com/user

Or use cURL's shorthand (cURL 7.61+):

curl --oauth2-bearer eyJhbGciOiJIUzI1NiIsInR... https://api.github.com/user

The shorthand is identical to the explicit header but reads cleaner in scripts.

Proxy Authentication

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/data

Or use the inline syntax:

curl --proxy http://USER:[email protected]:8000      https://api.example.com/data

The 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/data

This 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.

Digest, NTLM, Negotiate

Beyond Basic, cURL supports several other auth schemes:

FlagAuth schemeCommon use
--basicHTTP Basic (default)Most APIs, dev tools
--digestHTTP DigestOld enterprise systems
--ntlmNTLMWindows servers, Exchange
--negotiateSPNEGO/KerberosActive Directory environments
--anyauthcURL picksWhen 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

API keys come in three common forms:

1. Header:

curl -H "X-API-Key: abc123def" https://api.example.com/data

2. Query string:

curl "https://api.example.com/data?api_key=abc123def"

3. Basic with key as password:

curl -u "abc123def:" https://api.example.com/data

The third pattern (key as username, empty password) is what Stripe uses. Quote it carefully — the trailing colon must be inside the quotes.

How Basic Auth Is Actually Encoded

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
YWxpY2U6c2VjcmV0MTIz

Same 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

Common Errors

  • 401 Unauthorized: Wrong credentials, or the server expects a different auth scheme. Check -v output for the WWW-Authenticate header.
  • 407 Proxy Authentication Required: You forgot --proxy-user or supplied the wrong proxy creds. Different from 401 (which is from the upstream).
  • "curl: (67) Login denied": FTP-specific. Not applicable to HTTP.
  • Special characters break: URL-encode the password if it contains @, #, 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.