When building Next.js applications that rely on APIs, developers often face repetitive tasks like adding authentication headers to every request, handling errors in every component, and managing data transformation in multiple places. These repeated patterns make the code harder to maintain and lead to bugs if something changes, like a new auth flow or an API version update.
Axios interceptors solve this problem by letting you define global logic for every request or response. This makes it easier to keep your code clean and avoid duplication.
This article explains what Axios interceptors are, why they’re valuable in Next.js projects, and how to implement them.
What is an Axios Interceptor?
Axios is a popular JavaScript library for making HTTP requests, both in the browser and in Node.js. In a Next.js project, you use Axios to talk to APIs and fetch data for your pages and components.
Axios interceptors are functions that Axios calls automatically before sending a request or after receiving a response. They let you add headers, handle errors, or change the response in one place.
- Request interceptors: These run before the request is sent, letting you add headers like authentication tokens or modify parameters.
- Response interceptors: These run after a response is received, so you can catch errors, refresh tokens, or transform data before it’s used in your app.
Why Use Interceptors in Next.js?
Using Axios interceptors in Next.js is especially helpful because data fetching can happen on the server side (for SEO or faster load times) or on the client side (for user interactions). Interceptors help you keep everything consistent, no matter where the request is made.
- Add authentication tokens automatically: Instead of repeating this logic everywhere, you can do it once in the request interceptor.
- Handle errors globally: Show a consistent error message or log errors from one spot.
- Transform API responses consistently: Change data shapes or convert field names before your components use them.
- Secure sensitive requests: Attach CSRF tokens or other security headers so your API calls are protected.
How to Set Up Axios in Next.js
Here’s how to create a reusable Axios instance you’ll use throughout your Next.js project.
- Install Axios: Use the following code to install Axios.
npm install axios
- Create a reusable Axios instance: Use axios.create() to set your base URL and any default settings. Store your API base URLs in environment variables so you can switch between dev, staging, and production without changing code.
For example:
// lib/axiosInstance.js import axios from 'axios'; const axiosInstance = axios.create({ baseURL: process.env.NEXT_PUBLIC_API_BASE_URL, timeout: 10000 }); export default axiosInstance;
- Use environment variables for base URLs: Store your API base URLs in .env files to switch between development, staging, and production without changing code.
How to Implement Request Interceptors in Next.js
Request interceptors let you set common logic for every request before it’s sent. They’re great for adding tokens, custom headers, or small tweaks to every request.
- Add authentication headers for client-side: Use localStorage or cookies to get your token and add it to each request’s Authorization header.
- Add authentication headers for server-side: In server-side functions (like getServerSideProps or API routes), read the token from cookies or environment variables and add it to requests.
- Attach custom headers for third-party APIs: Some APIs need extra headers, like an API key or version. Use an interceptor to add these automatically to every request.
For example:
// lib/axiosInstance.js import axios from 'axios'; const axiosInstance = axios.create({ baseURL: process.env.NEXT_PUBLIC_API_BASE_URL, timeout: 10000 }); // Add request interceptor axiosInstance.interceptors.request.use( (config) => { // For client-side requests if (typeof window !== 'undefined') { const token = localStorage.getItem('access_token'); if (token) { config.headers.Authorization = `Bearer ${token}`; } } // For server-side requests (like in getServerSideProps) // You might set headers here with server-only environment variables or cookies. // For third-party APIs // config.headers['X-API-KEY'] = process.env.NEXT_PUBLIC_API_KEY; return config; }, (error) => Promise.reject(error) ); export default axiosInstance;
This setup ensures that every request uses the right headers, whether it’s a client-side request or a server-side request.
How to Implement Response Interceptors in Next.js
Response interceptors help you catch errors and clean up data consistently.
- Handle global errors: Catch errors in one place and show helpful messages or logs.
- Automatically refresh tokens: If your token expires (like a 401 error), interceptors can handle refreshing it and retry the request.
- Transform response data: Change the response (like converting snake_case to camelCase) so your front-end components don’t have to.
For example,
// lib/axiosInstance.js axiosInstance.interceptors.response.use( (response) => response, (error) => { if (error.response?.status === 401) { // Example: refresh token logic or redirect to login console.error('Unauthorized, maybe redirect to login...'); } console.error('API error:', error); return Promise.reject(error); } );
How to Secure API Requests with Axios Interceptors in Next.js
Interceptors can also help keep your API requests secure and protect sensitive data.
- Add CSRF or XSRF tokens: Many backends need a token to prevent cross-site attacks. Use Axios options like xsrfCookieName and xsrfHeaderName to send them automatically.
- Keep server-side requests secure: In server components or API routes, never expose tokens in the browser. Use environment variables or server sessions to inject them into requests.
- Handle third-party security needs: If you’re calling APIs like Stripe or AWS that need signed requests or extra headers, set them up in one interceptor.
For example,
// lib/axiosInstance.js const axiosInstance = axios.create({ baseURL: process.env.NEXT_PUBLIC_API_BASE_URL, xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN' });
Common Pitfalls and Debugging Axios Interceptors in Next.js
These are the most frequent issues developers see when using interceptors.
- Interceptor order matters: The order in which you attach interceptors decides what happens first. For example, add the logger before the auth header if you need to log requests.
- Returning the wrong data: Interceptors must return the config or response object (or a rejected promise). If you forget to return them, Axios can’t finish the request, and your app may freeze.
- Different behaviors in SSR and CSR: Data and tokens can change between the server and client. Test both to make sure interceptors work in both environments.
- Silent errors if not handled: If you don’t handle errors in an interceptor, your requests might fail without any sign. This can confuse users and make bugs hard to find.
Best Practices for Integrating Axios Interceptors in Next.js
Interceptors can make API calls easier and cleaner. But if you’re not careful, they can cause problems. Here’s how to use them well:
- Separate client and server interceptors: Your app’s client-side code can use localStorage to get tokens. But on the server side, localStorage isn’t available, so you should use cookies or environment variables instead. By setting up interceptors differently for the client and server, you ensure each uses the right source and avoids errors.
- Use separate Axios instances for different APIs: If your app calls more than one API (for example, your own API and a payment API), use a separate Axios instance for each one. This stops tokens or headers meant for one API from accidentally being sent to another.
Also Read: What is API Testing? (with Examples)
- Attach interceptors only once: Set up interceptors when you create your Axios instance, not inside React components or functions. If you attach them in components, you might end up adding them many times without meaning to. This can lead to duplicated logic and memory leaks.
- Add clear comments to explain each interceptor: Write a short comment for each interceptor that says what it does and why it’s needed. This helps other developers (and your future self) understand how your API calls work, which makes updates easier.
- Be careful with retry logic: Retrying failed requests is helpful for temporary errors like server overloads. But if you retry too often, it slows down your app and can overload the server. Use simple retry logic with a limit on how many retries to avoid these issues.
Advanced Patterns of Axios Interceptors in Next.js
You might need more complex patterns to keep things organized as your app grows.
- Reusable API service class: Wrap your Axios instance in a class or module with common methods (like getUser or postOrder) so you don’t repeat endpoint URLs and options everywhere.
- Chain multiple interceptors: Add logging first, then add headers, then transform data. This order matters to avoid missing important steps.
- Use feature flags or environment checks: Some APIs or headers should only be sent in production, or only if a feature is enabled. Put these checks in your interceptors.
Read More: What is a QA environment?
- Cancel duplicate requests: If a user clicks a button twice or navigates quickly, cancel old requests using Axios’ cancel tokens or AbortController to save bandwidth and avoid confusing results.
- Add telemetry or monitoring: If you need to track performance or errors for analytics, interceptors are a good place to send that data.
How to Test Axios Interceptors in Next.js
Testing interceptors is essential to catch bugs before they reach users.
- Use unit tests with mocks: Use tools like Jest and axios-mock-adapter to fake API responses. This helps you check if interceptors add headers or handle errors the way you expect.
- Test token refresh and auth flows: Test how your app handles expired tokens or missing headers. This confirms your refresh logic and error handling work well.
- Integration testing with real endpoints: Run tests that call actual endpoints in your staging environment. This ensures interceptors work with real data and real server responses.
Read More: What is Integration Testing
- Test both SSR and CSR cases: Next.js uses server-side rendering first, then switches to client-side. Make sure interceptors work in both so you don’t run into issues during hydration.
Why Use Requestly as an Alternative to Axios Interceptors
Requestly is a browser extension that lets you modify HTTP requests and responses directly from your browser. Unlike Axios interceptors, which require changing your app’s code, Requestly works entirely outside of your application. It can be a great choice for testing, debugging, or handling temporary changes without changing your Next.js project.
Here are a few reasons why Requestly is the right alternative to Axios Interceptors.
- No code changes needed: Requestly modifies requests in the browser, so you don’t have to touch your application’s source code.
- Framework-independent: It works with any front-end framework or app, not just Next.js or React.
- Easy to test and debug: You can change headers, URLs, or responses instantly, without deploying new code.
- Good for quick experiments: Test new scenarios or simulate different API responses without changing your actual app.
- Enhanced security and privacy: Use it to block tracking scripts, add secure headers, or test compliance measures quickly.
Here’s how to use Requestly without touching your Next.js app’s code.
1. Modify API responses
This feature lets you change the data your server returns, so you can see how your app behaves with different responses. For example, you can override the response body to mimic different scenarios, like showing what happens if a product’s data is missing or incorrect.
To do this, create a Modify Response rule in Requestly, set the URL to match your API endpoint, and change the response body to whatever data you want to test.
2. Insert or inject scripts
Requestly’s Insert Script Rule lets you add JavaScript or CSS to any web page as it loads. This is helpful for testing new styles, changing the DOM structure, or adding features temporarily, without changing your code. For example, you could inject a script that highlights a certain section of your app for debugging, or add a temporary CSS file to test a new layout.
3. Replace parts of URLs
The Replace Rule in Requestly lets you swap out parts of a URL. This is useful if you want to test your app against different environments, like switching from production to a staging API. For example, you can create a rule to replace https://api.production.com with https://api.staging.com so that all your requests go to the staging server instead.
4. Block network requests
Requestly also allows you to block network requests to see how your app handles missing resources. This is great for testing offline scenarios or seeing how your app handles errors when a third-party script isn’t available. For example, you could block a tracking script or an external library to see if your site still loads correctly without it.
5. Add custom headers
With Requestly, you can add headers like Authorization or custom CORS headers directly in your browser. This is especially helpful when testing secure APIs that require specific headers.
For example, if your API requires a Bearer token, you can create a Modify Headers rule in Requestly to automatically add Authorization: Bearer YOUR_TOKEN to each request without updating your app’s code.
Conclusion
Axios interceptors are essential in Next.js apps for adding headers, catching errors, and transforming data in one place. They save you from repeating the same logic in every component and make your app easier to maintain and test. Start by adding authentication and error handling, then move to more advanced patterns like request cancellation and conditional logic as your app grows.
For developers looking to test and debug quickly without changing their app’s code, Requestly is a great choice. With Requestly, you can modify API requests, add or change headers, block network requests, and even simulate different server responses right in the browser. It works with any front-end framework and doesn’t require editing your source code.