Skip to content
devcards.space
FrontendTools

What is Axios? A Practical HTTP Client for Modern Apps

Make HTTP requests with Axios — a Promise-based client more powerful than fetch. Walkthrough covers instances, interceptors, error handling and query params.

9 minute read
Axios infographic showing GET, POST, instance, interceptor and error handling across 12 sections

Axios is a Promise-based HTTP client that runs in both the browser and Node.js — for years the industry standard. It fills in fetch's gaps with automatic JSON parsing, request/response interceptors, an instance pattern and richer error handling, making the API layer of modern apps faster to ship. This guide walks through how to install Axios and configure it in real-world scenarios.

What is Axios?

A Promise-based HTTP client that works in both the browser and Node.js. Compared to fetch it adds automatic JSON parsing, shortcuts for GET/POST/PUT/DELETE and a more robust error model. It's one of the most popular choices for an app's API layer.

  • Promise-based — async/await friendly
  • Single API for browser + Node.js
  • Automatic JSON conversion
  • Plays nicely with REST APIs

Why Use Axios?

fetch is standard, but as projects grow you end up repeating configuration. Axios centralizes that configuration through instances and interceptors.

  • Cleaner syntax — short and readable
  • Automatic JSON parsing
  • Request/response interceptors
  • Built-in timeout management
  • Great fit for REST APIs

Installation

Add it with one command as a runtime dependency.

bash
npm install axios

Basic GET Request

axios.get returns a single Promise; response.data already contains parsed data.

api/users.ts
ts
import axios from "axios";

const fetchUsers = async () => {
  const res = await axios.get("/api/users");
  return res.data;
};

POST Request

The second argument is the body; Axios serializes the object to JSON and sets the right Content-Type header.

api/users.ts
ts
await axios.post("/api/users", {
  name: "Ada",
  email: "ada@dev.com",
});

GET with TypeScript

Axios accepts generic types. That makes response.data the model you expect instead of any, giving your components autocomplete and type safety.

api/users.ts
ts
import axios from "axios";

type User = {
  id: string;
  name: string;
  email: string;
};

export async function getUsers() {
  const res = await axios.get<User[]>("/api/users");
  return res.data;
}

const users = await getUsers();
users[0].email; // string

POST with TypeScript

Type the request body and response model separately. This is especially useful for forms, auth flows and create/update screens where field names drift easily.

api/users.ts
ts
import { api } from "@/lib/api";

type CreateUserInput = {
  name: string;
  email: string;
};

type User = CreateUserInput & {
  id: string;
};

export async function createUser(input: CreateUserInput) {
  const res = await api.post<User>("/users", input);
  return res.data;
}

await createUser({
  name: "Ada",
  email: "ada@dev.com",
});

Axios Instance (IMPORTANT)

Collect repeated settings into an instance: baseURL, timeout, common headers. Using a single instance everywhere removes configuration drift.

lib/api.ts
ts
import axios from "axios";

export const api = axios.create({
  baseURL: "https://example.com/api",
  timeout: 5000,
  headers: { Accept: "application/json" },
});

api.get("/users");

Typed API Layer

Instead of spreading raw axios calls across components, write small typed functions. This shape plugs cleanly into React Query, Zustand or server actions.

services/users.ts
ts
import { api } from "@/lib/api";

type ApiResponse<T> = {
  data: T;
  message?: string;
};

type User = {
  id: string;
  name: string;
  role: "admin" | "editor" | "viewer";
};

export async function getUser(id: string) {
  const res = await api.get<ApiResponse<User>>(`/users/${id}`);
  return res.data.data;
}

Interceptors

Use interceptors to globally hook into the request/response lifecycle. They're perfect for attaching tokens, central error handling and logging.

lib/api.ts
ts
api.interceptors.request.use((config) => {
  config.headers.Authorization = `Bearer ${getToken()}`;
  return config;
});

api.interceptors.response.use(
  (response) => response,
  (error) => {
    console.error(error);
    return Promise.reject(error);
  }
);

Error Handling

Unlike fetch, Axios automatically rejects on 4xx/5xx codes. Catch with try/catch and inspect error.response for details.

ts
type ApiError = {
  message: string;
  code?: string;
};

try {
  const res = await api.get("/users");
} catch (err) {
  if (axios.isAxiosError<ApiError>(err)) {
    console.log(err.response?.status, err.response?.data);
  }
}

Request Config

You can override settings on a per-request basis: headers, timeout, params, withCredentials and more.

ts
await api.get("/users", {
  headers: { "X-Trace-Id": "abc" },
  timeout: 2000,
  withCredentials: true,
});

Query Params

The params field accepts an object and appends ?key=value to the URL. For complex shapes you can supply a paramsSerializer.

ts
await api.get("/posts", {
  params: { page: 1, limit: 10 },
});
// → /posts?page=1&limit=10

Use Cases

Where Axios shines:

  • Consuming REST APIs
  • Authentication flows (token interceptor)
  • Typed API services with TypeScript
  • Modern frontend frameworks
  • Working alongside React Query

Summary

Axios is a strong, flexible library that simplifies HTTP requests. Compared to fetch it offers cleaner syntax, more reliable error handling and better scalability. From small scripts to enterprise apps, it remains the go-to HTTP client of the modern JavaScript ecosystem.

Frequently Asked Questions

Common questions about this topic.

Axios or fetch?

fetch is built-in; Axios adds extras. For tiny projects fetch is enough — but when you need interceptors, instances and cleaner error handling, Axios pulls ahead.

How big is Axios?

Roughly ~13kB gzip. With tree-shaking the impact is minimal. For performance-critical mobile work fetch may be preferable; for most web apps it's negligible.

Does Axios work with SSR?

Yes — same API on Node.js. In frameworks like Next.js you can use it for server-side data fetching. For cookie-based auth, configure withCredentials or pass custom headers.

How do I do token refresh?

Catch 401s in the response interceptor, call your refresh endpoint, then retry the original request with the new token. A small state object queues pending requests during refresh.

Can I use Axios with React Query?

Yes — that's a common pattern. Axios handles the HTTP layer; React Query handles cache/state. Just call axios.get inside your queryFn.

Other infographics on connected topics.

Discover more developer infographics

Visit the homepage so you don't miss new content.

See all infographics