How to Stream Axios Responses in Node.js
This guide explains how to read incoming HTTP response streams chunk-by-chunk using Axios in Node.js. By configuring Axios to handle responses as streams instead of buffering the entire payload into memory, you can efficiently process large datasets, download massive files, or handle real-time data feeds like Server-Sent Events (SSE).
Configuring Axios for Streaming
By default, Axios parses and buffers the entire response body in
memory before resolving the promise. To receive the response as a
Node.js Readable stream, set the responseType configuration
property to 'stream'.
const axios = require('axios');
async function initiateStream() {
const response = await axios({
method: 'get',
url: 'https://example.com/large-data-source',
responseType: 'stream'
});
return response.data;
}When responseType: 'stream' is enabled,
response.data returns a Node.js Readable
stream instance rather than a parsed object or string.
Method 1: Using Event Listeners
The traditional way to process stream chunks in Node.js is by
attaching listeners to the data, end, and
error events on response.data.
const axios = require('axios');
async function streamWithEvents() {
try {
const response = await axios({
method: 'get',
url: 'https://httpbin.org/stream/5',
responseType: 'stream'
});
const stream = response.data;
// Triggered each time a chunk of data is received
stream.on('data', (chunk) => {
console.log('Received chunk:', chunk.toString());
});
// Triggered when the stream has finished receiving data
stream.on('end', () => {
console.log('Stream completed successfully.');
});
// Triggered if an error occurs during streaming
stream.on('error', (err) => {
console.error('Stream processing error:', err.message);
});
} catch (error) {
console.error('Request failed:', error.message);
}
}
streamWithEvents();Method 2: Using
Async Iteration (for await...of)
Node.js readable streams implement the async iterable interface. You
can process chunks sequentially using a for await...of
loop, which provides cleaner asynchronous control flow and built-in
error handling via standard try...catch blocks.
const axios = require('axios');
async function streamWithAsyncIterator() {
try {
const response = await axios({
method: 'get',
url: 'https://httpbin.org/stream/5',
responseType: 'stream'
});
for await (const chunk of response.data) {
const dataString = chunk.toString();
console.log('Received chunk:', dataString);
// Perform sequential per-chunk processing here
}
console.log('Stream finished.');
} catch (error) {
console.error('Streaming failed:', error.message);
}
}
streamWithAsyncIterator();Piping Streams to a Destination
If your goal is to forward incoming chunks directly to disk or
another destination, use the pipe() method or the
stream/promises pipeline utility.
const axios = require('axios');
const fs = require('fs');
const { pipeline } = require('stream/promises');
async function downloadFile() {
try {
const response = await axios({
method: 'get',
url: 'https://example.com/largefile.zip',
responseType: 'stream'
});
const writer = fs.createWriteStream('local-file.zip');
// Safely handles stream cleanup and error propagation
await pipeline(response.data, writer);
console.log('File download complete.');
} catch (error) {
console.error('Pipeline failed:', error.message);
}
}
downloadFile();Handling Stream Termination
To cancel or close a stream early (for example, if a client disconnects or an error condition occurs), destroy the readable stream to free up system resources and close the underlying socket:
response.data.destroy();