How to Use Axios in JavaScript: Complete Guide
A complete guide to using Axios for HTTP requests in JavaScript. Covers installation, GET and POST requests, automatic JSON transforms, error handling differences from Fetch, creating instances with defaults, cancellation with AbortController, timeout configuration, and a full comparison table between Axios and Fetch.
Axios is a promise-based HTTP client for the browser and Node.js that simplifies making HTTP requests compared to the native Fetch API. It provides automatic JSON transforms, built-in error handling for HTTP status codes, request/response interceptors, and a cleaner API for common tasks.
Installing Axios
# npm
npm install axios
# yarn
yarn add axios
# CDN (browser)
# <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>// ES Module import
import axios from "axios";
// CommonJS
const axios = require("axios");See JavaScript ES6 modules import export guide for module syntax details.
Basic GET Request
async function getUsers() {
try {
const response = await axios.get("https://jsonplaceholder.typicode.com/users");
// response.data is already parsed JSON
console.log(response.data);
console.log(response.status); // 200
console.log(response.statusText); // "OK"
console.log(response.headers); // response headers
} catch (error) {
console.error("Request failed:", error.message);
}
}Unlike Fetch, Axios automatically parses JSON responses. There is no need to call response.json(). The parsed data is available directly on response.data.
The Axios Response Object
| Property | Description |
|---|---|
data | Response body, auto-parsed from JSON |
status | HTTP status code (200, 404, etc.) |
statusText | HTTP status message ("OK", "Not Found") |
headers | Response headers (lowercase keys) |
config | The request configuration that was used |
request | The underlying XMLHttpRequest (browser) or http.ClientRequest (Node.js) |
GET With Query Parameters
async function searchUsers(query, page) {
const response = await axios.get("https://api.example.com/users", {
params: {
q: query,
page: page,
limit: 20,
},
});
// URL becomes: /users?q=query&page=1&limit=20
return response.data;
}Axios serializes the params object into the query string automatically.
POST Request
async function createUser(userData) {
try {
const response = await axios.post("https://api.example.com/users", {
name: userData.name,
email: userData.email,
role: userData.role,
});
console.log("Created user:", response.data);
console.log("Status:", response.status); // 201
return response.data;
} catch (error) {
console.error("Failed to create user:", error.message);
throw error;
}
}Axios automatically sets Content-Type: application/json when the body is an object. No manual JSON.stringify() or header setting needed.
PUT and DELETE Requests
// PUT - full update
async function updateUser(id, userData) {
const response = await axios.put(`https://api.example.com/users/${id}`, userData);
return response.data;
}
// PATCH - partial update
async function patchUser(id, updates) {
const response = await axios.patch(`https://api.example.com/users/${id}`, updates);
return response.data;
}
// DELETE
async function deleteUser(id) {
const response = await axios.delete(`https://api.example.com/users/${id}`);
return response.status === 204;
}Error Handling: Axios vs Fetch
The biggest difference between Axios and Fetch is how they treat HTTP errors. Fetch only rejects on network failures; a 404 or 500 response is considered successful. Axios rejects the promise for any response outside the 2xx range.
async function fetchUserSafe(id) {
try {
const response = await axios.get(`/api/users/${id}`);
return response.data;
} catch (error) {
if (error.response) {
// Server responded with 4xx or 5xx
console.error("Status:", error.response.status);
console.error("Data:", error.response.data);
console.error("Headers:", error.response.headers);
} else if (error.request) {
// Request was made but no response received (network error)
console.error("No response received:", error.request);
} else {
// Error in setting up the request
console.error("Request setup error:", error.message);
}
throw error;
}
}Error Categories
| Error Type | error.response | error.request | Cause |
|---|---|---|---|
| HTTP error (4xx/5xx) | Present | Present | Server returned error status |
| Network error | undefined | Present | No response received (offline, DNS, CORS) |
| Setup error | undefined | undefined | Invalid config or canceled request |
Creating an Axios Instance
const api = axios.create({
baseURL: "https://api.example.com/v2",
timeout: 10000,
headers: {
"Authorization": `Bearer ${getToken()}`,
"X-Custom-Header": "RuneHub",
},
});
// Use the instance
async function getProjects() {
const response = await api.get("/projects");
return response.data;
}
async function createProject(data) {
const response = await api.post("/projects", data);
return response.data;
}Instances let you configure a base URL, default headers, and timeout once. Every request through the instance inherits those defaults. This is especially useful when your app talks to multiple APIs.
Request Configuration
const response = await axios({
method: "post",
url: "/api/data",
baseURL: "https://api.example.com",
headers: {
"Authorization": "Bearer token123",
"Content-Type": "application/json",
},
data: { key: "value" },
params: { format: "json" },
timeout: 5000,
responseType: "json", // default
validateStatus: (status) => status < 500,
maxRedirects: 5, // Node.js only
signal: controller.signal, // AbortController
});Cancellation
async function searchWithCancel(query) {
// Create an AbortController
const controller = new AbortController();
// Start the request
const promise = axios.get("/api/search", {
params: { q: query },
signal: controller.signal,
});
// Cancel after 3 seconds if still pending
const timeoutId = setTimeout(() => controller.abort(), 3000);
try {
const response = await promise;
clearTimeout(timeoutId);
return response.data;
} catch (error) {
if (axios.isCancel(error)) {
console.log("Request was canceled");
} else {
throw error;
}
}
}Debounced search with cancellation
let activeController = null;
async function debouncedSearch(query) {
// Cancel previous request
if (activeController) {
activeController.abort();
}
activeController = new AbortController();
try {
const response = await axios.get("/api/search", {
params: { q: query },
signal: activeController.signal,
});
return response.data;
} catch (error) {
if (!axios.isCancel(error)) throw error;
return null;
}
}Concurrent Requests
async function loadDashboard(userId) {
const [profileRes, projectsRes, notificationsRes] = await Promise.all([
axios.get(`/api/users/${userId}`),
axios.get(`/api/users/${userId}/projects`),
axios.get(`/api/notifications`),
]);
return {
profile: profileRes.data,
projects: projectsRes.data,
notifications: notificationsRes.data,
};
}File Upload With Progress
async function uploadFile(file, onProgress) {
const formData = new FormData();
formData.append("file", file);
const response = await axios.post("/api/upload", formData, {
headers: { "Content-Type": "multipart/form-data" },
onUploadProgress: (progressEvent) => {
const percent = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
onProgress(percent);
},
});
return response.data;
}
// Usage
uploadFile(selectedFile, (percent) => {
progressBar.style.width = `${percent}%`;
progressBar.textContent = `${percent}%`;
});Unlike the native Fetch API, Axios supports upload progress tracking natively. See uploading files via JS Fetch API complete guide for the Fetch-based workaround.
Axios vs Fetch Comparison
| Feature | Axios | Fetch |
|---|---|---|
| JSON auto-parse | Yes | Manual .json() call |
| Auto reject on HTTP error | Yes (4xx/5xx) | No (only network errors) |
| Request/response interceptors | Built-in | Manual wrapper needed |
| Upload progress | onUploadProgress | Not supported natively |
| Timeout | timeout config | Manual AbortController |
| XSRF protection | Built-in | Manual |
| Browser support | IE11+ (with polyfill) | Modern browsers only |
| Bundle size | ~13KB (minified + gzipped) | 0KB (built-in) |
| Node.js support | Yes | Node 18+ (experimental) |
| Cancel requests | AbortController + isCancel | AbortController |
Reusable API Client
import axios from "axios";
class ApiClient {
constructor(baseURL, options = {}) {
this.client = axios.create({
baseURL,
timeout: options.timeout || 10000,
headers: {
"Content-Type": "application/json",
...options.headers,
},
});
}
setAuth(token) {
this.client.defaults.headers.common["Authorization"] = `Bearer ${token}`;
}
clearAuth() {
delete this.client.defaults.headers.common["Authorization"];
}
async get(url, params = {}) {
const response = await this.client.get(url, { params });
return response.data;
}
async post(url, data) {
const response = await this.client.post(url, data);
return response.data;
}
async put(url, data) {
const response = await this.client.put(url, data);
return response.data;
}
async delete(url) {
const response = await this.client.delete(url);
return response.data;
}
}
const api = new ApiClient("https://api.example.com/v2");
api.setAuth(localStorage.getItem("token"));
export default api;Rune AI
Key Insights
- Automatic JSON transforms: Axios stringifies request bodies and parses response bodies without manual steps
- HTTP error rejection: Unlike Fetch, Axios rejects promises for 4xx/5xx responses; no need to check
response.ok - Three error categories:
error.response(server error),error.request(network error), and setup error (config issue) cover every failure scenario - Instances isolate configuration: Create separate Axios instances for different APIs with unique base URLs, headers, and timeouts
- Upload progress built in: The
onUploadProgresscallback provides real-time upload tracking without XMLHttpRequest workarounds
Frequently Asked Questions
When should I use Axios instead of Fetch?
Does Axios work in Node.js?
Is Axios still relevant in 2026?
How do I handle 401 Unauthorized responses globally?
Can I use Axios with TypeScript?
Conclusion
Axios simplifies HTTP requests with automatic JSON parsing, HTTP error rejection, configurable instances, and upload progress tracking. Its structured error object with error.response, error.request, and setup error categories makes debugging easier than Fetch's single-layer error handling. For advanced patterns like auth token injection and retry logic, see axios interceptors in JavaScript complete guide. For the event loop mechanics behind async HTTP calls, see the JS event loop architecture complete guide.
More in this topic
OffscreenCanvas API in JS for UI Performance
Master the OffscreenCanvas API to offload rendering from the main thread. Covers worker-based 2D and WebGL rendering, animation loops inside workers, bitmap transfer, double buffering, chart rendering pipelines, image processing, and performance measurement strategies.
Advanced Web Workers for High Performance JS
Master Web Workers for truly parallel JavaScript execution. Covers dedicated and shared workers, structured cloning, transferable objects, SharedArrayBuffer with Atomics, worker pools, task scheduling, Comlink RPC patterns, module workers, and performance profiling strategies.
JavaScript Macros and Abstract Code Generation
Master JavaScript code generation techniques for compile-time and runtime metaprogramming. Covers AST manipulation, Babel plugin authorship, tagged template literals as macros, code generation pipelines, source-to-source transformation, compile-time evaluation, and safe eval alternatives.