Custom Query Parameter Serialization in Axios with qs

Axios is a popular promise-based HTTP client for JavaScript, but its default query parameter serialization cannot always handle complex data structures like nested objects or custom-formatted arrays. To overcome this limitation, Axios provides the paramsSerializer configuration option, which allows developers to delegate query string creation to specialized libraries such as qs. By integrating qs, you gain complete control over how arrays, indices, nested properties, and special characters are encoded into request URLs.

Why Axios Requires Custom Serialization

By default, Axios uses basic internal mechanisms (or URLSearchParams in modern environments) to serialize the params object into a URL query string. While this works for simple key-value pairs, it often fails or produces unwanted results when handling:

Backend frameworks often expect specific query parameter formats, making standard serialization incompatible.

Integrating qs with paramsSerializer

The qs library is a querystring parsing and stringifying library supporting security features, nested objects, and diverse array formatting options.

Basic Implementation in Axios v1.x

In modern Axios versions (v1.0.0 and newer), paramsSerializer accepts an object with a custom serialize function or configuration options.

import axios from 'axios';
import qs from 'qs';

const response = await axios.get('https://api.example.com/items', {
  params: {
    categories: ['electronics', 'appliances'],
    filter: { inStock: true, priceLimit: 500 }
  },
  paramsSerializer: {
    serialize: (params) => qs.stringify(params, { arrayFormat: 'brackets' })
  }
});

Global Configuration with Axios Instances

To avoid specifying paramsSerializer in every single request, you can configure it globally on a custom Axios instance created via axios.create:

import axios from 'axios';
import qs from 'qs';

const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  paramsSerializer: {
    serialize: (params) => qs.stringify(params, {
      arrayFormat: 'repeat',
      allowDots: true,
      skipNulls: true
    })
  }
});

// Used automatically on all requests with params
apiClient.get('/search', { params: { tags: ['js', 'node'], user: null } });
// URL Result: /search?tags=js&tags=node

Configuring Array Formatting in qs

Different APIs expect arrays formatted in different ways. The arrayFormat option in qs allows you to switch between standard conventions:

qs.stringify({ ids: [10, 20] }, { arrayFormat: 'comma' });
// Output: ids=10%2C20 (or ids=10,20 depending on encode setting)

Handling Nested Objects

When working with nested objects, qs provides the allowDots option to switch from bracket notation to dot notation:

Using paramsSerializer with qs ensures that your outbound Axios requests match whatever query parameter format your target API requires without needing manual URL string construction.