Axios
Most popular HTTP client library for JavaScript/TypeScript. Features promise-based API, request/response transformation, automatic JSON handling, interceptors, error handling, and timeout capabilities. Works in both browser and Node.js environments with extensive configuration options.
Library
Axios
Overview
Axios is developed as a "Promise based HTTP client for the browser and node.js" and is an HTTP client library. With isomorphic design that works with the same codebase in both browser and Node.js environments, it uses the native Node.js HTTP module on the server-side and XMLHttpRequests on the client-side. It provides automatic JSON transformation, request/response interceptors, robust error handling, and supports older browsers including IE11.
Details
Axios 1.7.9 remains the most popular HTTP client library in the JavaScript ecosystem as of 2025, with active development. It provides complete TypeScript support with TypeScript 4.7+ and flexible module resolution with esModuleInterop. Automatic JSON transformation eliminates the need for manual parsing, and global interceptors enable unified preprocessing and postprocessing of requests and responses. XMLHttpRequest-based architecture ensures stable operation even on older browsers including IE11.
Key Features
- Automatic JSON Transformation: Automatic conversion of JSON responses to JavaScript objects
- Interceptors: Global preprocessing and postprocessing functionality for requests and responses
- Default Configuration: Reduction of code duplication through predefined settings like base URLs and headers
- Error Handling: Robust error handling with detailed error messages
- Wide Browser Support: Stable operation on older browsers including IE11
- TypeScript Integration: Built-in TypeScript definitions and error type guards
Pros and Cons
Pros
- Most established HTTP client in JavaScript ecosystem (10+ years of development)
- High compatibility through wide browser support including IE11
- Improved development efficiency through automatic JSON conversion and rich configuration options
- Unified request/response processing through interceptors
- Robust error handling and ease of debugging
- Rich ecosystem with plugins and extensions
Cons
- Adds 35KB to bundle size (Fetch API adds 0KB)
- Fetch API can achieve equivalent functionality in modern browsers
- Overkill for lightweight API client needs
- Some new features limited due to XMLHttpRequest base
- Configuration complexity due to feature richness
- Slightly higher learning curve compared to fetch API
References
Code Examples
Basic Setup
# Install Axios
npm install axios
# TypeScript type definitions (usually included automatically)
# npm install @types/axios # Not needed with latest versions
Import and Basic Usage
// ES6 modules (recommended)
import axios from 'axios';
// CommonJS (Node.js) - with TypeScript type support
const axios = require('axios').default;
// Simple GET request
axios.get('/user?ID=12345')
.then(function (response) {
// handle success
console.log(response.data);
console.log(response.status);
console.log(response.headers);
})
.catch(function (error) {
// handle error
console.log(error);
})
.finally(function () {
// always executed
});
// Alternative method with separate parameters
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response.data);
})
.catch(function (error) {
console.log(error);
});
Modern Approach with Async/Await
// async/await usage
async function getUser() {
try {
const response = await axios.get('/user?ID=12345');
console.log('User data:', response.data);
console.log('Status:', response.status);
return response.data;
} catch (error) {
console.error('Error occurred:', error);
throw error;
}
}
// POST request example
async function createUser(userData) {
try {
const response = await axios.post('/user', {
firstName: 'John',
lastName: 'Doe',
email: '[email protected]'
});
console.log('User created successfully:', response.data);
return response.data;
} catch (error) {
console.error('User creation error:', error);
throw error;
}
}
// Multiple concurrent requests
async function getUserWithPermissions(userId) {
try {
const [userResponse, permissionsResponse] = await Promise.all([
axios.get(`/user/${userId}`),
axios.get(`/user/${userId}/permissions`)
]);
return {
user: userResponse.data,
permissions: permissionsResponse.data
};
} catch (error) {
console.error('Data retrieval error:', error);
throw error;
}
}
Instance Creation and Custom Configuration
// Creating custom instance
const apiClient = axios.create({
baseURL: 'https://api.example.com/v1',
timeout: 10000,
headers: {
'Content-Type': 'application/json',
'X-API-Key': 'your-api-key'
}
});
// Global default configuration
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = 'Bearer your-token';
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
// Configuration precedence test
const instance = axios.create();
instance.defaults.timeout = 2500; // Instance default
// Request-specific configuration (highest priority)
instance.get('/longRequest', {
timeout: 5000
});
// Complete configuration options example
const config = {
url: '/user',
method: 'get',
baseURL: 'https://api.example.com',
headers: {'X-Requested-With': 'XMLHttpRequest'},
params: { ID: 12345 },
data: { firstName: 'Fred' },
timeout: 1000,
withCredentials: false,
auth: {
username: 'janedoe',
password: 's00pers3cret'
},
responseType: 'json',
validateStatus: function (status) {
return status >= 200 && status < 300;
}
};
axios(config)
.then(function (response) {
console.log(response);
});
Common Processing with Interceptors
// Request interceptor
axios.interceptors.request.use(
function (config) {
// Processing before request is sent
console.log('Sending request:', config);
// Automatic addition of auth token
const token = localStorage.getItem('authToken');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
// Record request time
config.metadata = { startTime: new Date() };
return config;
},
function (error) {
// Processing for request error
console.error('Request error:', error);
return Promise.reject(error);
}
);
// Response interceptor
axios.interceptors.response.use(
function (response) {
// Processing for 2xx status codes
console.log('Response received:', response);
// Calculate response time
const endTime = new Date();
const duration = endTime - response.config.metadata.startTime;
console.log(`Request duration: ${duration}ms`);
return response;
},
function (error) {
// Processing for error status codes
console.error('Response error:', error);
if (error.response.status === 401) {
// Redirect to login page for authentication errors
localStorage.removeItem('authToken');
window.location.href = '/login';
}
return Promise.reject(error);
}
);
// Removing interceptors
const myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);
Error Handling and Debugging
// Detailed error handling
axios.get('/user/12345')
.catch(function (error) {
if (error.response) {
// Server responded with status code outside 2xx range
console.log('Error data:', error.response.data);
console.log('Status:', error.response.status);
console.log('Headers:', error.response.headers);
// Status code-specific processing
switch (error.response.status) {
case 400:
console.error('Bad Request: Invalid request');
break;
case 401:
console.error('Authentication Error: Login required');
break;
case 404:
console.error('Resource not found');
break;
case 500:
console.error('Server error occurred');
break;
default:
console.error('Unexpected error occurred');
}
} else if (error.request) {
// Request was sent but no response received
console.log('Network error:', error.request);
console.error('Cannot connect to server');
} else {
// Error occurred during request setup
console.log('Configuration error:', error.message);
}
// Request configuration information
console.log('Request config:', error.config);
// Detailed error information (JSON format)
console.log('Detailed error info:', error.toJSON());
});
// Custom error validation
axios.get('/user/12345', {
validateStatus: function (status) {
return status < 500; // Only consider status codes below 500 as success
}
});
// Timeout and retry functionality implementation
async function requestWithRetry(config, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await axios(config);
return response;
} catch (error) {
console.log(`Attempt ${i + 1} failed:`, error.message);
if (i === maxRetries - 1) {
throw error; // Throw error if last attempt fails
}
// Wait with exponential backoff
const delay = Math.pow(2, i) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
// Usage example
try {
const response = await requestWithRetry({
url: '/api/unstable-endpoint',
timeout: 5000
});
console.log('Success:', response.data);
} catch (error) {
console.error('Finally failed:', error);
}
Form Data and File Upload
// Using FormData
const formData = new FormData();
formData.append('username', 'johndoe');
formData.append('email', '[email protected]');
formData.append('avatar', fileInput.files[0]);
axios.post('/user/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data'
},
onUploadProgress: function (progressEvent) {
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
console.log(`Upload progress: ${percentCompleted}%`);
}
})
.then(function (response) {
console.log('Upload successful:', response.data);
});
// Sending URL-encoded data
const params = new URLSearchParams();
params.append('name', 'John Doe');
params.append('email', '[email protected]');
axios.post('/user', params, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
// Automatic FormData header setup interceptor
axios.interceptors.request.use(config => {
if (config.data instanceof FormData) {
Object.assign(config.headers, config.data.getHeaders());
}
return config;
});
// File download
async function downloadFile(url, filename) {
try {
const response = await axios({
method: 'GET',
url: url,
responseType: 'blob',
onDownloadProgress: function (progressEvent) {
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
console.log(`Download progress: ${percentCompleted}%`);
}
});
// Download file in browser
const url_blob = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url_blob;
link.setAttribute('download', filename);
document.body.appendChild(link);
link.click();
link.remove();
console.log('Download completed');
} catch (error) {
console.error('Download error:', error);
}
}
Request Cancellation
// Cancellation using AbortController (recommended)
const controller = new AbortController();
axios.get('/user/12345', {
signal: controller.signal
})
.then(function (response) {
console.log(response.data);
})
.catch(function (error) {
if (axios.isCancel(error)) {
console.log('Request was cancelled:', error.message);
} else {
console.error('Error:', error);
}
});
// Cancel request after 5 seconds
setTimeout(() => {
controller.abort('Operation timed out');
}, 5000);
// Using deprecated CancelToken (for backward compatibility)
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get('/user/12345', {
cancelToken: source.token
})
.catch(function (thrown) {
if (axios.isCancel(thrown)) {
console.log('Request cancelled:', thrown.message);
} else {
console.error('Error:', thrown);
}
});
// Execute cancellation
source.cancel('Cancelled by user');
// Batch cancellation of multiple requests
const cancelTokenSource = axios.CancelToken.source();
Promise.all([
axios.get('/user/12345', { cancelToken: cancelTokenSource.token }),
axios.get('/user/12345/permissions', { cancelToken: cancelTokenSource.token })
])
.then(function (responses) {
console.log('All results:', responses);
})
.catch(function (error) {
if (axios.isCancel(error)) {
console.log('All requests were cancelled');
}
});
// Conditional cancellation
setTimeout(() => {
cancelTokenSource.cancel('Operation was cancelled');
}, 3000);