Axios ArrayBuffer Uploads for Binary Protocols

This article explains how the Axios HTTP client handles raw ArrayBuffer data for binary-based network protocols such as Protocol Buffers, MessagePack, or custom binary payloads. It covers the underlying transport mechanisms in both browser and Node.js environments, required header configurations, proper payload handling, and how to avoid common serialization pitfalls.

Environment-Specific Transport Mechanisms

Axios automatically adapts how it transmits binary data depending on the execution runtime:

Setting Request Headers for Binary Payloads

When transmitting raw binary protocols, you must explicitly define the Content-Type header. If omitted, Axios or the receiving server might attempt to infer the MIME type or default to application/x-www-form-urlencoded or application/json.

Common headers for binary uploads include:

Code Example: Sending an ArrayBuffer

import axios from 'axios';

// Create binary data
const buffer = new ArrayBuffer(8);
const view = new Int32Array(buffer);
view[0] = 42;
view[1] = 84;

async function uploadBinaryData() {
  try {
    const response = await axios.post('https://api.example.com/binary-endpoint', buffer, {
      headers: {
        'Content-Type': 'application/octet-stream',
      },
      // Ensure the response is also handled as binary if needed
      responseType: 'arraybuffer',
      // Explicit maxBodyLength setting for large binary uploads in Node.js
      maxBodyLength: Infinity,
      maxContentLength: Infinity,
    });

    console.log('Binary upload successful:', response.data);
  } catch (error) {
    console.error('Binary upload failed:', error);
  }
}

uploadBinaryData();

Handling TypedArrays vs. ArrayBuffers

Axios accepts both ArrayBuffer instances and typed array views (like Uint8Array, Float32Array, or DataView).

If you are working with a typed array that represents a sub-slice of a larger buffer, pass the typed array directly or pass the specific sliced buffer:

const uint8Array = new Uint8Array([0x01, 0x02, 0x03, 0x04]);

// Passing TypedArray directly:
await axios.post('/api', uint8Array, {
  headers: { 'Content-Type': 'application/octet-stream' }
});

// Or accessing the underlying ArrayBuffer:
await axios.post('/api', uint8Array.buffer, {
  headers: { 'Content-Type': 'application/octet-stream' }
});

Request Transformations and Interceptors

By default, Axios includes built-in request transformers in axios.defaults.transformRequest. These default transformers check whether the data is an ArrayBuffer, Buffer, FormData, or Stream. When raw binary data is detected, Axios bypasses JSON stringification and leaves the payload untouched.

If you use custom Axios instances with modified transformRequest functions, ensure your custom transformations do not convert binary payloads into strings or objects before transmission:

const instance = axios.create({
  transformRequest: [
    (data, headers) => {
      if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {
        return data; // Do not transform binary data
      }
      return JSON.stringify(data);
    }
  ]
});