How to Get the Final Request URL in Axios

When making HTTP requests that involve server-side redirects, the final destination URL often differs from the initial target provided in the request configuration. This article explains how to inspect and retrieve the final resolved request URL inside the Axios HTTP client across both browser and Node.js environments, highlighting the differences between the underlying transport adapters.

The Mechanism for Retrieving the Final URL

Axios does not update the response.config.url property when a redirect occurs; response.config.url will always retain the original, unmodified URL passed to the request configuration.

To obtain the actual, final resolved URL, you must inspect the underlying request object attached to the Axios response. Because Axios uses different adapters depending on the runtime environment (the browser's XMLHttpRequest or Node.js native http/https modules), the property path varies.

1. In the Browser

In browser environments, Axios uses XMLHttpRequest. Modern browsers expose the final redirected URL on the XHR instance via the responseURL property:

axios.get('https://example.com/initial-redirect')
  .then(response => {
    const finalUrl = response.request.responseURL;
    console.log('Final resolved URL:', finalUrl);
  })
  .catch(error => {
    console.error(error);
  });

2. In Node.js

In Node.js, Axios uses the follow-redirects package over the standard HTTP/HTTPS modules. The incoming response object (res) attached to the client request stores the final URL under responseUrl:

const axios = require('axios');

axios.get('https://example.com/initial-redirect')
  .then(response => {
    const finalUrl = response.request.res.responseUrl;
    console.log('Final resolved URL:', finalUrl);
  })
  .catch(error => {
    console.error(error);
  });

Writing an Isomorphic Helper

If your application runs in both the browser and Node.js (such as in an SSR environment like Next.js or Nuxt), you can use a fallback helper to safely read the final URL regardless of the platform:

function getFinalUrl(response) {
  if (!response || !response.request) {
    return null;
  }
  
  // Browser (XMLHttpRequest)
  if (response.request.responseURL) {
    return response.request.responseURL;
  }
  
  // Node.js (http.ClientRequest / follow-redirects)
  if (response.request.res && response.request.res.responseUrl) {
    return response.request.res.responseUrl;
  }

  // Fallback to original configured URL if no redirect data is available
  return response.config.url;
}

Implementing in Axios Interceptors

You can also attach this logic to a response interceptor to automatically decorate all successful response objects with the resolved URL:

axios.interceptors.response.use(response => {
  response.finalUrl = response.request?.responseURL 
    || response.request?.res?.responseUrl 
    || response.config.url;
    
  return response;
});

Using this approach, you can directly access response.finalUrl throughout your application without repeatedly querying the nested adapter properties.