Base64 in JSON APIs: When Files Have to Live in a Text Field

Riley Chen · Aug 9, 2026 · 5 min read

I maintain a REST API that accepts scanned documents. The spec the client's team handed us said: "send the PDF as base64 in a JSON field." A 5MB PDF became a 6.7MB string, and requests were timing out. We changed it to multipart upload and cut payload size by a third — but for small files, base64-in-JSON is still the right call, and knowing exactly when saves everyone an argument.

Why JSON forces base64 in the first place

JSON is a text format. It has no native binary type — you can't put raw bytes inside a JSON document without corrupting the encoding. Base64 is the standard escape hatch: it turns bytes into safe ASCII that JSON can carry without breaking. That's why you see "avatar": "data:image/png;base64,…" and "signature": "iVBOR…" in so many payloads.

// JSON can't hold a PNG. It can hold this:
{ "receipt": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCA…" }

The two gotchas that bite in production

1. Size. Base64 inflates by 33%, and unlike multipart upload, the whole string sits in memory as JSON. For anything over ~1MB, prefer multipart/form-data. Under that, base64 is fine and simpler.
2. URL-safety. Plain base64 contains + and /. In a URL or some strict JSON parsers those get mangled. If the string is destined for a URL parameter or a browser fetch with query strings, use base64url (which swaps in - and _) or URL-encode the payload.

What I actually do in my API code

For file fields in JSON, I keep a cap: if the decoded size would exceed ~1MB, the endpoint rejects it and tells the caller to use multipart. And when I need to inspect or regenerate a base64 file during development, I paste it into file-to-base64 or base64-to-file — encode a local file to test, or decode a response to check what the API really received. Both run in the browser, so I'm never piping a client's document through some third-party server.

The 33% overhead and the base64url variant are both standard enough that section 5 of RFC 4648 is worth a skim before you design the field.

Riley Chen Written by Riley Chen — Full-Stack Developer. More about me →