SpikeMe
← Comparisons
HTTP

Axios vs fetch

updated on July 13, 2026

Axios vs fetch (nativo)

Axios compared to the native Fetch API on interceptors, timeout, HTTP error handling, and request cancellation — with real npm data and a verdict by context.

FactAxiosfetch (nativo)
Current version1.18.1
Downloads/week (npm)90,588,410
LicenseMIT
Bundle (gzip)16.6 kB
CriterionAxiosfetch (nativo)
Response parsingJSON parsed automatically into response.datarequires calling .json() manually on the Response
HTTP errors (4xx/5xx)throws an exception automatically for status codes outside the 2xx rangedoesn't throw — the promise resolves normally, you need to check response.ok
Interceptorsbuilt-in request and response interceptorsno native interceptors — requires your own wrapper
Timeouttimeout option built into the request configurationno dedicated timeout option — combine with AbortSignal.timeout()
Cancellationsupports AbortController plus its own legacy cancellation tokennative support via AbortController/AbortSignal
Upload/download progressbuilt-in onUploadProgress and onDownloadProgress eventsno native progress event — requires reading the ReadableStream manually
Availabilityexternal dependency installed via npmnative API in the browser and in Node.js, no installation

Context

Before it existed as a native API available in every browser or runtime, making an HTTP call in JavaScript meant writing directly against XMLHttpRequest — verbose enough that third-party libraries were born just to wrap it in a more comfortable API. fetch is that native API, specified by WHATWG and available in both browsers and the Node.js runtime, with nothing to install: it's the primitive that request libraries are built on top of. Axios is one of those libraries: a third-party dependency that wraps the environment's own HTTP transport layer (XMLHttpRequest in the browser, the native http module in Node.js) in an API with more conveniences built in — interceptors, configurable timeout, automatic serialization and parsing, and error handling that already treats a 404 or 500 as a failure.

That last difference is the one that most surprises people migrating from one side to the other: a fetch call that gets a 500 from the server doesn't throw any exception — the promise resolves normally, and it's up to the code to check response.ok or response.status manually to find out something went wrong. Axios handles that same scenario by throwing an exception automatically, so try/catch already catches both network failures and error HTTP responses in the same place.

When to choose Axios

Axios pays off when the application makes HTTP calls repeatedly enough that interceptors, timeout, and uniform error handling pay for themselves — avoiding rewriting that plumbing on every call:

import axios from "axios";

const api = axios.create({ baseURL: "/api", timeout: 5000 });
api.interceptors.request.use((config) => {
  config.headers.Authorization = `Bearer ${getToken()}`;
  return config;
});

The request interceptor above injects the authentication token into every call made through that instance, without needing to repeat that logic in every place that makes a request — and the same mechanism exists for intercepting responses, useful for renewing an expired token or standardizing the error format before it reaches business code. Added to the timeout built into the configuration and the automatic JSON parsing in response.data, Axios solves out of the box a set of problems that, with plain fetch, every project ends up reimplementing in a slightly different way.

Axios also exposes progress events (onUploadProgress, onDownloadProgress) directly in the call configuration, which is particularly useful for uploading large files where the UI needs to show a progress bar — a scenario where plain fetch requires reading the response body as a ReadableStream manually to calculate that same progress. For teams that make HTTP calls in many different places across the application, centralizing that behavior in a single configured Axios instance tends to come out cheaper than making sure everyone wrote the fetch wrapper the same way.

When to choose fetch (native)

Native fetch pays off when the volume and complexity of HTTP calls don't justify an external dependency, or when the project already has (or is willing to write) its own thin wrapper:

async function apiFetch(path: string, timeoutMs = 5000) {
  const res = await fetch(`/api${path}`, { signal: AbortSignal.timeout(timeoutMs) });
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

AbortSignal.timeout() is the piece that resolves, natively and precisely, what Axios offers ready-made in its configuration: it generates an AbortSignal that aborts the request on its own after the specified time, without needing to orchestrate a setTimeout and an AbortController manually. The if (!res.ok) throw above is the equivalent of Axios's automatic behavior in the face of an HTTP error — just written by hand, once, inside the wrapper. For anyone who doesn't need interceptors or upload progress events, this few-line wrapper covers most of what a typical application uses from an HTTP library, without adding weight to the bundle or another dependency to keep up to date.

Because fetch is an API standardized by the browser itself and by the Node.js runtime, the same request code runs in both environments without needing an isomorphic package — something third-party libraries have historically had to solve with separate builds or polyfills for each side. This matters especially in projects that share code between client and server, like data-fetching functions used both in a server component and in a test running in Node: there's no risk of the API behaving differently between the two environments, because it's the same native implementation on both sides.

Verdict

How much plumbing code — interceptors, timeout, error handling, cancellation — is worth writing and maintaining by hand, instead of outsourcing to an already-tested dependency? That question, more than any benchmark, is what decides between Axios and plain fetch, since technically fetch alone covers the vast majority of cases: it's a mature, well-supported API. Teams that write that wrapper once and reuse it across the whole project rarely miss Axios; teams that prefer those ready-made conveniences, tested and documented by a dedicated library, tend to prefer installing the dependency over maintaining that code in-house.

Axios

Choose Axios if…

Choose Axios if you want interceptors, a built-in timeout, and HTTP errors treated as exceptions, without writing that wrapper yourself.

fetch (nativo)

Choose fetch (nativo) if…

Choose native fetch if you want zero extra dependencies and the project doesn't depend on interceptors or upload/download progress events.

The numbers above came from the registry, with source and date. Still, this comparison is generic: the right answer depends on versions, your team and what already exists in your project.

Generate the spike for YOUR stack

Share

XLinkedIn