Do you need to send an HTTP request in JavaScript? Use the native Fetch API. Both on the browser and on the server.

Do you need an Axios-like API that is nicer than native fetch? Use ky.

Do you need the conveniences that Axios brings? Also use ky.

Axios was a godsend back when JavaScript was still a mess. But those days are over. The standard Fetch API is now available in all major platforms. Thanks for everything Axios, but it is time to say goodbye.

Adios, Axios 👋

Why?

Why?

TLDR?

Axios was once a convenient library that utilized XMLHttpRequest in web browsers and the http module in Node environments. However, in today's modern development landscape, this approach has been surpassed by the native Fetch API, which offers consistent functionality across browsers, Node, and even other environments.

With the adoption of a unified API like Fetch, you can easily eliminate Axios as an additional dependency in your modern codebase, resulting in reduced bundle sizes. Moreover, the Fetch API has undergone full standardization, unlike Axios, which comes with its own set of nuances that often catch developers off-guard. This includes differences in how fetch and Axios handle promise rejection in various scenarios.

Furthermore, certain frameworks, like Next.js, have begun exposing additional features within the Fetch API that may not be readily accessible when using Axios.

The Fetch API is available across all environments

Since the release of Node 18 in April 2022, the Fetch API, which had been implemented in browsers for over a half decade by that point, became available by default in Node. In September 2023, Node 16, the last Long-Term Support (LTS) version that did not include the Fetch API by default, reached its end of life and is no longer maintained. Consequently, all LTS versions of Node, as well as other runtimes like Bun, now include the Fetch API by default (see also Can I use... and the MDN Browser Compatibility on fetch).

Handling errors is more natural with the Fetch API

When using either Axios or the Fetch API, you'll be working with promises. In both cases, these promises will resolve once the server's response is received. Notably, the Fetch API only "rejects when a network error occurs (typically due to permission issues or similar problems)." In all other scenarios, including when the server responds with a status code like 404, the promise resolves and the response object is returned and can be inspected for additional logic.

In contrast, the Axios implementation rejects the promise if the returned status code falls outside the 2xx range (which is configurable via validateStatus), if no response is received, or if any other issues occur while setting up the request (see also Handling Errors in the Axios docs).

Although it's a matter of subjective interpretation, one can make a case that certain situations, like handling redirects falling within the 3xx status code range, should not trigger an error. Typically, it is discouraged to raise an error unless the circumstances are unrecoverable or so critical that they significantly disrupt the ongoing operation of the application, such as a genuine network error.

Incompatibilities with Next.js

With the introduction of the App Router in Next.js 13, developers gain access to granular caching options like cache, revalidate, and tags that can be seamlessly integrated with the Fetch API. These options are processed by the underlying server using a custom implementation of fetch to modify caching behavior. In contrast, Axios lacks support for these new custom options, forcing developers to resort to less granular caching alternatives in the form of route segment configuration options.

Reusing standard web APIs

Unlike Axios, which introduces its own abstractions and API design, the Fetch API is a standardized web API built on classes and functions familiar to developers across various use cases. For instance, explicitly using methods like Response.json, Response.formData, or Response.blob instead of relying on automatic data deserialization. This opens up opportunities for lazy evaluation of incoming streams and results in cleaner code, typically adding just one extra line compared to what Axios would have provided.

The Fetch API is truly isomorphic

The term "isomorphic" is a fancy way of saying "it works on both the client side and the server side." However, unlike Axios, the Fetch API is implemented identically in both environments, making it much easier to ensure the correctness of your code.

What about the convenience of Axios?

Axios offers a great deal of convenience by automatically handling tasks like setting HTTP methods or headers, particularly for content types. When using the Fetch API, these aspects might require manual configuration unless you create custom, reusable functions to abstract them according to your requirements. Alternatively, you can explore a dedicated wrapper for the Fetch API called ky, which provides similar functionality while remaining a small, self-contained dependency that you can consider adding to your project.

Migrating off of Axios to the Fetch API

Unless you opt for a dedicated wrapper like ky, as mentioned earlier, you will need to manually migrate certain features that Axios conveniently offers out of the box.

For request cancellation, you would need to utilize an AbortController, a part of the standard web APIs. Handling request retries, perhaps incorporating exponential backoff, would involve writing custom code tailored to your specific requirements.

Additionally, other features you might consider migrating include interceptors, which can be easily implemented as small, reusable functions that you can apply to response objects.