Blob stands for Binary Large Object, an immutable browser object that holds a sequence of raw bytes together with a MIME type. It is defined by the W3C File API specification, and File inherits from it. You meet it when you build a download, upload a file, read a fetch response with blob(), or create a URL for in-memory data. A Blob is read-only: once created, its bytes never change.
The constructor takes an array of parts and an optional options object: new Blob(parts, { type, endings }). Each part can be a string, an ArrayBuffer, a typed array or another Blob. Strings are encoded as UTF-8, and the parts are joined in order.
Two read-only properties describe it. size is the byte count, not the character count. type is the media type as a lowercase string, or an empty string if unknown. If you pass a type containing characters outside printable ASCII, it becomes an empty string. The endings option accepts "transparent" (default) or "native" to convert line endings in string parts.
Reading a Blob is asynchronous. The promise methods are text(), arrayBuffer(), bytes() and stream(). The text() method always decodes as UTF-8. The older FileReader can pick another encoding.
slice(start, end, contentType) returns a new Blob covering bytes from start up to but not including end. Negative numbers count from the end, as with arrays. The new Blob has no connection to the original beyond its bytes, and its type is the third argument, or empty if omitted.
(async () => {
const b = new Blob(['héllo ', new Uint8Array([119, 111, 114, 108, 100])], { type: 'Text/Plain' });
console.log(b.size, b.type, b instanceof Blob);
const s = b.slice(0, 6, 'text/x-part');
console.log(s.size, s.type, await s.text());
console.log(await b.slice(-5).text(), (await b.slice(1,3).bytes()));
console.log(new Blob([]).size, new Blob(['x'], {type:'é'}).type === '');
console.log(Object.prototype.toString.call(b), JSON.stringify({ b }));
})();
Output from Node 22.22.0:
12 text/plain true
6 text/x-part héllo
world Uint8Array(2) [ 195, 169 ]
0 true
[object Blob] {"b":{}}
The string "héllo " is 6 characters but 7 bytes, because é takes 2 bytes in UTF-8, which is why size is 12.
Call URL.createObjectURL(blob), which returns a string starting with blob:, put it in an anchor with a download attribute, click it, then call URL.revokeObjectURL(url). The object URL keeps the Blob alive in memory until you revoke it or the document unloads, so always revoke it.