In the browser, a WebSocket receives binary messages and your handler finds that event.data is a Blob. What does the socket's binaryType property control, which values does it accept, and when should you set it?
answer
- two legal values, one is the default
- text messages ignore this property entirely
- Blob is a handle, not bytes
- reading a Blob is asynchronous
- set it right after the constructor
basics
~20 sbinaryType chooses how a browser WebSocket hands you binary messages: 'blob' (the default) or 'arraybuffer'. Set it to 'arraybuffer' immediately after constructing the socket when you need to read bytes synchronously instead of doing an asynchronous Blob read.
solid answer
~50 s`socket.binaryType` only affects **binary** messages; a text message always arrives as a string no matter what it is set to. The default is `'blob'`, which gives you a `Blob` — an opaque, possibly disk-backed handle whose bytes you can only get asynchronously via `blob.arrayBuffer()` or `blob.text()`. Setting `socket.binaryType = 'arraybuffer'` instead delivers an `ArrayBuffer` that is already fully in memory, so the `message` handler can wrap it in a `DataView` or a typed array and parse fields synchronously. Choose `'arraybuffer'` for anything you actually decode — length-prefixed frames, protobuf, a binary tick feed. Keep `'blob'` for large payloads you never inspect, such as an image you pass straight to `URL.createObjectURL` or write to storage. Set it right after constructing the socket: it applies to messages received after the change, so flipping it mid-stream makes `event.data`'s type unpredictable downstream.
code
javascript · 15 linesconst socket = new WebSocket('wss://example.com/stream');
socket.binaryType = 'arraybuffer'; // set before any message can arrive
socket.addEventListener('message', (event) => {
if (typeof event.data === 'string') {
console.log('text message:', event.data);
return;
}
// Binary message: parse a 1-byte tag and a big-endian 4-byte length, synchronously
const view = new DataView(event.data);
const tag = view.getUint8(0);
const length = view.getUint32(1, false);
const body = new Uint8Array(event.data, 5, length);
console.log('binary message', { tag, length, bytes: body.byteLength });
});go deeper
Know that a WebSocket message can arrive as a string, a Blob, or an ArrayBuffer, and that binaryType is the property deciding between the last two.
Explain that 'blob' is the default, that a Blob is an asynchronously-read handle while an ArrayBuffer is resident bytes you can view with DataView, and that text messages are unaffected.
Justify the choice from the protocol: eager buffers for anything you parse, because an awaited Blob read reorders handling relative to later messages, and blobs for large payloads you pass straight through untouched.
Own the message-format decision itself — whether a binary framing earns its debugging cost over JSON, and what that implies for versioning, tooling and the observability of your realtime traffic.
## What binaryType actually decides A WebSocket carries two kinds of message: text and binary. The browser has no choice about text — a text message always surfaces as a JavaScript string in `event.data`. For binary messages it needs to know which JavaScript representation you want, and `socket.binaryType` is how you tell it. There are exactly two legal values: ```js socket.binaryType = 'blob'; // default socket.binaryType = 'arraybuffer'; ``` Assigning anything else is ignored by conforming implementations rather than throwing, so a typo like `'ArrayBuffer'` silently leaves you on the default — worth knowing when a handler keeps receiving `Blob`s you thought you had turned off. Because `event.data` can be one of three types depending on the message and the setting, defensive handlers usually branch: ```js socket.addEventListener('message', (event) => { if (typeof event.data === 'string') handleText(event.data); else if (event.data instanceof ArrayBuffer) handleBytes(new DataView(event.data)); else handleBlob(event.data); // a Blob }); ``` ## Blob versus ArrayBuffer as a data type A `Blob` is a *handle* to immutable bytes. Crucially, the bytes need not be in the JavaScript heap at all — the browser is free to keep them in its own storage or spill them to disk — and there is no synchronous way to read them. You get at the contents through asynchronous methods (`blob.arrayBuffer()`, `blob.text()`, `blob.stream()`), each of which returns a promise, or you hand the whole `Blob` to something that consumes blobs directly, like `URL.createObjectURL(blob)` for an `<img>` or a `<video>`. An `ArrayBuffer` is the opposite: a fixed-length block of raw bytes that is already resident and immediately addressable. You never read an `ArrayBuffer` directly; you place a view over it — `new Uint8Array(buffer)`, `new DataView(buffer)` — and read fields at offsets, choosing endianness explicitly with `DataView` methods such as `getUint32(offset, littleEndian)`. That difference decides the choice. If the message *is* the payload — an image, an audio chunk, a file you are going to hand off untouched — `'blob'` avoids materialising bytes you were never going to look at. If you have to parse a header to know what the message even is, `'blob'` forces every message through an extra asynchronous hop, which both adds latency and reorders your handling relative to the messages that follow, because the awaited continuation runs after later `message` events have already been dispatched. That reordering hazard is the real argument for `'arraybuffer'` in a protocol where message order matters. ## Timing: set it before messages arrive `binaryType` is a plain mutable property, and the value in effect at delivery time is the one that governs a given message. Changing it mid-stream is legal but means your handler will see `Blob`s for early messages and `ArrayBuffer`s for later ones, with no marker between them. The safe habit is one line immediately after construction, before the connection can possibly open: ```js const socket = new WebSocket('wss://example.com/stream'); socket.binaryType = 'arraybuffer'; ``` Since construction and the `open` event are separated by at least one turn of the event loop, this always wins the race. ## The sending side is separate `binaryType` governs only what you receive. What you *send* is determined by the argument you pass: `send()` accepts a string (sent as a text message) or an `ArrayBuffer`, a typed array or `DataView`, or a `Blob` (all sent as binary). So a socket can perfectly well send `Blob`s while receiving `ArrayBuffer`s. In every case `bufferedAmount` grows by the byte length of what you queued, which is why a string of multi-byte characters adds more bytes than its `.length` suggests — the count is UTF-8 bytes, not code units. ## Interview framing The question is rarely asked as trivia about two string literals. What an interviewer is checking is whether you understand that a `Blob` is a lazily-read handle rather than a byte array, that the default is the lazy one, and that binary-protocol code wants the eager one. A candidate who says "I set arraybuffer so I can `DataView` the header synchronously in the message handler and keep message ordering intact" has answered the real question.
- Why can reading Blob messages asynchronously reorder your handling of a message stream?`blob.arrayBuffer()` returns a promise, so the code that inspects message N resumes in a later job — by which time `message` events for N+1 and N+2 may already have been dispatched and queued their own reads. Unless you serialise the continuations yourself, processing order stops matching arrival order. `'arraybuffer'` parses inline and avoids the problem.
- Does binaryType affect what you can pass to send()?No. `binaryType` is receive-only. `send()` accepts a string, an `ArrayBuffer`, an `ArrayBufferView` such as a `Uint8Array` or `DataView`, or a `Blob`, and picks text or binary framing from the argument type. A socket can send `Blob`s and receive `ArrayBuffer`s at the same time.
- When is leaving binaryType at its default genuinely the better choice?When the payload is large and opaque to you — an image, a media segment, a file transfer. A `Blob` lets the browser keep those bytes outside the JavaScript heap and hand them straight to `URL.createObjectURL`, an `<img>`, or a storage write, without ever materialising a buffer your code has no use for.
saying these in an interview costs you the question
- Thinks binaryType also changes how text messages are delivered
- Believes a Blob's bytes can be read synchronously
- Assumes 'arraybuffer' is the default value
- Sets binaryType long after messages have started arriving
- Expects binaryType to change what send() puts on the wire