Skip to content

Axios Instance and Configuration — Complete Guide

DodaTech Updated 2026-06-28 5 min read

In this tutorial, you'll learn about Axios instance configuration. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

Axios instances are custom configurations that let you create pre-configured HTTP clients with default settings, reducing repetitive code across your application's API calls.

What You'll Learn

By the end of this tutorial, you'll create custom Axios instances, set default configurations, merge per-request configs, organize API modules, and share instances across components.

Why It Matters

Without instances, every API call repeats the same base URL, headers, and timeout settings. Instances centralize configuration: change the base URL in one place and every request updates. This is essential for scaling applications.

Real-World Use

Durga Antivirus Pro creates separate Axios instances for different services: one for the threat database API (base URL, 5s timeout, auth headers) and another for the update server (longer timeout, progress tracking). Each instance has its own interceptors and defaults.

Where This Fits in Your Learning Path

flowchart LR
    A["Getting Started"] --> B["**Instance & Config**"]
    B --> C["Request Configuration"]
    C --> D["Response Schema"]
    D --> E["Axios Advanced"]
    style B fill:#f97316,stroke:#c2410c,color:#fff
    style A fill:#e5e7eb,stroke:#9ca3af,color:#374151
    style E fill:#22c55e,stroke:#16a34a,color:#fff

Creating an Instance

Use axios.create() to create a new instance with default configuration.

import axios from 'axios'

const api = axios.create({
  baseURL: 'https://api.example.com/v1',
  timeout: 5000,
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  }
})

// Now use `api` like you would use `axios`
const response = await api.get('/users')

Expected output: Requests from the api instance default to https://api.example.com/v1/users with a 5-second timeout and JSON content type headers.

Setting Defaults on Default Axios

You can also set global defaults that apply to all requests from the standard axios object.

axios.defaults.baseURL = 'https://api.example.com'
axios.defaults.headers.common['Authorization'] = 'Bearer token123'
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
axios.defaults.timeout = 10000

Expected output: Every axios request now includes the base URL, auth header, and 10-second timeout by default.

Merging Config Per-Request

Instance defaults merge with per-request configuration. Per-request values override instance defaults.

const api = axios.create({ baseURL: 'https://api.example.com' })

// Override timeout for a specific slow endpoint
const response = await api.get('/reports/detailed', {
  timeout: 30000,
  headers: {
    'X-Request-Priority': 'high'
  }
})

console.log(response.data)

Expected output: The request uses the instance's baseURL but overrides the timeout to 30 seconds. The additional X-Request-Priority header is merged with instance defaults.

Organizing API Modules

Create separate instances for different API domains, each with its own base config.

// api/users.js
export const usersApi = axios.create({
  baseURL: 'https://api.example.com/users',
  timeout: 3000
})

// api/products.js
export const productsApi = axios.create({
  baseURL: 'https://api.example.com/products',
  timeout: 5000
})

// Import and use in components
import { usersApi } from './api/users'
const users = await usersApi.get('/')
const user = await usersApi.get('/123')

Expected output: Each API module has its own base URL and timeout. The / maps to the full base URL, /123 maps to https://api.example.com/users/123.

Instance Interceptors

Attach interceptors to specific instances for targeted request/response processing.

const api = axios.create({ baseURL: 'https://api.example.com' })

// Request interceptor specific to this instance
api.interceptors.request.use(config => {
  config.headers['X-Request-ID'] = crypto.randomUUID()
  return config
})

// Response interceptor specific to this instance
api.interceptors.response.use(
  response => response.data,
  error => {
    console.error('API Error:', error.config.url, error.message)
    return Promise.reject(error)
  }
)

const data = await api.get('/users')  // returns response.data directly

Expected output: Every request from this instance gets a unique request ID header. Response interceptor unwraps .data automatically and logs errors.

Common Mistakes

1. Using the default axios for everything

Without instances, changing the base URL requires updating every API call. Use instances to centralize configuration.

2. Forgetting that instance defaults merge, not replace

Per-request config objects merge with instance defaults. Setting headers in a request adds to instance headers rather than replacing them.

3. Creating a new instance for every component

Create instances once and export them as singletons from modules. Creating instances in every component is wasteful and breaks centralization.

4. Not handling instance-specific errors

Interceptors attached to an instance only handle requests from that instance. Global interceptors handle all requests.

5. Mixing axios.defaults with instance defaults

axios.defaults affects the global axios object. Instance defaults only affect that instance. They do not interfere with each other.

Practice Questions

  1. How do you create a custom Axios instance? Use axios.create({ baseURL: '...', timeout: 5000, headers: {} }).

  2. What happens when you set both axios.defaults and instance defaults? They are separate. The global defaults apply to the main axios object. Instance defaults apply only to that instance.

  3. Can instances have their own interceptors? Yes. Each instance can have independent request and response interceptors.

  4. How does per-request config merge with instance defaults? Per-request config is merged on top of instance defaults. Properties like headers are deep-merged.

  5. Why use multiple instances? Each instance represents a different API service with its own base URL, timeout, auth, and interceptor requirements.

Challenge

Create three Axios instances: one for authentication endpoints (auth token management), one for data CRUD (main API), and one for file uploads (long timeout, progress tracking). Each should have appropriate defaults and interceptors.

FAQ

Can I change instance defaults after creation?

Yes. Modify instance.defaults object: api.defaults.timeout = 10000. Changes apply to subsequent requests.

Do interceptors run in the order they are added?

Request interceptors run in reverse order (last added runs first). Response interceptors run in the order added.

Can I remove interceptors from an instance?

Yes. Store the interceptor ID returned by .use() and call .eject(id) to remove it.

How do I share an instance across my application?

Create the instance in a module and export it. Import the same instance wherever needed.

Can instances have different adapters?

Yes. Each instance can have its own adapter, useful for testing with mock adapters or using HTTP/2 in Node.js.


Mini Project

Build an API client module that creates three pre-configured instances for a typical application: authApi (refresh tokens, short timeout), mainApi (CRUD operations, standard config), and uploadApi (no timeout, multipart headers, progress callbacks).

// api/client.js
import axios from 'axios'

export const authApi = axios.create({
  baseURL: 'https://api.example.com/auth',
  timeout: 3000,
  headers: { 'Content-Type': 'application/json' }
})

authApi.interceptors.response.use(
  response => response.data,
  async error => {
    if (error.response?.status === 401) {
      // Attempt token refresh logic here
      console.log('Token expired, redirect to login')
    }
    return Promise.reject(error)
  }
)

export const mainApi = axios.create({
  baseURL: 'https://api.example.com/v2',
  timeout: 5000,
  headers: { 'Content-Type': 'application/json' }
})

mainApi.interceptors.request.use(config => {
  const token = localStorage.getItem('accessToken')
  if (token) config.headers.Authorization = `Bearer ${token}`
  return config
})

export const uploadApi = axios.create({
  baseURL: 'https://api.example.com/uploads',
  timeout: 0, // no timeout for uploads
  headers: { 'Content-Type': 'multipart/form-data' }
})

What's Next

Dive deeper into request configuration:

Tutorial What You'll Learn
Request Configuration Full request config options, params, and customization
Response Schema Understanding the full response object structure

Related topics: JavaScript module patterns, REST API design principles.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro