
If you work with modern web applications, sooner or later you'll need to handle data that isn't simply a JavaScript string or JSON object.
You may need to:
- Preview an uploaded image before sending it to the server.
- Generate a CSV file directly in the browser.
- Download a PDF returned by an API.
- Convert generated data into a file.
- Upload binary data using
fetch(). - Display an image or PDF without saving it first.
- Process audio or video data.
This is where the Blob API becomes extremely useful.
In this article, we'll go beyond the basic definition of Blob.
We'll understand how Blob works, how it relates to File, ArrayBuffer, and typed arrays, and we'll build a complete practical example involving:
Selecting an image → converting it to a Blob → previewing it → uploading it → receiving a Blob from an API → downloading it.
Table of Contents
- What Is a Blob?
- Why Do We Need Blob?
- Creating a Blob
- Blob Parts
- The MIME Type
- Blob Properties
- Reading Blob Data
- Blob.text()
- Blob.arrayBuffer()
- Blob.stream()
- Blob.slice()
- Blob and Object URLs
- Previewing an Image
- Downloading a Blob
- Blob vs File
- Creating a File from a Blob
- Uploading a Blob
- Receiving a Blob from an API
- Complete Practical Example
- Blob vs ArrayBuffer vs Uint8Array
- Blob Streams
- Memory Management
- Common Mistakes
- When Should You Use Blob?
- Final Thoughts
What Is a Blob?
Blob stands for:
Binary Large Object
A Blob represents immutable raw binary data.
That data could represent:
- an image
- a PDF
- a video
- an audio file
- a CSV file
- plain text
- JSON
- arbitrary binary data
For example:
const blob = new Blob( ["Hello, world!"], { type: "text/plain" } ); We have created a Blob containing:
Hello, world! and told the browser:
This data is text/plain. We can inspect it:
console.log(blob.size); console.log(blob.type); The result will be approximately:
13 text/plain Why approximately?
Because size represents the number of bytes, not necessarily the number of JavaScript characters.
For ASCII text such as "Hello, world!", the number happens to match.
For Unicode text, it can be different:
const blob = new Blob( ["Hello 👋"], { type: "text/plain" } ); console.log(blob.size); The browser is measuring the encoded binary representation.
Why Do We Need Blob?
JavaScript applications frequently communicate using JSON:
fetch("/api/users") .then(response => response.json()) .then(data => { console.log(data); }); But not everything is JSON.
Imagine your backend returns:
report.pdf or:
profile-image.jpg or:
invoice.xlsx The browser needs a representation for that binary content.
That's where Blob becomes useful.
A simplified flow looks like this:
flowchart LR A[Server] --> B[Binary Data] B --> C[Blob] C --> D[Preview] C --> E[Download] C --> F[Upload] C --> G[Convert to File] Blob is therefore especially useful at the boundary between:
Web APIs and binary data
Creating a Blob
The Blob constructor has the following general structure:
new Blob(blobParts, options) For example:
const blob = new Blob( ["Hello Blob!"], { type: "text/plain" } ); Let's inspect it:
console.log(blob); You can also inspect:
console.log(blob.size); console.log(blob.type); Blob Parts
The first argument is an array of parts.
Those parts can contain different types of data.
For example:
const blob = new Blob([ "Hello ", "world!" ]); The resulting Blob contains:
Hello world! You can also combine multiple strings:
const blob = new Blob([ "Hello\n", "This is a Blob\n", "Created in JavaScript." ], { type: "text/plain" }); Blob Can Contain Other Blobs
You can also combine existing Blobs:
const first = new Blob( ["Hello "], { type: "text/plain" } ); const second = new Blob( ["world!"], { type: "text/plain" } ); const combined = new Blob([ first, second ], { type: "text/plain" }); Now:
console.log(await combined.text()); Result:
Hello world! The MIME Type
The type property represents the Blob's MIME type.
For example:
const blob = new Blob( ["Hello"], { type: "text/plain" } ); Then:
console.log(blob.type); returns:
text/plain For an image:
const imageBlob = new Blob( [imageData], { type: "image/png" } ); For a PDF:
const pdfBlob = new Blob( [pdfData], { type: "application/pdf" } ); For JSON:
const jsonBlob = new Blob( [JSON.stringify({ name: "Abanoub" })], { type: "application/json" } ); Common MIME types include:
| Content | MIME Type |
|---|---|
| Plain text | text/plain |
| HTML | text/html |
| JSON | application/json |
application/pdf | |
| PNG | image/png |
| JPEG | image/jpeg |
| GIF | image/gif |
| WebP | image/webp |
| CSV | text/csv |
| ZIP | application/zip |
| MP3 | audio/mpeg |
| MP4 | video/mp4 |
The MIME type doesn't magically transform the data.
It is metadata describing what the data represents.
Blob Properties
A Blob mainly exposes two important properties.
size
size returns the size of the Blob in bytes.
const blob = new Blob( ["Hello"] ); console.log(blob.size); Result:
5 type
type returns the MIME type.
const blob = new Blob( ["Hello"], { type: "text/plain" } ); console.log(blob.type); Result:
text/plain Reading Blob Data
Creating a Blob is only part of the story.
Eventually, you usually need to consume the data.
The most important methods are:
blob.text() blob.arrayBuffer() blob.stream() Blob.text()
Use text() when the Blob contains textual data.
Example:
const blob = new Blob( ["Hello from Blob!"], { type: "text/plain" } ); const text = await blob.text(); console.log(text); Output:
Hello from Blob! Because text() returns a Promise, you can use:
blob.text().then(text => { console.log(text); }); Or preferably:
const text = await blob.text(); Reading JSON from a Blob
Suppose you have:
const data = { name: "Abanoub", role: "Frontend Developer" }; const blob = new Blob( [JSON.stringify(data)], { type: "application/json" } ); You can read it:
const text = await blob.text(); const parsed = JSON.parse(text); console.log(parsed.name); console.log(parsed.role); Output:
Abanoub Frontend Developer Blob.arrayBuffer()
If you need the actual binary representation, use:
blob.arrayBuffer() Example:
const blob = new Blob( ["Hello"], { type: "text/plain" } ); const buffer = await blob.arrayBuffer(); console.log(buffer); You get an:
ArrayBuffer This becomes particularly useful when working with:
- binary protocols
- cryptography
- Web APIs
- Web Audio
- WebSockets
- binary file formats
- typed arrays
Blob → ArrayBuffer → Uint8Array
A common pattern is:
const buffer = await blob.arrayBuffer(); const bytes = new Uint8Array(buffer); console.log(bytes); For "Hello" you'll see byte values similar to:
[72, 101, 108, 108, 111] The relationship is:
flowchart LR A[Blob] -->|arrayBuffer| B[ArrayBuffer] B --> C[Uint8Array] C --> D[Individual Bytes] Blob.stream()
A Blob can also expose its data as a ReadableStream.
const blob = new Blob( ["Hello from Blob"], { type: "text/plain" } ); const stream = blob.stream(); console.log(stream); This becomes useful when dealing with streaming APIs and large amounts of data.
We'll return to this later.
Blob.slice()
slice() creates a new Blob containing a portion of the original Blob.
Example:
const blob = new Blob( ["Hello World"], { type: "text/plain" } ); const part = blob.slice(0, 5); console.log(await part.text()); Result:
Hello The syntax is:
blob.slice(start, end, contentType) For example:
const part = blob.slice( 0, 5, "text/plain" ); This is useful when you need to work with only a portion of binary data.
Blob and Object URLs
One of the most useful concepts associated with Blob is:
URL.createObjectURL() Suppose you have:
const blob = new Blob( ["Hello"], { type: "text/plain" } ); You can create a temporary URL:
const url = URL.createObjectURL(blob); console.log(url); You'll get something similar to:
blob:https://example.com/550e8400-e29b-41d4-a716-446655440000 This URL doesn't represent a file on your server.
It represents the Blob in the browser.
Think of It Like This
flowchart LR A[Blob in Memory] --> B[URL.createObjectURL] B --> C[blob:// URL] C --> D[img] C --> E[a] C --> F[iframe] C --> G[video] This is extremely useful.
Previewing an Image
Let's say the user selects an image.
HTML:
<input type="file" id="imageInput" accept="image/*" /> <img id="preview" width="300" /> JavaScript:
const input = document.getElementById("imageInput"); const preview = document.getElementById("preview"); input.addEventListener("change", () => { const file = input.files[0]; if (!file) { return; } const url = URL.createObjectURL(file); preview.src = url; }); Notice something important:
File is already a kind of Blob.
So we don't need to manually convert the selected file into another Blob just to preview it.
Blob URLs Are Temporary
An object URL consumes browser resources.
When you're finished with it, release it:
URL.revokeObjectURL(url); For example:
const url = URL.createObjectURL(file); preview.src = url; preview.onload = () => { URL.revokeObjectURL(url); }; This becomes important when you're creating many object URLs.
Downloading a Blob
One of the most common Blob use cases is generating a file dynamically.
Let's generate a text file.
const content = ` Name: Abanoub Role: Frontend Developer `; const blob = new Blob( [content], { type: "text/plain" } ); Create an object URL:
const url = URL.createObjectURL(blob); Create a link:
const link = document.createElement("a"); link.href = url; link.download = "profile.txt"; link.click(); Finally:
URL.revokeObjectURL(url); Complete example:
function downloadTextFile() { const content = ` Name: Abanoub Role: Frontend Developer `; const blob = new Blob( [content], { type: "text/plain" } ); const url = URL.createObjectURL(blob); const link = document.createElement("a"); link.href = url; link.download = "profile.txt"; link.click(); URL.revokeObjectURL(url); } This creates a real downloadable file without sending anything to a server.
Generating a CSV File
Blob becomes particularly useful for exporting data.
Imagine:
const users = [ { name: "Abanoub", email: "abanoub@example.com" }, { name: "John", email: "john@example.com" } ]; We can generate CSV:
const csv = [ "name,email", ...users.map(user => `${user.name},${user.email}` ) ].join("\n"); Then:
const blob = new Blob( [csv], { type: "text/csv;charset=utf-8" } ); Create the download:
const url = URL.createObjectURL(blob); const link = document.createElement("a"); link.href = url; link.download = "users.csv"; link.click(); URL.revokeObjectURL(url); The browser will download:
users.csv Blob vs File
This is one of the most important distinctions.
A File is essentially a specialized kind of Blob.
Conceptually:
Blob ↑ | File A Blob primarily represents binary data.
A File represents binary data plus file-oriented metadata, such as:
- filename
- last modified timestamp
For example:
const file = new File( ["Hello"], "hello.txt", { type: "text/plain" } ); We can inspect:
console.log(file.name); console.log(file.size); console.log(file.type); console.log(file.lastModified); File Is a Blob
You can check:
const file = new File( ["Hello"], "hello.txt", { type: "text/plain" } ); console.log(file instanceof Blob); Result:
true That's why APIs that accept Blob often also accept File.
For example:
function processBlob(blob) Source:https://dev.to/abanoubkerols/blob-in-javascript-a-practical-deep-dive-with-real-world-examples-3b6p Related posts
More than a Manipulator: Planning Propellant-Free Attitude Maneuvers for Free-Floating Spacecraft
MiniMax H3 Acceleration in ComfyUI: Eleven Graphs Across Model Tier, LoRA, Attention and Cache
Goodbye :nth-child! How Modern CSS sibling-index() Works Under the Hood
Fluid sizes with CSS clamp(): practical examples you can copy
Next.js robots.txt: Why You Shouldn't Block /_next/
