Skip to content

Guide

Sending file uploads as Base64 in a JSON API payload

JSON has no native way to carry binary data. Base64 is the workaround — and workarounds have costs.

By Published

JSON’s data model — defined in RFC 8259 — has no native binary type. Every value is either a string, number, boolean, null, object, or array, and strings must be valid Unicode text. A raw file’s bytes can contain sequences that aren’t valid text at all, so there’s no way to drop them into a JSON string directly. Base64 solves that by re-encoding the binary as a restricted alphabet of 64 printable ASCII characters — safe to embed in a JSON string, an XML document, or a URL, at the cost of roughly 33% more bytes than the original file.

What the payload actually looks like

A typical file-upload JSON body wraps the encoded data in a field alongside metadata the server needs to reconstruct the file:

{ "filename": "invoice.pdf", "contentType": "application/pdf", "data": "JVBERi0xLjQK..." }

The server decodes the data field back to raw bytes on receipt — the exact reverse of the encoding step — and writes it to storage or processes it directly. This pattern is common in webhook payloads and API clients that only want to speak JSON, since it avoids the extra content-type negotiation that multipart uploads require.

The tradeoff: size and request limits

ApproachSize overheadBest for
Base64 in JSON~33% largerSmall files, JSON-only clients, webhooks
multipart/form-dataNone (minimal boundary overhead)Large files, standard upload endpoints

Because most API gateways, load balancers, and server frameworks enforce a maximum request body size, the 33% overhead directly eats into how large a file can actually be uploaded. A gateway capped at 10MB effectively caps Base64-in-JSON uploads at around 7.5MB of real file content — worth checking against your provider’s documented limits before assuming a file that’s “under the cap” will actually go through once encoded.

When to skip Base64 entirely

For anything beyond a few megabytes, or any endpoint where request size or upload speed genuinely matters, multipart/form-datais the better tool: it sends the file’s raw bytes with only a small boundary-marker overhead, no 33% tax. This is also what plain HTML <input type="file"> forms use natively via the FormData API. Reach for Base64-in-JSON specifically when the client can only send JSON, the file is small, or the payload needs to stay self-contained as a single JSON object — not as a default for every upload.

Frequently asked questions

Why can't I just put binary data directly in JSON?
JSON's grammar only defines strings, numbers, booleans, null, objects, and arrays — strings must be valid Unicode text. Raw binary bytes can contain byte sequences that aren't valid text at all, so they can't be embedded in a JSON string without first converting them to a text-safe representation, which is exactly what Base64 does.
What's the size cost of Base64-encoding a file for a JSON API?
About 33% larger than the raw file, plus whatever JSON string-escaping adds on top (usually negligible since Base64's alphabet avoids characters that need escaping). A 3MB PDF becomes roughly 4MB of Base64 text inside the JSON body.
When should I use multipart form data instead of Base64 in JSON?
For large files, or any upload where request size matters — multipart/form-data transmits the file as raw bytes with no encoding overhead, and is the standard approach for file upload endpoints (including plain HTML forms). Base64-in-JSON is more common for smaller files, API clients that only speak JSON, or webhook payloads that need to stay self-contained in one JSON object.
Does Base64 in JSON count against request size limits?
Yes, and the 33% overhead makes it count faster. If an API gateway or server caps request bodies at, say, 10MB, a Base64-encoded file has to be under about 7.5MB raw to fit — worth checking before assuming a file 'under the limit' will actually upload successfully once encoded.

Sources & references

Authoritative references cited by this piece. Verified by Buğra Sözeri on the dates shown and re-checked at every deploy.

Related

More guides on this topic

Published September 25, 2026