Creating a Blob from a Base64 String in JavaScript

Converting a Base64 string back into a Blob is one of those tasks that looks trivial until you try to download a PDF and end up with a file that says "this file is corrupted."

The browser gives you the raw Base64 string. You need a Blob. The gap between them is about five lines of code — but those five lines have to be right.

The Core Pattern

The standard approach decodes the Base64 string, creates an ArrayBuffer from the decoded bytes, and wraps it in a Blob:

function base64ToBlob(base64, mimeType = "") {
  // Decode Base64 to binary string
  const byteChars = atob(base64);

  // Create an ArrayBuffer
  const byteNumbers = new ArrayBuffer(byteChars.length);
  const byteArray = new Uint8Array(byteNumbers);

  // Fill the ArrayBuffer with decoded bytes
  for (let i = 0; i < byteChars.length; i++) {
    byteArray[i] = byteChars.charCodeAt(i);
  }

  // Return the Blob
  return new Blob([byteArray], { type: mimeType });
}

Usage:

const blob = base64ToBlob("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==", "image/png");
console.log(blob); // Blob { size: 67, type: "image/png" }

This pattern works for any binary type — images, PDFs, ZIP files, audio, video.

Handling Data URI Strings

If you're starting from a data URI (the format returned by FileReader.readAsDataURL()), strip the prefix before decoding:

function dataUriToBlob(dataUri) {
  // Split on the comma — left side is metadata, right side is the Base64 data
  const parts = dataUri.split(",");
  const mimeMatch = parts[0].match(/:(.*?);/);

  if (!mimeMatch) {
    throw new Error("Invalid data URI format");
  }

  const mimeType = mimeMatch[1];
  const base64 = parts[1];
  const byteChars = atob(base64);
  const byteArray = new Uint8Array(byteChars.length);

  for (let i = 0; i < byteChars.length; i++) {
    byteArray[i] = byteChars.charCodeAt(i);
  }

  return new Blob([byteArray], { type: mimeType });
}

This handles data URIs like data:image/png;base64,iVBORw0KGgo... and extracts both the Base64 data and the MIME type from the prefix.

Creating a Downloadable File from Base64 (Blob → File → URL)

The most common use case for this conversion is generating a downloadable file:

function downloadBase64AsFile(base64, filename, mimeType) {
  const blob = base64ToBlob(base64, mimeType);
  const url = URL.createObjectURL(blob);

  const link = document.createElement("a");
  link.href = url;
  link.download = filename;
  document.body.appendChild(link);
  link.click();

  // Clean up
  document.body.removeChild(link);
  URL.revokeObjectURL(url);
}

// Usage — user clicks a download button
document.getElementById("download-btn").addEventListener("click", () => {
  const base64 = getBase64FromApi(); // "JVBERi0xLjQKJcfs..."
  downloadBase64AsFile(base64, "report.pdf", "application/pdf");
});

URL.createObjectURL() generates a blob URL (blob:https://yoursite.com/uuid) that the browser treats like a regular file URL. The download attribute on the anchor tag triggers the download dialog.

Converting Blob to File

Sometimes you need a File object (which extends Blob with name and lastModified properties):

function base64ToFile(base64, filename, mimeType) {
  const blob = base64ToBlob(base64, mimeType);
  return new File([blob], filename, { type: mimeType, lastModified: Date.now() });
}

// Useful for re-uploading or processing
const file = base64ToFile("iVBORw0KGgo...", "avatar.jpg", "image/jpeg");
const formData = new FormData();
formData.append("avatar", file); // Works with FormData for upload

Displaying a Base64 Image in an <img> Tag

If your goal is to display the Base64 content, you don't need a Blob at all — use the data URI directly:

const base64 = "iVBORw0KGgo...";
document.getElementById("preview").src = `data:image/png;base64,${base64}`;

The browser decodes the Base64 string internally. Only convert to a Blob when you need to:

  • Trigger a file download
  • Upload via FormData
  • Pass to APIs that expect Blob or File (like the MediaStream Recording API)
  • Slice or manipulate the binary data

Performance: Large Base64 Strings

For large payloads (multi-MB Base64 strings), the naive loop has performance implications:

// Large payload — 10 MB Base64 string
const base64 = "..."; // millions of characters

// This loop blocks the main thread for tens to hundreds of milliseconds
for (let i = 0; i < byteChars.length; i++) {
  byteArray[i] = byteChars.charCodeAt(i);
}

Optimization with Uint8Array.from

function base64ToBlobOptimized(base64, mimeType = "") {
  const byteChars = atob(base64);
  const byteArray = Uint8Array.from(byteChars, c => c.charCodeAt(0));
  return new Blob([byteArray], { type: mimeType });
}

Uint8Array.from() with a mapping function is typically faster than a manual for loop in modern JavaScript engines.

Using a Web Worker for Large Payloads

For truly large payloads (50 MB+), move the conversion to a Web Worker to avoid blocking the UI:

// main.js
const worker = new Worker("base64-worker.js");
worker.postMessage({ base64, mimeType: "application/pdf" });
worker.onmessage = (event) => {
  const blob = event.data;
  // Use the blob...
};

// base64-worker.js
self.onmessage = (event) => {
  const { base64, mimeType } = event.data;
  const byteChars = atob(base64);
  const byteArray = new Uint8Array(byteChars.length);

  for (let i = 0; i < byteChars.length; i++) {
    byteArray[i] = byteChars.charCodeAt(i);
  }

  const blob = new Blob([byteArray], { type: mimeType });
  self.postMessage(blob);
};

Common Pitfalls

Pitfall 1: Not Stripping the Data URI Prefix

// WRONG: atob throws on the "data:image/png;base64," prefix
atob("data:image/png;base64,iVBORw0KGgo...");

// RIGHT: split on comma first
const base64 = dataUri.split(",")[1];
atob(base64);

Pitfall 2: Wrong MIME Type

If the MIME type doesn't match the actual content, the browser might refuse to open the downloaded file:

// WRONG: MIME type says PDF but content is actually a PNG
downloadBase64AsFile(pngBase64, "image.png", "application/pdf");

// The downloaded file will likely fail to open

Always detect the MIME type from the data URI prefix or the API response, not from assumptions.

Pitfall 3: Forgetting to Revoke the Blob URL

Every URL.createObjectURL() call consumes memory until URL.revokeObjectURL() is called. In single-file downloads this is usually fine, but in a dashboard with many previews, leaked blob URLs accumulate:

// Good: revoke after use
function createAndUseBlobUrl(blob) {
  const url = URL.createObjectURL(blob);
  // ... use the URL ...
  URL.revokeObjectURL(url); // Free the memory
}

FAQ

How do I convert a Base64 string to a downloadable file?

Decode the Base64 to a Blob using atob() + Uint8Array, create an object URL with URL.createObjectURL(blob), then use an <a> tag with the download attribute to trigger the browser's save dialog.

What's the difference between Blob and File for Base64 conversion?

A File extends Blob with name and lastModified properties. Use Blob for in-memory binary data. Use File when you need to upload the data via FormData or present a filename to the user.

Can I convert Base64 to Blob in Node.js?

In Node.js, use Buffer.from(base64, "base64") to get a Buffer, then create a Blob with new Blob([buffer]) (available since Node.js 18). Or skip the Blob entirely and write the Buffer directly to a file.

Why does my converted file show as corrupt?

The most likely causes: the Base64 string includes a data URI prefix that wasn't stripped, the MIME type is incorrect, or the Base64 string was truncated during transport. Validate the Base64 first using the Base64 Encoder & Decoder tool.

Does URL.createObjectURL work for all file types?

Yes. The browser serves any Blob, regardless of type, over the generated blob URL. However, the browser must be able to handle the MIME type — downloading a .exe or .dll might be blocked by security policies.


If you need to convert Base64 strings to downloadable files frequently, the Base64 Encoder & Decoder tool handles the decode-and-download workflow. For Base64-encoded images that you want to display inline, see How to Display Base64 Images in HTML for a broader discussion of data URIs.