I was reviewing a pull request last week when I spotted it: a developer had base64-encoded a JWT payload to “hide” the user ID before logging it. The encoding was a one-liner, the decoding was three lines of search results, and the actual user data was completely exposed in the logs. They thought base64 was encryption. It is not.
That confusion is more common than you think. Base64 shows up everywhere in web development — JWTs, data URIs, API payloads, email attachments, SSH keys — and developers regularly misuse it, misread it, or debug it with a janky online tool that uploads their data to some unknown server. That is the problem Base64Lab solves.
What Base64 Actually Is
Base64 is an encoding scheme, not encryption. It converts binary data into a text-safe format using 64 printable ASCII characters (A–Z, a–z, 0–9, +, /). The output is about 33% larger than the input, and anyone can decode it instantly — no key, no password, no secret.
The reason it exists: binary data (images, arbitrary bytes) cannot safely travel through text-only channels like SMTP or early HTTP. Base64 bridges that gap. It makes binary safe for text. That is all it does.
When you see eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 at the start of a JWT, that is just {"alg":"HS256","typ":"JWT"} base64-encoded. No secrets there. The actual signature is at the end — and that part depends on a private key.
Why Most Base64 Tools Are a Privacy Problem
Search “base64 decode online” and the top results are cloud services. You paste your data, it gets sent to their server, decoded server-side, and returned. For casual use that is fine. For anything sensitive — API tokens, JWT payloads, config files, binary certificates — you just handed your data to a third party for no reason.
Developers routinely paste things like:
- JWT tokens containing user IDs, roles, and email addresses
- Base64-encoded database connection strings from environment variables
- Private key material encoded in PEM files
- Internal API payloads during debugging sessions
None of that should leave your machine. Base64Lab runs entirely in your browser — there is no server, no upload, no request leaves your tab. The decode happens in JavaScript on your hardware.
The Three Things I Actually Use It For
1. Decoding JWT Headers on the Spot
JWTs have three parts separated by dots: header, payload, signature. The first two are base64url-encoded (standard base64 with + replaced by - and / replaced by _, no padding). When a JWT comes in malformed or with unexpected claims, I need to see the raw JSON fast.
Paste the payload section into Base64Lab, hit decode, see the JSON. Takes three seconds. The tool handles base64url automatically — you do not have to manually swap characters or add padding.
2. Inspecting Data URIs
A data URI looks like data:image/png;base64,iVBORw0KGgo.... They appear in HTML/CSS, API responses, and canvas exports. If you need to verify what image or file is actually embedded — or extract it — you paste the base64 portion into Base64Lab and preview it directly. For images it renders the preview inline, for other files it offers a download.
This is the kind of thing that saves you from writing a throwaway Python script just to see a file.
3. Encoding Config Fragments for Environment Variables
Some deployment systems expect secrets as base64 to avoid quoting problems. Kubernetes secrets, GitHub Actions, Heroku config vars — the pattern is everywhere. I use Base64Lab to encode a multi-line JSON config or a PEM certificate into a single base64 string before dropping it into a CI environment variable. No Python subprocess, no shell escaping issues.
How the In-Browser Decode Actually Works
The Web Crypto API and the standard atob()/btoa() functions are what make browser-side Base64 reliable. atob() decodes a base64 string to binary, btoa() encodes binary to base64. For file handling, the FileReader API reads a file as a data URL, which includes the base64-encoded contents.
For a binary file, the pipeline looks like this:
// Encoding a file to base64 in the browser
const reader = new FileReader();
reader.onload = (e) => {
// e.target.result is "data:application/octet-stream;base64,AAEC..."
const base64 = e.target.result.split(,)[1];
console.log(base64);
};
reader.readAsDataURL(file);
// Decoding base64 to a Uint8Array (for binary files)
function base64ToBytes(base64) {
const binary = atob(base64);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
return bytes;
}
The limit is memory — your browser tab can hold maybe 500MB comfortably before things get sluggish. Base64Lab supports files up to 50MB, which covers virtually every real debugging scenario.
Base64 vs. Base64URL vs. Base64 with Line Breaks
Three variants trip people up:
- Standard Base64: uses
+and/, padded with=. Common in email (MIME) and most non-URL contexts. - Base64URL: replaces
+with-,/with_, padding optional. Used in JWTs, OAuth tokens, URL-safe contexts. - MIME Base64: standard base64 with a line break every 76 characters. Required by some email standards. Strip the line breaks before decoding if your tool does not handle them.
If atob() throws “InvalidCharacterError”, you almost certainly have base64url input. Replace -→+, _→/, then pad to a multiple of 4 with =.
function base64urlToBase64(str) {
return str
.replace(/-/g, +)
.replace(/_/g, /)
.padEnd(str.length + (4 - str.length % 4) % 4, =);
}
Base64Lab handles all three variants automatically.
What to Actually Use for Encryption
Since we are on the topic: if you need to actually protect data (not just encode it), the Web Crypto API is the right tool. AES-GCM for symmetric encryption, ECDH or RSA-OAEP for key exchange. It runs in the browser, it is fast, and the SubtleCrypto interface is well-documented.
Base64 comes back into the picture when you need to store or transmit the resulting encrypted bytes as text — you encode the ciphertext as base64. That is the correct pattern: encrypt first, encode for transport second.
For verifying file integrity rather than encrypting data, HashForge generates SHA-256 and other hashes in-browser with the same no-upload approach.
The Privacy Angle Is Real
I know “privacy-first” sounds like marketing. But there is a concrete reason it matters here: developers debug in contexts where the data is sensitive. A JWT from your production auth system. A connection string from a real database. A certificate that should never leave your infrastructure.
The habit of pasting that stuff into random web tools is how credentials end up in breach datasets. It happens through carelessness, not malice. A browser-local tool removes the risk entirely because there is nothing to breach — the data never left your machine.
Base64Lab is at base64lab.orthogonal.info. Open it, paste something, it decodes. That is the whole thing. If you are already cautious about what you paste into online tools, it is a drop-in replacement for the ones you are probably using now.
For other privacy-first developer utilities — regex testing, hash generation, image compression — the full list is at orthogonal.info/tools.
If you want free market intelligence in your feed, join Alpha Signal on Telegram — daily signals, no noise.
📧 Get weekly insights on security, trading, and tech. No spam, unsubscribe anytime.
Leave a Reply