Developer tools · Base64 encoder & decoder
How the HTTP Basic authentication header is built and decoded with Base64
· How it works
base64 security
The Authorization: Basic header is just username:password run through Base64. This post shows how the value is built, how to decode one from a request log, and why the encoding hides nothing.
The 401 that persists although the credentials are right — a header value that decodes to a subtly wrong string
An HTTP API returns 401 Unauthorized and expects an Authorization: Basic header. The value is the scheme word Basic, one space, and a Base64 string. A missing prefix, an encoded prefix, or an unnoticed newline changes what the server receives even when the visible username and password look correct.
Decode that string and it reads username:password (literally colon between two). Bytes username:password are UTF-8 encoded then Base64 encoded, producing header value. If credentials are admin:s3cret, UTF-8 bytes are 0x61 0x64 0x6D 0x69 0x6E 0x3A 0x73 0x33 0x63 0x72 0x65 0x74 (ASCII letters plus colon), Base64 encoding produces YWRtaW46czNjcmV0, and header is Authorization: Basic YWRtaW46czNjcmV0.
The recipe from RFC 7617: 'user:pass', UTF-8, Base64 — the exact steps and the role of the colon
This is complete HTTP Basic authentication scheme defined in RFC 7617. It is simple, standardized, and offers no security by itself: anyone reading header can immediately decode it to read password. This is why HTTPS is mandatory for Basic auth. Encoding is transport requirement, not security feature. Password travels as UTF-8 bytes, same as any other data; Base64 is just notation used in HTTP protocol.
If need to decode Basic header from network log, process is straightforward: strip Basic, Base64 decode remainder, and you have username:password. Colon is delimiter between username and password. RFC 7617 specifies credentials are user-id : password, and first colon is separator. If password contains colon, second colon is just another character in password. The colon is structural because the receiver needs one unambiguous boundary. It searches for the first colon after decoding; everything before it identifies the user and everything after it is the password. A missing colon therefore indicates a malformed credential pair, not a Base64-alphabet problem.
Worked example: encoding admin:s3cret and decoding a header from a log — both directions, including a trailing-newline bug
If username is admin and password is pass:word, credentials are admin:pass:word, which encodes to YWRtaW46cGFzczp3b3Jk. When decode it, must split on first colon only, giving username admin and password pass:word. Splitting on every colon would incorrectly split password. The charset parameter in RFC 7617 states credentials are UTF-8 encoded. This means non-ASCII characters in usernames or passwords are converted to UTF-8 bytes before Base64 encoding.
If username is café (accented e), UTF-8 bytes are 0x63 0x61 0x66 0xC3 0xA9 (four bytes for ASCII letters plus two for accented character), and full credentials café:password have bytes for café, then colon byte 0x3A, then password. Base64 output encodes all bytes faithfully. Decoder must know to interpret decoded bytes as UTF-8 text, not Latin-1.
Passwords containing colons, spaces and non-ASCII — why the first colon splits, and what the charset parameter is for
A worked example: start with admin:s3cret. Convert to UTF-8 bytes: a=0x61, d=0x64, m=0x6D, i=0x69, n=0x6E, :=0x3A, s=0x73, 3=0x33, c=0x63, r=0x72, e=0x65, t=0x74. In decimal: (97, 100, 109, 105, 110, 58, 115, 51, 99, 114, 101, 116). Base64 encode these 12 bytes: group into four groups of three (produce four groups of four Base64 characters).
Encoded value is YWRtaW46czNjcmV0. Authorization header is Authorization: Basic YWRtaW46czNjcmV0. The password side can contain another colon without moving that first boundary. Spaces and non-ASCII text also survive when both peers agree on the text encoding. ToolAcre can verify the UTF-8 bytes it emits, but an older server that expects a different charset remains an interoperability issue outside the Base64 transformation.
Why this is not secure without TLS — decoding shows the password to anyone who sees the header
To decode received header, strip Basic, Base64 decode YWRtaW46czNjcmV0 to get bytes back, interpret as UTF-8 text to get admin:s3cret, split on first colon to extract username and password. A common mistake is trailing newline from echo. If run echo admin:s3cret | base64 in Unix shell, echo adds newline by default, so encode admin:s3cret with newline (13 bytes instead 12).
Base64 output is different: YWRtaW46czNjcmV0Cg== (padding and extra characters). Authorization header with this value will fail because password includes newline character. Fix is use echo -n or pipe through printf or tool that does not append newlines. Base64 encoder & decoder avoids this: encodes exactly what you paste, no hidden newlines. TLS changes the transport threat, not the credential format. Inside a protected connection the header is encrypted with the rest of the request; once software logs or displays it, the Base64 value again exposes the reusable credential to anyone able to decode it. Redaction still matters at every observation point.
Common mistakes — a newline from echo, a missing 'Basic ' prefix, and double-encoding the value
Another error is missing Basic prefix. Authorization header value is not valid Base64 alone; it is scheme name (Basic or Bearer or others) followed by space and then credential. Some systems fail to recognize YWRtaW46czNjcmV0 as credential but succeed with Basic YWRtaW46czNjcmV0. If debugging 401, check whether server is parsing Authorization header correctly.
Scheme is case-insensitive in HTTP standard but many implementations are case-sensitive; check API documentation. Double-encoding is another failure mode. If Base64 encode string that is already Base64 encoded, output is different string. Encoding YWRtaW46czNjcmV0 produces WVdkbWFXNDZjek5qY3JldA== (entirely different). Some systems might accidentally apply encoding twice: once during credential setup and again when constructing header. A newline from a shell command is especially easy to miss because it can be encoded as part of the credential rather than rejected as whitespace around the Base64. The resulting header decodes cleanly to a password with an extra byte, producing a 401 that looks like a server-side authentication failure.
What this does not cover — Digest and Bearer schemes, and browser credential prompts
Decoder expects single layer of Base64, so double-encoding causes mismatch. This is why logging credential values in Base64 form (not plaintext) can be confusing: if someone applies decoding once, they see username and password; if apply twice, they see obfuscation. Digest authentication (RFC 7616) and Bearer authentication (for OAuth tokens) use different schemes, each with different credential formats.
Digest requires server to send nonce, client to compute hash, and header to include hash plus username, not password. Bearer is typically JSON Web Token (JWT), which is Base64url encoded but not prefixed with username. Basic auth is simpler than both but completely insecure without TLS because credentials are readable in header. Digest and Bearer use the same Authorization header field but assign entirely different meaning to their values. Browser credential prompts add user-interface and caching behavior on top of Basic. This article stops at constructing and inspecting the Basic credential payload rather than comparing those authentication systems.
Takeaway: Basic auth is Base64, not protection — how the Base64 encoder & decoder lets you check a header value locally without sending the credential anywhere
If API supports multiple authentication schemes, choose most secure available. Base64 encoder & decoder can help debug Basic auth failure: paste credential string (username and colon and password), and tool produces Base64 value immediately. Compare result to header sending, and mismatch is visible. Conversely, paste header value from network log, strip Basic prefix, decode to see what server saw.
For learning, paste admin:s3cret and observe output, then modify password to see how Base64 changes. Understanding how header built clarifies why decoding requires knowing RFC format and why colon is structural element, not Base64. A local check should use an invented credential, not a live password copied from production. Encode the pair, move the output back into the input panel, and decode it. Matching punctuation and exact trailing characters prove the representation round-trip before the header is sent anywhere.