
Axios is a promise-based HTTP client for the browser and Node.js. It’s designed to make interacting with APIs simpler and more approachable, especially when compared to native fetch or other libraries. One of the standout features of Axios is that it automatically transforms JSON data, which can save you a lot of time. No need to manually invoke JSON.parse() on your responses.
Another advantage is how Axios handles requests and will automatically reject the promise for HTTP status codes outside the range of 2xx. This behavior helps in quickly identifying issues with server responses and eliminates some of the boilerplate error handling you’d typically write.
Here’s a simple example of how you can set up Axios in your project:
npm install axios
You can then import it into your project with:
import axios from 'axios';
Axios also supports request and response interceptors, which allows you to modify requests or responses before they are handled by your application. This can be especially useful for adding authentication tokens to headers or logging requests for debugging purposes.
Another neat feature is the ability to cancel requests. If you’re making multiple requests and only care about the latest one, you can cancel previous requests to avoid unnecessary processing. This capability can be crucial in applications that require real-time data fetching, such as messaging apps or live feeds.
The default timeout is also configurable, which allows you to manage how long your application will wait for a response before giving up. Setting a reasonably low timeout can significantly improve user experience by ensuring your app remains responsive, even when a server is slow to respond.
Axios supports all the HTTP methods you’d commonly need: GET, POST, PUT, DELETE, and more. Plus, it can handle request and response serialization automatically, so you can send and receive data without worrying too much about format.
To get started with making GET requests, you’ll find that the syntax is straightforward:
axios.get('https://api.example.com/data')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Error fetching data:', error);
});
This simple example retrieves data from a given endpoint and logs it to the console. If there’s an error during the request, it’s caught and logged as well.
But let’s not get ahead of ourselves. It’s essential to understand how you can handle responses and errors gracefully, ensuring your application can react appropriately in various scenarios…
Highwings 8K 10K 4K HDMI Cable 48Gbps 6.6FT/2M, Certified Ultra High Speed 2.1 HDMI Cable Braided Cord-4K@120Hz 8K@60Hz, DTS:X, HDCP 2.2 & 2.3, HDR 10 Compatible with Roku TV/PS5/HDTV/Blu-ray
$5.99 (as of June 2, 2026 22:39 GMT +00:00 - More infoProduct prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on [relevant Amazon Site(s), as applicable] at the time of purchase will apply to the purchase of this product.)Making your first GET request with Axios
When you make a GET request using Axios, you can expect a response that contains not only the data you requested but also additional metadata about the request. This includes HTTP status codes, headers, and other useful properties. Handling this response effectively is crucial for building robust applications.
The response object returned by Axios has a structure that resembles the following:
{
data: {}, // the data from the response
status: 200, // the HTTP status code
statusText: 'OK', // the status text
headers: {}, // the response headers
config: {}, // the config that was used for the request
request: {} // the request object
}
To access the data returned in the response, you typically focus on the data property. However, it’s equally important to be aware of potential errors and handle them gracefully. For instance, if the server returns a 404 error, you should inform the user rather than leaving them in the dark.
Here’s an example of how you can extract useful information from the response and handle different HTTP status codes:
axios.get('https://api.example.com/data')
.then(response => {
if (response.status === 200) {
console.log('Data received:', response.data);
} else {
console.warn('Unexpected status code:', response.status);
}
})
.catch(error => {
if (error.response) {
// The request was made and the server responded with a status code
console.error('Error fetching data:', error.response.status, error.response.data);
} else if (error.request) {
// The request was made but no response was received
console.error('No response received:', error.request);
} else {
// Something happened in setting up the request that triggered an error
console.error('Error', error.message);
}
});
This code provides a more detailed approach to error handling, allowing you to respond differently based on the type of error encountered. It distinguishes between errors that arise from the server’s response and those that occur before the request is sent, giving you the flexibility to handle each scenario appropriately.
Moreover, Axios lets you set up global error handling, which can be particularly useful for centralized logging or user notifications. You can create an interceptor that catches all errors before they propagate through your application:
axios.interceptors.response.use(
response => response,
error => {
console.error('Global error handler:', error);
return Promise.reject(error);
}
);
This interceptor will log every error that occurs on a response, which can help you debug issues across your application. Just be mindful of the volume of logs generated, as too much logging can lead to performance issues or make it harder to find relevant information.
As you develop more complex applications, you might find yourself dealing with multiple requests that depend on each other. In such cases, it’s vital to manage the flow of data properly, ensuring that requests complete in the right order. You can achieve this using Promise chaining or async/await syntax, which simplifies the handling of asynchronous operations.
Here’s how you can use async/await to make sequential GET requests:
async function fetchData() {
try {
const userResponse = await axios.get('https://api.example.com/user');
const postsResponse = await axios.get(https://api.example.com/posts?userId=${userResponse.data.id}); console.log('User Posts:', postsResponse.data); } catch (error) { console.error('Error fetching data:', error); } } fetchData();
This pattern is cleaner and easier to read than traditional Promise chaining, making it ideal for scenarios where you need to wait for one request to complete before starting another. It’s also easier to handle errors in a single location rather than having to catch them at each stage of the chain.
By leveraging Axios’ capabilities for handling responses and errors, you can build applications that are not only functional but also resilient. The next step is to explore more advanced features of Axios, including how to send data with POST requests and manage headers more effectively…
Handling responses and errors gracefully
So, you’ve made a request, but what happens when things go wrong? A server might be down, an endpoint might not exist, or you might simply lose your network connection. Axios standardizes error handling by wrapping all these potential failures in a single error object that you can inspect in your .catch() block.
The structure of this error object is what makes it so useful. It’s not just a generic message. Axios gives you a clear breakdown, so you know exactly where the failure occurred. There are three main scenarios you’ll encounter, which you can check for on the error object:
First, there’s error.response. This exists if the server actually responded, but with an HTTP status code that falls outside the 2xx range. This is the most common case you’ll handle. It contains all the response information we saw earlier: data, status, headers, etc. You can inspect error.response.status to decide what to do next.
Second, there’s error.request. This object is present if the request was made, but no response was ever received. Think of a network error or a timeout. The browser sent the request out into the void, but nothing came back. In a Node.js environment, error.request is an instance of http.ClientRequest.
Finally, if neither of those is present, you’re left with error.message. This usually indicates a problem that happened when you were setting up the request itself, before it was even sent. Maybe you passed an invalid configuration option.
axios.get('https://api.example.com/non-existent-endpoint')
.catch(function (error) {
if (error.response) {
// The server responded with a status code outside the 2xx range
console.log('Server responded with an error');
console.log('Status:', error.response.status);
console.log('Data:', error.response.data);
console.log('Headers:', error.response.headers);
} else if (error.request) {
// The request was made but no response was received
console.log('No response received from server. Check network.');
console.log('Request details:', error.request);
} else {
// Something happened in setting up the request that triggered an Error
console.log('Error setting up request:', error.message);
}
});
While this is a solid reactive approach, you can also be proactive. Axios allows you to define what you consider a “successful” HTTP status code using the validateStatus configuration option. By default, it’s any code in the 200-299 range. But what if a 404 “Not Found” is an expected and valid outcome for your application logic? You can tell Axios to treat it as a success, so it resolves the promise and goes to your .then() block instead of .catch().
axios.get('https://api.example.com/users/12345', {
validateStatus: function (status) {
// Treat any 2xx status or a 404 as a success
return (status >= 200 && status < 300) || status === 404;
}
})
.then(function (response) {
if (response.status === 404) {
console.log('User does not exist, but that is okay.');
// Handle the "not found" case gracefully
} else {
console.log('User found:', response.data);
}
});
Another critical aspect of graceful handling is managing timeouts. You can’t let your application hang forever waiting for a slow server. You can specify a timeout in milliseconds in the request configuration. If the request takes longer than your specified timeout, the promise will be rejected.
axios.get('https://api.example.com/slow-service', {
timeout: 5000 // Wait for 5 seconds
}).then(response => {
console.log('Got response from slow service:', response.data);
}).catch(error => { // A timeout error will have a code property set to 'ECONNABORTED'
if (error.code === 'ECONNABORTED') {
console.error('Request timed out after 5 seconds.');
} else {
// Handle other errors
console.error('An error occurred:', error.message);
}
});
Finally, sometimes you need to cancel a request that’s already in flight. For example, if a user navigates away from a page while data is still loading. Axios supports cancellation using an AbortController, which is the modern standard for aborting asynchronous tasks in JavaScript. You create a controller, pass its signal to the request config, and call controller.abort() when you want to cancel.
const controller = new AbortController();
axios.get('https://api.example.com/long-running-task', {
signal: controller.signal
})
.then(response => {
console.log('Task completed:', response.data);
})
.catch(error => {
if (axios.isCancel(error)) {
console.log('Request was canceled by the user.');
} else {
console.error('An error occurred:', error.message);
}
});
// After 2 seconds, we decide we don't need the data anymore
setTimeout(() => {
controller.abort();
}, 2000);
