
Customizing headers on a per-request basis with Axios is simpler and essential when you need fine-grained control over your HTTP communication. It’s a common scenario when dealing with APIs that require different authentication tokens, content types, or other metadata depending on the endpoint or the user context.
To set custom headers for an individual request, you simply pass a headers object inside the config parameter of your Axios method. This overrides or supplements the default headers for that specific call without affecting others.
axios.get('/user/profile', {
headers: {
'Authorization': 'Bearer your-access-token',
'Accept-Language': 'en-US'
}
})
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Request failed:', error);
});
Notice how you can specify any header you want, not just authorization. This approach works identically for POST, PUT, or any HTTP method:
axios.post('/data/upload', {
name: 'Eric',
role: 'developer'
}, {
headers: {
'Content-Type': 'application/json',
'X-Custom-Header': 'custom-value'
}
})
.then(response => console.log('Upload successful'))
.catch(error => console.error('Upload failed:', error));
If you need conditional headers—say, switching tokens based on user login status—your config object can be dynamically constructed just before the call:
const token = user.isLoggedIn ? user.token : null;
const config = {
headers: {
...(token && { 'Authorization': Bearer ${token} }),
'Cache-Control': 'no-cache'
}
};
axios.get('/private/data', config)
.then(res => console.log(res.data))
.catch(err => console.error(err));
This pattern leverages JavaScript’s spread operator to elegantly include the Authorization header only when a token exists, keeping your requests clean and explicit.
Remember, headers set this way are only for the current request. Axios merges these with any instance or global defaults, enabling you to override only what’s necessary without repeating every header.
For cases where you want to attach headers dynamically to many requests but not all, consider writing a function that returns the config object instead of hardcoding it inline. This keeps your code DRY and easy to maintain.
function makeAuthConfig(token) {
return {
headers: {
'Authorization': Bearer ${token},
'Accept': 'application/json'
}
};
}
axios.get('/user/data', makeAuthConfig(user.token))
.then(res => console.log(res.data));
Using this approach, you can centralize header logic and update it in one place without hunting down every request call. It’s a small pattern that pays off when your project scales and your header requirements multiply.
Another handy tip: if you’re debugging header issues, logging the request config before sending can save hours. Axios exposes the config object in the error response, but sometimes a manual console.log of your headers helps catch subtle typos or missing values early.
Axios also respects custom headers’ case sensitivity as per HTTP standards, but consistent casing (usually Pascal-Case or hyphen-separated lowercase) prevents headaches with some servers that might be picky. So stick to known conventions like Content-Type or Authorization.
One last note on headers with credentials: if you need to send cookies or HTTP authentication with your request, setting the withCredentials flag in the config is necessary, but it’s separate from headers:
axios.get('/user/session', {
headers: {
'X-Requested-With': 'XMLHttpRequest'
},
withCredentials: true
})
.then(res => console.log(res.data));
Headers and credentials control different aspects of the HTTP request, so don’t conflate them. Setting withCredentials ensures cookies are sent along with the request, which some APIs use for session management instead of tokens in headers.
By mastering per-request headers in Axios, you avoid the trap of monolithic configurations that don’t fit all use cases, giving you flexibility and precision where it counts. Now, let’s move on to configuring default headers across Axios instances for a broader, reusable approach—
Silkland Certified HDMI 2.1 Cable, [4K@240Hz 144Hz 120Hz, 8K@60Hz] 1440P Ultra High Speed HDMI Cable 48Gbps (Upgrade Braided), HDR10+, eARC, HDCP 2.3, Compatible for Xbox/PS5/PS4/Roku TV-6.6ft
$8.48 (as of June 2, 2026 22:39 GMT +00:00 - More infoProduct prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on [relevant Amazon Site(s), as applicable] at the time of purchase will apply to the purchase of this product.)Configuring default headers for all Axios instances
When you find yourself repeatedly setting the same headers for multiple requests, managing them individually becomes tedious and error-prone. Axios lets you configure default headers on an instance level, which means every request made through that instance inherits those headers unless explicitly overridden.
Creating an Axios instance with default headers is as simple as calling axios.create() and passing a config object. This config can include a headers property where you specify any headers that should be common across requests:
const apiClient = axios.create({
baseURL: 'https://api.example.com',
headers: {
'Authorization': 'Bearer your-default-token',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
Once this instance is configured, you can use it throughout your app, confident that these headers will be attached automatically. This reduces duplication and centralizes your configuration:
apiClient.get('/users')
.then(response => console.log(response.data))
.catch(error => console.error(error));
apiClient.post('/posts', { title: 'Hello World' })
.then(response => console.log('Post created'))
.catch(error => console.error(error));
Default headers can be modified or extended after instance creation by directly mutating the defaults.headers object. This is useful when your token or other header values change dynamically during runtime:
apiClient.defaults.headers['Authorization'] = Bearer ${newToken};
Note that Axios organizes default headers by HTTP method, so if you want to set a default header for all methods, set it under apiClient.defaults.headers.common. For example:
apiClient.defaults.headers.common['X-Custom-Header'] = 'my-custom-value';
If you want to target specific methods, you can do so as well:
apiClient.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
This granularity allows you to optimize headers according to the HTTP method semantics without repeating yourself.
Keep in mind that default headers set on an Axios instance serve as the baseline. Any headers specified in individual request configs will override these defaults for that request only. This layered approach gives you a powerful way to mix global and local header settings.
If your application requires multiple API endpoints with different default headers, create multiple Axios instances, each tailored with its own baseURL and headers. This avoids the pitfalls of a one-size-fits-all client and keeps your code organized:
const authClient = axios.create({
baseURL: 'https://auth.example.com',
headers: {
'Authorization': 'Bearer auth-token',
'Accept': 'application/json'
}
});
const dataClient = axios.create({
baseURL: 'https://data.example.com',
headers: {
'X-API-Key': 'data-api-key',
'Content-Type': 'application/json'
}
});
Using these instances, you maintain clear separation of concerns, reducing bugs caused by header leakage or incorrect authentication.
Lastly, if you want to globally set default headers for all Axios requests without creating a new instance, you can modify axios.defaults.headers directly. This affects every request made with the default Axios import:
axios.defaults.headers.common['Authorization'] = 'Bearer global-token'; axios.defaults.headers.post['Content-Type'] = 'application/json';
However, this approach is less flexible and can lead to unintended side effects in larger applications where different parts require different headers. Prefer instances for scalable, maintainable codebases.
