
Using Axios in Vanilla JS: A Beginner’s Guide
Axios is a promise-based HTTP client library that makes API requests cleaner and more manageable than the traditional XMLHttpRequest or even the newer fetch API. While many developers associate Axios with React or Node.js environments, it works perfectly in vanilla JavaScript projects, offering automatic JSON data transformation, request/response interceptors, and better error handling out of the box. This guide will walk you through integrating Axios into your vanilla JS projects, covering everything from basic GET requests to advanced interceptor configurations and real-world troubleshooting scenarios.
How Axios Works in Vanilla JavaScript
Axios operates as a wrapper around XMLHttpRequest in browsers, providing a promise-based interface that simplifies HTTP operations. Unlike fetch(), Axios automatically handles JSON parsing, throws errors for HTTP error status codes, and provides more intuitive request/response transformation options.
The library can be included in vanilla JavaScript projects through a CDN link or by downloading the standalone file. Once loaded, Axios exposes a global object with methods corresponding to HTTP verbs (GET, POST, PUT, DELETE, etc.), plus configuration options for headers, timeouts, and interceptors.
Feature | Axios | Fetch API | XMLHttpRequest |
---|---|---|---|
JSON Handling | Automatic | Manual (.json()) | Manual (JSON.parse) |
Error Handling | Throws on 4xx/5xx | Only network errors | Manual status checking |
Request Timeout | Built-in | Requires AbortController | Built-in |
Interceptors | Yes | No | No |
Browser Support | IE11+ | Modern browsers | All browsers |
Step-by-Step Implementation Guide
Getting started with Axios in vanilla JavaScript requires minimal setup. Here’s how to integrate it into your project:
Installation and Basic Setup
Add Axios to your HTML file via CDN:
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
Or download and host it locally:
<script src="./js/axios.min.js"></script>
Basic GET Request
Start with a simple GET request to fetch data from an API:
// Basic GET request
axios.get('https://jsonplaceholder.typicode.com/posts/1')
.then(response => {
console.log('Data:', response.data);
console.log('Status:', response.status);
console.log('Headers:', response.headers);
})
.catch(error => {
console.error('Error:', error.message);
});
POST Request with Data
Sending data to an API endpoint:
const postData = {
title: 'New Post',
body: 'This is the post content',
userId: 1
};
axios.post('https://jsonplaceholder.typicode.com/posts', postData)
.then(response => {
console.log('Created:', response.data);
document.getElementById('result').innerHTML =
`<p>Post created with ID: ${response.data.id}</p>`;
})
.catch(error => {
console.error('Failed to create post:', error);
});
Advanced Configuration
Create an Axios instance with custom configuration:
const apiClient = axios.create({
baseURL: 'https://api.example.com/v1',
timeout: 10000,
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer your-token-here'
}
});
// Use the configured instance
apiClient.get('/users')
.then(response => {
displayUsers(response.data);
})
.catch(handleApiError);
Real-World Examples and Use Cases
Dynamic Content Loading
A common use case is loading content dynamically without page refresh:
class ContentLoader {
constructor(baseUrl) {
this.api = axios.create({
baseURL: baseUrl,
timeout: 5000
});
}
async loadArticle(articleId) {
try {
const response = await this.api.get(`/articles/${articleId}`);
this.renderArticle(response.data);
} catch (error) {
this.showError('Failed to load article');
}
}
renderArticle(article) {
document.getElementById('article-content').innerHTML = `
<h1>${article.title}</h1>
<p>${article.content}</p>
<small>Published: ${article.publishedAt}</small>
`;
}
showError(message) {
document.getElementById('error-message').style.display = 'block';
document.getElementById('error-message').textContent = message;
}
}
Form Submission with Validation
Handle form submissions with proper error handling and user feedback:
document.getElementById('contact-form').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const data = Object.fromEntries(formData.entries());
// Show loading state
const submitBtn = document.getElementById('submit-btn');
submitBtn.disabled = true;
submitBtn.textContent = 'Sending...';
try {
const response = await axios.post('/api/contact', data, {
headers: {
'Content-Type': 'application/json'
}
});
showSuccessMessage('Message sent successfully!');
e.target.reset();
} catch (error) {
if (error.response && error.response.status === 422) {
showValidationErrors(error.response.data.errors);
} else {
showErrorMessage('Failed to send message. Please try again.');
}
} finally {
submitBtn.disabled = false;
submitBtn.textContent = 'Send Message';
}
});
Using Interceptors for Global Handling
Interceptors are powerful features that allow you to handle requests and responses globally:
// Request interceptor - add auth token to all requests
axios.interceptors.request.use(
config => {
const token = localStorage.getItem('authToken');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
error => Promise.reject(error)
);
// Response interceptor - handle common errors
axios.interceptors.response.use(
response => response,
error => {
if (error.response?.status === 401) {
// Redirect to login page
window.location.href = '/login';
} else if (error.response?.status === 500) {
showGlobalError('Server error. Please try again later.');
}
return Promise.reject(error);
}
);
Best Practices and Common Pitfalls
Best Practices
- Use async/await for cleaner code instead of chaining .then() calls
- Set appropriate timeouts to prevent hanging requests
- Implement proper error handling for different HTTP status codes
- Use interceptors for cross-cutting concerns like authentication
- Create configured instances rather than using the global axios object
- Validate data before sending requests to reduce server errors
Common Pitfalls and Solutions
CORS Issues: When making requests to different domains, ensure the server includes proper CORS headers. You cannot fix CORS issues from the client side:
// This won't work for CORS issues
axios.get('https://external-api.com/data', {
headers: {
'Access-Control-Allow-Origin': '*' // Don't do this
}
});
Memory Leaks with Interceptors: Always remove interceptors when they’re no longer needed:
// Store the interceptor ID
const requestInterceptor = axios.interceptors.request.use(config => config);
// Remove it later
axios.interceptors.request.eject(requestInterceptor);
Handling Network Errors: Distinguish between network errors and HTTP errors:
axios.get('/api/data')
.catch(error => {
if (error.response) {
// Server responded with error status
console.log('Server Error:', error.response.status);
} else if (error.request) {
// Request made but no response received
console.log('Network Error:', error.request);
} else {
// Something else happened
console.log('Error:', error.message);
}
});
Performance Considerations
Axios adds approximately 40KB to your bundle size (minified), which is reasonable for the features it provides. However, consider these optimizations:
- Request Cancellation: Use AbortController for cancelling requests when components unmount or when new requests supersede old ones
- Response Caching: Implement caching for frequently requested data to reduce server load
- Connection Pooling: Axios automatically reuses connections, but be mindful of concurrent request limits
// Request cancellation example
const source = axios.CancelToken.source();
axios.get('/api/search', {
cancelToken: source.token,
params: { q: searchQuery }
}).catch(thrown => {
if (axios.isCancel(thrown)) {
console.log('Request cancelled');
}
});
// Cancel the request if needed
if (newSearchQuery !== searchQuery) {
source.cancel('Operation cancelled by user');
}
Troubleshooting Common Issues
Request Timeout Errors: Increase timeout values for slow APIs or implement retry logic:
const axiosRetry = async (url, options = {}, retries = 3) => {
try {
return await axios.get(url, { timeout: 5000, ...options });
} catch (error) {
if (retries > 0 && error.code === 'ECONNABORTED') {
console.log(`Retrying... ${retries} attempts left`);
return axiosRetry(url, options, retries - 1);
}
throw error;
}
};
Content-Type Issues: Ensure you’re sending the correct Content-Type header:
// For form data
const formData = new FormData();
formData.append('file', fileInput.files[0]);
axios.post('/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
// For URL-encoded data
const params = new URLSearchParams();
params.append('key', 'value');
axios.post('/api/form', params, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
For comprehensive documentation and advanced usage patterns, check the official Axios documentation. The library’s GitHub repository also contains extensive examples and troubleshooting guides for complex scenarios.

This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.
This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.