Getting started
Installation
# Package managers
npm install axios
yarn add axios
pnpm add axios
<!-- CDN -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
Import
// ES6
import axios from "axios";
// CommonJS
const axios = require("axios");
Quick example
// GET request
const { data } = await axios.get("/users");
// POST request
await axios.post("/users", {
name: "John",
email: "john@example.com",
});
Basic requests
HTTP methods
// GET
const { data } = await axios.get("/users");
// POST
await axios.post("/users", {
name: "John",
email: "john@example.com",
});
// PUT
await axios.put("/users/1", {
name: "Updated",
});
// PATCH
await axios.patch("/users/1", {
email: "new@email.com",
});
// DELETE
await axios.delete("/users/1");
Full config syntax
await axios({
method: "post",
url: "/users",
data: { name: "John" },
});
Response destructuring
// Get only data
const { data } = await axios.get("/users");
// Get status and headers
const { status, headers, data } = await axios.get("/users");
Request config
Config options
axios({
method: "post", // HTTP method
url: "/user/12345", // Request URL
baseURL: "https://api.example.com",
headers: {
Authorization: "Bearer token",
"Content-Type": "application/json",
},
params: { ID: 12345 }, // URL parameters
data: { firstName: "Fred" }, // Request body
timeout: 1000, // Milliseconds
withCredentials: false, // Send cookies
responseType: "json", // Response type
maxRedirects: 5, // Max redirects
validateStatus: (status) => status < 500,
});
Common options
| Option | Description | Default |
|---|---|---|
baseURL |
Base URL prefix | - |
headers |
Request headers | {} |
params |
URL query params | - |
data |
Request body | - |
timeout |
Request timeout (ms) | 0 |
withCredentials |
Send cookies | false |
responseType |
Response format | 'json' |
validateStatus |
Status validator | status >= 200 && status < 300 |
Response types
responseType: "arraybuffer"; // ArrayBuffer
responseType: "document"; // DOM document
responseType: "json"; // JSON (default)
responseType: "text"; // String
responseType: "stream"; // Node.js stream
responseType: "blob"; // Blob
Response schema
Response object
{
data: {}, // Response body
status: 200, // HTTP status code
statusText: 'OK', // Status message
headers: {}, // Response headers (lowercase)
config: {}, // Original request config
request: {} // XMLHttpRequest / http.ClientRequest
}
Headers are always lowercase:
response.headers["content-type"]; // Correct
response.headers["Content-Type"]; // Won't work
Creating instances
Custom instance
const api = axios.create({
baseURL: "https://api.example.com",
timeout: 1000,
headers: { "X-Custom-Header": "foobar" },
});
// Use like axios
api.get("/user/12345");
Instance defaults
const api = axios.create({
baseURL: "https://api.example.com",
});
// Update defaults
api.defaults.headers.common["Authorization"] = AUTH_TOKEN;
api.defaults.timeout = 2500;
Config precedence
// 1. Library defaults (lowest priority)
axios.defaults.timeout = 1000;
// 2. Instance defaults
const api = axios.create({ timeout: 2000 });
// 3. Request config (highest priority)
api.get("/users", { timeout: 3000 });
Interceptors
Request interceptor
axios.interceptors.request.use(
(config) => {
// Modify config before request
config.headers.Authorization = "Bearer " + getToken();
return config;
},
(error) => {
// Handle request error
return Promise.reject(error);
},
);
Response interceptor
axios.interceptors.response.use(
(response) => {
// Process successful response
return response;
},
(error) => {
// Handle response error
if (error.response?.status === 401) {
// Redirect to login
}
return Promise.reject(error);
},
);
Remove interceptor
// Store interceptor ID
const id = axios.interceptors.request.use(fn);
// Remove later
axios.interceptors.request.eject(id);
Instance interceptors
const api = axios.create();
api.interceptors.request.use((config) => {
// Only affects this instance
return config;
});
Error handling
Error types
try {
await axios.get("/user/12345");
} catch (error) {
if (error.response) {
// Server responded with non-2xx
console.log(error.response.status);
console.log(error.response.data);
console.log(error.response.headers);
} else if (error.request) {
// No response received
console.log(error.request);
} else {
// Request setup error
console.log(error.message);
}
}
Type guard
if (axios.isAxiosError(error)) {
// TypeScript: error is AxiosError
console.log(error.response?.status);
console.log(error.code);
}
Serialize error
const errorJson = error.toJSON();
// Returns serializable error object
Custom status validation
axios.get("/user", {
validateStatus: (status) => {
// Accept 404 as success
return status < 500;
},
});
Authentication
Bearer token (global)
axios.defaults.headers.common["Authorization"] = `Bearer ${token}`;
Per request
axios.get("/user", {
headers: {
Authorization: `Bearer ${token}`,
},
});
Basic auth
axios.get("/user", {
auth: {
username: "jane",
password: "s3cret",
},
});
Cookies cross-origin
axios.get("https://api.example.com/data", {
withCredentials: true,
});
Cancellation
AbortController
const controller = new AbortController();
axios.get("/user/12345", {
signal: controller.signal,
});
// Cancel request
controller.abort();
Timeout via AbortSignal
// Auto-cancel after 5 seconds
axios.get("/user", {
signal: AbortSignal.timeout(5000),
});
CancelToken is deprecated (v0.22.0+). Use AbortController instead.
FormData & file uploads
FormData upload
const formData = new FormData();
formData.append("file", fileInput.files[0]);
formData.append("name", "Document");
axios.post("/upload", formData);
Shorthand syntax
// Automatically creates FormData
axios.postForm("/upload", {
file: fileInput.files[0],
name: "Document",
});
Progress tracking
axios.post("/upload", formData, {
onUploadProgress: (progressEvent) => {
const percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total,
);
console.log(`${percentCompleted}%`);
},
});
Download progress
axios.get("/file.zip", {
onDownloadProgress: (progressEvent) => {
const percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total,
);
},
});
Concurrent requests
Promise.all
const [users, permissions] = await Promise.all([
axios.get("/users"),
axios.get("/permissions"),
]);
console.log(users.data);
console.log(permissions.data);
Promise.allSettled
const results = await Promise.allSettled([
axios.get("/users"),
axios.get("/permissions"),
]);
results.forEach((result) => {
if (result.status === "fulfilled") {
console.log(result.value.data);
} else {
console.log(result.reason);
}
});
TypeScript
Type response data
import axios, { AxiosResponse } from "axios";
interface User {
id: number;
name: string;
}
// Typed response
const { data } = await axios.get<User>("/user/1");
console.log(data.name); // TypeScript knows this is a string
Error type guard
import { AxiosError } from "axios";
try {
await axios.get("/user");
} catch (error) {
if (axios.isAxiosError(error)) {
const axiosError: AxiosError = error;
console.log(axiosError.response?.status);
console.log(axiosError.code);
}
}
Custom instance type
import axios, { AxiosInstance } from "axios";
const api: AxiosInstance = axios.create({
baseURL: "https://api.example.com",
});
Generic response type
interface ApiResponse<T> {
success: boolean;
data: T;
}
const response = await axios.get<ApiResponse<User>>("/user/1");
console.log(response.data.data.name);
Config defaults
Global defaults
// Base URL for all requests
axios.defaults.baseURL = "https://api.example.com";
// Common headers
axios.defaults.headers.common["Authorization"] = AUTH_TOKEN;
// POST headers
axios.defaults.headers.post["Content-Type"] =
"application/x-www-form-urlencoded";
Precedence: library defaults < instance defaults < request config
Gotchas
Common pitfalls
- ⚠️ Global defaults affect ALL instances — Use
axios.create()for isolated config - ⚠️
timeoutonly covers response, not connection — Combine with AbortController for full timeout control - ⚠️ CancelToken is deprecated (v0.22.0+) — Use AbortController instead
- ⚠️ Response headers are always lowercase — Use
response.headers['content-type'], not'Content-Type' - ⚠️
validateStatusdefault only accepts 2xx — Override for custom status handling - ⚠️
statusTextmay be empty in HTTP/2 — Don't rely on it for error messages - ⚠️
null/undefinedparams are silently ignored — Use empty string if needed in query string
Also see
- Axios Documentation (axios-http.com)
- Request Config Reference (axios-http.com)
- Interceptors Guide (axios-http.com)
- Error Handling (axios-http.com)
- Cancellation (axios-http.com)
- GitHub Repository (github.com)