Skip to content
Back to Blog
By JSONConvert Team··7 min read

JSON to Base64: A Practical Guide

You need to stuff a JSON payload into a URL, a cookie, or an HTML data attribute, and the quotes, braces, and ampersands keep breaking things. Base64 fixes this by turning any JSON into a plain ASCII string that survives transport. The basic idea is simple, but UTF-8 handling, URL-safe variants, and a sneaky size penalty trip up most developers the first time.

Why Base64 Encode JSON at All

JSON is already text, so the encoding question is fair. The reason is that plenty of transport channels are hostile to raw JSON characters:

  • URLs choke on &, =, spaces, and quotes in query parameters
  • HTTP headers cannot contain newlines or many punctuation characters
  • Cookies have a restricted character set
  • Data URIs need a compact, inline-safe blob
  • Embedding JSON inside another format (XML, CSV, a shell command) invites escaping nightmares
Base64 maps arbitrary bytes onto a 64-character alphabet (A-Z, a-z, 0-9, +, /) with = for padding. The output is plain ASCII that passes through almost anything untouched.

One thing to be clear about before you ship it: Base64 is encoding, not encryption. Anyone can decode it in one line. Never use it to hide passwords, tokens, or anything you would not paste into a public chat.

Encoding JSON in the Browser

The browser gives you btoa and atob, but they have a sharp edge: they only handle Latin-1 (single-byte) characters. For ASCII-only JSON they work fine:

The moment your JSON contains an emoji, an accented character, or anything outside Latin-1, btoa throws InvalidCharacterError. The fix is to convert the string to UTF-8 bytes first with TextEncoder:

This round-trips any valid JSON, including {"city":"São Paulo"}, which naive btoa would reject.

Node.js: Just Use Buffer

On the server, skip btoa entirely. Buffer handles UTF-8 natively and is less error-prone:

No alphabet quirks, no manual byte juggling. If you are writing isomorphic code that runs in both environments, branch on typeof Buffer or pull in a small polyfill rather than fighting btoa.

Standard vs URL-Safe Base64

Standard Base64 uses +, /, and =. All three are problematic in URLs: + decodes to a space, / looks like a path separator, and = is a query delimiter. URL-safe Base64 (RFC 4648 §5, often called base64url) swaps the troublesome characters and drops padding.

FeatureStandard Base64URL-Safe (base64url)
62nd char+-
63rd char/_
Padding= requiredusually stripped
Safe in URLsNoYes
Used byemail, data URIsJWT, query params
Converting standard output to URL-safe is three replacements:

This is exactly the scheme JWT uses. Each segment of a token is base64url-encoded JSON, which is why you can paste any token into the JWT decoder and read the header and payload back as plain objects. To re-add padding when decoding, append = until the length is a multiple of four.

The 33% Size Penalty

Base64 is not free. It encodes every 3 bytes of input as 4 output characters, so the result is roughly 33% larger than the original. For a small config object that is nothing, but for a 2 MB payload it matters.

Original JSONBase64 sizeOverhead
100 bytes~136 bytes+36%
1 KB~1.37 KB+37%
1 MB~1.33 MB+33%
The single best thing you can do is minify the JSON before encoding. Stripping whitespace and indentation often cuts the source by 20% or more, which carries straight through to a smaller Base64 string. Run your payload through the JSON minifier first, then encode the compact result with the Base64 encoder.

Inlining JSON as a Data URI

A data URI lets you embed an entire JSON file inline, no separate request needed. This is handy for download links and self-contained config:

The browser decodes the blob and hands the user a real config.json. For larger files this beats round-tripping to a server, though remember the 33% inflation counts against any size budget you care about.

Common Mistakes

A few bugs show up again and again:

  • Forgetting UTF-8. Using btoa on JSON with non-Latin-1 characters throws or silently corrupts data. Always encode to UTF-8 bytes first.
  • Mixing alphabets. Encoding with standard Base64 and decoding with a URL-safe parser (or the reverse) produces garbage. Pick one and stay consistent end to end.
  • Double-encoding. If your JSON is already an escaped string, you may be encoding the escaped form rather than the real object. Clean it up with the escape/unescape tool before encoding so you are not preserving stray backslashes.
  • Treating it as security. Base64 hides nothing. If the payload is sensitive, encrypt it, then Base64 the ciphertext.
The reliable workflow is the same every time: minify the JSON, decide standard or URL-safe based on where the string is going, encode the UTF-8 bytes, and decode with a matching parser. Get those four steps right and Base64 stops being a source of mystery bugs.

Related Tools