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.

JavaScriptintermediate
15 min read

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

bashbash
# npm
npm install axios
 
# yarn
yarn add axios
 
# CDN (browser)
# <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
javascriptjavascript
// 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

javascriptjavascript
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

PropertyDescription
dataResponse body, auto-parsed from JSON
statusHTTP status code (200, 404, etc.)
statusTextHTTP status message ("OK", "Not Found")
headersResponse headers (lowercase keys)
configThe request configuration that was used
requestThe underlying XMLHttpRequest (browser) or http.ClientRequest (Node.js)

GET With Query Parameters

javascriptjavascript
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

javascriptjavascript
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

javascriptjavascript
// 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.

javascriptjavascript
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 Typeerror.responseerror.requestCause
HTTP error (4xx/5xx)PresentPresentServer returned error status
Network errorundefinedPresentNo response received (offline, DNS, CORS)
Setup errorundefinedundefinedInvalid config or canceled request

Creating an Axios Instance

javascriptjavascript
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

javascriptjavascript
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

javascriptjavascript
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

javascriptjavascript
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

javascriptjavascript
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

javascriptjavascript
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

FeatureAxiosFetch
JSON auto-parseYesManual .json() call
Auto reject on HTTP errorYes (4xx/5xx)No (only network errors)
Request/response interceptorsBuilt-inManual wrapper needed
Upload progressonUploadProgressNot supported natively
Timeouttimeout configManual AbortController
XSRF protectionBuilt-inManual
Browser supportIE11+ (with polyfill)Modern browsers only
Bundle size~13KB (minified + gzipped)0KB (built-in)
Node.js supportYesNode 18+ (experimental)
Cancel requestsAbortController + isCancelAbortController

Reusable API Client

javascriptjavascript
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

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 onUploadProgress callback provides real-time upload tracking without XMLHttpRequest workarounds
RunePowered by Rune AI

Frequently Asked Questions

When should I use Axios instead of Fetch?

Use Axios when you need interceptors, automatic error handling for HTTP status codes, upload progress tracking, or broader browser support. Use Fetch for simple requests or when minimizing bundle size is critical.

Does Axios work in Node.js?

Yes. Axios uses `XMLHttpRequest` in the browser and the `http`/`https` modules in Node.js. The API is identical in both environments.

Is Axios still relevant in 2026?

Yes. While Fetch has improved significantly, Axios still offers a better developer experience for complex applications, especially with interceptors and automatic transforms. Many production codebases rely on Axios.

How do I handle 401 Unauthorized responses globally?

Use response interceptors to catch 401 errors and redirect to login or refresh tokens. See [axios interceptors in JavaScript complete guide](/tutorials/programming-languages/javascript/axios-interceptors-in-javascript-complete-guide) for implementation details.

Can I use Axios with TypeScript?

Yes. Axios ships with TypeScript declarations. Use `axios.get<User>("/api/user")` to type the response data.

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.