What HTTP Basic Auth Actually Is
HTTP Basic Authentication is defined in RFC 7617 (June 2015, superseding the older RFC 2617). It is the simplest possible HTTP authentication scheme: concatenate a username and password, Base64-encode the result, and send it in the Authorizationheader on every request. There is no handshake, no challenge-response, no token refresh — the client just attaches credentials to each HTTP call.
The Base64 step is not encryption. It exists only because HTTP headers restrict the character set — colons, newlines, non-ASCII characters, and certain control characters would break the header parser. Base64 produces pure ASCII output using only A-Z a-z 0-9 + / =, which is safe in any HTTP header value.
The Exact Header Format
Authorization: Basic <base64(username ":" password)>
# Example:
# username = "alice"
# password = "secret123"
# combined = "alice:secret123"
# base64("alice:secret123") = "YWxpY2U6c2VjcmV0MTIz"
Authorization: Basic YWxpY2U6c2VjcmV0MTIzThree gotchas most tutorials miss:
- No trailing newline. If you build the token with
echo "user:pass" | base64(without-n), you include a trailing\nin the Base64 input and the server rejects the credentials. Always useecho -norprintf. - Standard Base64, not URL-safe. HTTP headers happily carry
+and/. Do not substitute-/_— that would break strict RFC 7617 parsers. - Keep the padding. The trailing
=characters stay. Stripping them is a JWT convention, not a Basic Auth one.
Building the Header in Every Common Language
# ─── Shell (cURL has a built-in flag) ───
curl -u alice:secret123 https://api.example.com/me
# Equivalent manual version:
TOKEN=$(printf 'alice:secret123' | base64)
curl -H "Authorization: Basic $TOKEN" https://api.example.com/me
# ─── Python ───
import base64
creds = 'alice:secret123'.encode('utf-8')
token = base64.b64encode(creds).decode('ascii')
headers = {'Authorization': f'Basic {token}'}
# ─── Node.js ───
const token = Buffer.from('alice:secret123', 'utf-8').toString('base64');
const headers = { Authorization: 'Basic ' + token };
# ─── Browser fetch ───
const token = btoa('alice:secret123'); // ASCII only
const token = btoa(String.fromCharCode(...new TextEncoder().encode('álice:secret123'))); // UTF-8 safe
# ─── Go ───
import "encoding/base64"
token := base64.StdEncoding.EncodeToString([]byte("alice:secret123"))
req.Header.Set("Authorization", "Basic "+token)
# ─── PHP ───
$token = base64_encode('alice:secret123');
$headers = ['Authorization: Basic ' . $token];
# ─── Ruby ───
require 'base64'
token = Base64.strict_encode64('alice:secret123')
headers['Authorization'] = "Basic #{token}"UTF-8 Usernames and Passwords
RFC 7617 §2.1 updated the original Basic Auth spec to explicitly require UTF-8 encoding of the user-id:password string before Base64. This matters for users with accented characters, CJK scripts, or emoji in their passwords. Most libraries do this correctly by default, but the browser btoa() function does NOT handle UTF-8 — it throws InvalidCharacterError on any character outside the Latin-1 range.
// WRONG — btoa alone cannot handle non-ASCII
btoa('álice:secret'); // throws InvalidCharacterError
// RIGHT — encode to UTF-8 bytes first
const bytes = new TextEncoder().encode('álice:secret');
const token = btoa(String.fromCharCode(...bytes));
// token: "w6FsaWNlOnNlY3JldA=="Postman, HTTPie, and Testing Tools
# Postman
# Authorization tab → Type = "Basic Auth" → fill in Username and Password
# Postman builds the header for you — no manual Base64 needed
# HTTPie
http -a alice:secret123 https://api.example.com/me
# Insomnia
# Auth tab → Basic → Username + Password
# wget
wget --user=alice --password=secret123 https://api.example.com/meSecurity Realities
- Base64 is NOT encryption. Any observer with the Base64 token can decode it to plaintext credentials in milliseconds:
echo YWxpY2U6c2VjcmV0MTIz | base64 -d. - Credentials are sent on EVERY request. Unlike a short-lived JWT, Basic Auth replays the full username and password on each HTTP call. If any single response is logged or cached with the request, credentials are leaked.
- No built-in logout. Browsers cache Basic Auth credentials until the tab is closed. There is no server-side way to invalidate a session.
- Must be used over HTTPS. Basic Auth over plain HTTP is equivalent to sending the password in cleartext — anyone on the network can decode it instantly.
- Rate limit by IP, not account. Because clients send credentials eagerly, typos trigger a flood of 401s. Rate-limit by source IP to avoid locking out the real user.
When to Use Basic Auth vs. Alternatives
- Internal machine-to-machine APIs over HTTPS. Perfect fit. Simple, no token refresh, works everywhere.
- Legacy systems that only support Basic. Many LDAP servers, SMTP servers, and SOAP endpoints only speak Basic Auth. You will need to generate the header.
- User-facing web apps. Prefer session cookies or OAuth / JWT. Basic Auth lacks logout and shows an ugly browser dialog.
- Public APIs. Prefer API keys in headers (e.g.
X-API-Key) or OAuth 2 Bearer tokens — both are easier to rotate.
Common Mistakes
- Trailing newline in the Base64 input.
echoappends\nby default. Useecho -norprintf. - Colon in the username.Forbidden by RFC 7617. If your username is an email, you're fine; if it's a URN like
urn:acct:alice, encode it differently (e.g. percent-encode the colon). - URL-safe Base64. Wrong alphabet. Use standard Base64.
- Stripping the
=padding.That's a JWT convention, not Basic Auth. - Encoding
"Basic username:password"instead of just"username:password".The literal word "Basic" is prepended AFTER Base64, not before.
Key Facts
- Specification:
- RFC 7617 (2015)
- Header name:
- Authorization
- Scheme:
- Basic
- Separator:
- colon (:) between username and password
- Encoding:
- UTF-8 bytes → standard Base64 (padding kept)
- Transport:
- HTTPS required (Base64 is not encryption)
- Response on 401:
- WWW-Authenticate: Basic realm="..."
Related Base64 Tools
- Base64 Encode Online — general-purpose encoder
- Base64 Encode String — cross-language reference
- URL-Safe Base64 — the JWT variant
- Base64 Decode Online — reverse a Basic Auth token
- JWT Debugger — inspect Bearer tokens (Basic's successor)
- Base64 Encode in JavaScript — browser btoa / Node Buffer patterns