Base64 File Upload Encoding — A Practical Guide

Web forms and REST APIs can't send raw binary through a JSON body — JSON is text-only. Base64 solves that by turning any file into a plain string, at the cost of extra bytes on the wire. This guide explains when that trade-off makes sense and when it doesn't.

Why files get Base64 encoded at all

JSON, XML, and many database text columns can only store printable characters — they choke on arbitrary binary bytes (null bytes, control characters). Base64 maps any binary data to 64 safe printable ASCII characters, so a PNG, PDF, or ZIP file can travel inside a JSON string field without corruption.

// A file embedded directly in a JSON API request body
{
  "fileName": "invoice.pdf",
  "mimeType": "application/pdf",
  "fileData": "JVBERi0xLjQKJeLjz9MK..." // Base64-encoded PDF bytes
}

Encoding a file to Base64 for upload

In the browser, use the FileReader API to convert a selected file into a Base64 data URI, then strip the prefix before sending just the encoded payload:

function fileToBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => {
      // result looks like: "data:image/png;base64,iVBORw0KG..."
      const base64 = reader.result.split(',')[1];
      resolve(base64);
    };
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

// Usage with a file input
const file = document.querySelector('input[type="file"]').files[0];
const base64Data = await fileToBase64(file);

await fetch('/api/upload', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ fileName: file.name, fileData: base64Data }),
});

Decoding on the server (Node.js)

import fs from 'fs';

app.post('/api/upload', (req, res) => {
  const { fileName, fileData } = req.body;

  const buffer = Buffer.from(fileData, 'base64');
  fs.writeFileSync(`./uploads/${fileName}`, buffer);

  res.json({ ok: true, sizeBytes: buffer.length });
});

The size overhead — why Base64 isn't free

Base64 encodes every 3 bytes of input as 4 characters of output, so encoded data is always about 33% larger than the original. For a 3 MB image, that's roughly 4 MB of actual bytes sent over the network — plus JSON escaping overhead if wrapped in quotes.

  • 10 KB file → ~13.3 KB encoded
  • 1 MB file → ~1.37 MB encoded
  • 10 MB file → ~13.7 MB encoded, plus more CPU time to encode/decode

When to use multipart/form-data instead

For standard file uploads from an HTML form, multipart/form-data sends the raw binary bytes directly with no encoding overhead. It's the right default for large files, bulk uploads, or anywhere bandwidth and server CPU matter.

<form action="/api/upload" method="POST" enctype="multipart/form-data">
  <input type="file" name="document" />
  <button type="submit">Upload</button>
</form>

// Fetch equivalent
const formData = new FormData();
formData.append('document', file);
await fetch('/api/upload', { method: 'POST', body: formData });
// No Base64 conversion, no 33% overhead

Decision guide

  • Use Base64 when the transport is text-only: JSON APIs, GraphQL mutations, XML/SOAP, or embedding small icons as CSS/HTML data URIs.
  • Use multipart/form-data for browser file-upload forms, large attachments, and any case where you control both client and server.
  • For files over a few MB, prefer multipart or direct binary streaming — Base64's overhead and in-memory string handling become expensive.
  • If you must use Base64 for large files, consider chunking the upload rather than encoding the whole file in memory at once.

Frequently Asked Questions

Why do developers Base64 encode files for upload?

Base64 turns binary file data into plain text, which lets you embed a file directly inside a JSON payload, a database text column, or an HTML data URI — formats that cannot natively hold raw binary bytes.

How much bigger does Base64 make a file?

Base64 encoding increases size by approximately 33%, because every 3 bytes of binary input become 4 characters of text output. A 1 MB file becomes roughly 1.37 MB once encoded.

Should I use Base64 or multipart/form-data for file uploads?

Use multipart/form-data for standard file uploads from a browser form — it sends raw binary with no size penalty. Use Base64 only when the transport requires text, such as JSON APIs, GraphQL, or embedding small files inline in HTML or CSS.

Try the Free Base64 Encoder/Decoder

Paste small files or text into our free tool to see the encoded Base64 output instantly — great for testing API payloads before you write the upload code.

Related articles