How to Send multipart/form-data Using Axios
This guide explains how to properly send
multipart/form-data payloads, such as files and binary
data, using the Axios HTTP client. You will learn the correct
implementation methods for both browser and Node.js environments, how
modern Axios handles boundary headers automatically, and common pitfalls
to avoid during implementation.
Sending Form Data in the Browser
In modern browsers, the standard approach relies on the native
FormData interface.
import axios from 'axios';
const uploadFile = async (file, textDescription) => {
const formData = new FormData();
formData.append('file', file);
formData.append('description', textDescription);
try {
const response = await axios.post('https://api.example.com/upload', formData);
console.log('Upload successful:', response.data);
} catch (error) {
console.error('Upload failed:', error);
}
};Automatic Content-Type Management
Do not manually set the Content-Type header to
multipart/form-data. When left unset, Axios and the browser
automatically assign the header along with the required unique boundary
string (e.g.,
multipart/form-data; boundary=----WebKitFormBoundary...).
Manually setting this header without the boundary will cause the server
to fail to parse the incoming payload.
Automatic Serialization (Axios v1.x+)
Modern versions of Axios support automatic serialization. You can
pass a standard JavaScript object containing file references or Blob
instances, and specify multipart/form-data in the request
configuration.
import axios from 'axios';
const uploadDirectly = async (fileInput) => {
try {
const response = await axios.post(
'https://api.example.com/upload',
{
file: fileInput.files[0],
fileName: 'example.png',
},
{
headers: {
'Content-Type': 'multipart/form-data',
},
}
);
console.log(response.data);
} catch (error) {
console.error(error);
}
};Sending Form Data in Node.js
In Node.js environments prior to native FormData support
(Node.js 18+), you must use the form-data package or read
streams.
Using Node.js Streams with
form-data
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
async function uploadFileNode() {
const form = new FormData();
form.append('file', fs.createReadStream('/path/to/file.pdf'));
form.append('user', 'John Doe');
try {
const response = await axios.post('https://api.example.com/upload', form, {
headers: {
...form.getHeaders(),
},
});
console.log('File uploaded:', response.data);
} catch (error) {
console.error('Error uploading file:', error);
}
}When using the form-data library in Node.js, calling
form.getHeaders() is required to supply the correct
boundary metadata generated by the library.
Tracking Upload Progress
Axios provides the onUploadProgress callback, which
allows you to monitor the transmission state for large payloads:
const response = await axios.post('https://api.example.com/upload', formData, {
onUploadProgress: (progressEvent) => {
const percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
console.log(`Upload Progress: ${percentCompleted}%`);
},
});