Passing Custom Metadata in Axios Request Config

Passing custom metadata through the Axios HTTP client allows developers to attach contextual information—such as request start times, tracking IDs, or retry counts—directly to an individual request. This article explains how Axios handles custom properties within its request configuration object, how to access that metadata inside request and response interceptors, and how to properly type custom configuration fields using TypeScript.

How the Metadata Mechanism Works

Axios creates an internal configuration object for every HTTP request. Any custom properties added to the configuration object during a request call are preserved throughout the entire lifecycle of that request. When a response is received, Axios attaches the original configuration object to response.config.

Because the configuration object persists from dispatch to response, it serves as the primary transport mechanism for passing state and metadata across interceptors.

Attaching Metadata to a Request

To pass custom metadata, add custom properties directly to the config object when executing a request:

import axios from 'axios';

axios.get('https://api.example.com/data', {
  metadata: {
    startTime: Date.now(),
    requestId: 'req-12345',
    skipAuth: false
  }
});

You can also assign custom properties to an Axios instance default configuration or inside a request interceptor.

Accessing Metadata in Interceptors

Interceptors allow you to read, modify, and act on the metadata before the request is sent or after the response arrives.

Measuring Request Latency (Example)

A common use case is measuring network latency by setting a timestamp before dispatch and calculating the delta upon response:

import axios from 'axios';

const apiClient = axios.create();

// Request Interceptor: Record start time
apiClient.interceptors.request.use((config) => {
  config.metadata = { startTime: new Date().getTime() };
  return config;
}, (error) => {
  return Promise.reject(error);
});

// Response Interceptor: Calculate duration
apiClient.interceptors.response.use((response) => {
  const startTime = response.config.metadata?.startTime;
  if (startTime) {
    const duration = new Date().getTime() - startTime;
    console.log(`Request to ${response.config.url} took ${duration} ms`);
  }
  return response;
}, (error) => {
  if (error.config?.metadata?.startTime) {
    const duration = new Date().getTime() - error.config.metadata.startTime;
    console.error(`Failed request took ${duration} ms`);
  }
  return Promise.reject(error);
});

TypeScript Module Augmentation

In TypeScript, adding unknown properties to AxiosRequestConfig can trigger type errors. To support custom metadata with full type safety, use module augmentation to extend the Axios interface:

import axios from 'axios';

declare module 'axios' {
  export interface AxiosRequestConfig {
    metadata?: {
      startTime?: number;
      requestId?: string;
      retryCount?: number;
    };
  }
  export interface InternalAxiosRequestConfig {
    metadata?: {
      startTime?: number;
      requestId?: string;
      retryCount?: number;
    };
  }
}

By extending both AxiosRequestConfig (for initial requests) and InternalAxiosRequestConfig (used inside modern Axios interceptors), your custom metadata properties become fully typed across your application.