obah sylva

Fetch API vs Axios: How to Make API Calls in JavaScript

Share:fXinW
Share this article

Every JavaScript project that talks to an API eventually asks the same question: reach for the native fetch() that ships in every modern browser and in Node.js 18+, or add Axios, still the most-downloaded HTTP client on npm with tens of millions of weekly downloads. In 2026 the honest answer is that both are solid choices, and the right one depends on what your project actually needs rather than which one is more popular.

The Fundamental Difference: Error Handling

This is the single most consequential difference between the two, and it trips up developers constantly. Fetch only rejects its promise on a network failure — a 404, 500, or 503 response is still treated as a “successful” fetch, and you have to manually check response.ok to catch it. Axios throws automatically on any non-2xx status code.

// Fetch: a 404 does NOT throw
const res = await fetch('/api/users/999');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();

// Axios: a 404 throws automatically, caught by try/catch
try {
  const { data } = await axios.get('/api/users/999');
} catch (error) {
  console.log(error.response.status); // 404
}

JSON Handling and Request Setup

Fetch requires an explicit .json() call to parse the response body, plus manual header configuration for POST requests. Axios parses JSON automatically and defaults to JSON content type.

// Fetch
const res = await fetch('/api/users', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'Amara' })
});
const data = await res.json();

// Axios
const { data } = await axios.post('/api/users', { name: 'Amara' });
// JSON headers and parsing handled automatically

Code editor displaying JavaScript source code for an API request

READ ALSO:

Interceptors: Axios’s Standout Feature

Axios interceptors let you run logic on every request or response globally — attaching an auth token, logging, or redirecting on a 401 — without repeating that logic in every call. Fetch has no built-in equivalent; you’d write a wrapper function yourself.

axios.interceptors.request.use((config) => {
  const token = localStorage.getItem('token');
  if (token) config.headers.Authorization = `Bearer ${token}`;
  return config;
});

axios.interceptors.response.use(
  (response) => response,
  (error) => {
    if (error.response?.status === 401) redirectToLogin();
    return Promise.reject(error);
  }
);

Cancellation, Timeouts, and Progress

Both support request cancellation via AbortController, but Axios wraps it into a simpler config option and adds a timeout that throws automatically — Fetch has no built-in timeout at all and requires wiring AbortController to a setTimeout manually. Axios also has cleaner built-in support for upload progress tracking; with Fetch, tracking progress means manually reading the response body as a stream chunk by chunk.

Bundle Size vs. Zero Dependencies

Fetch is native everywhere it runs — browsers, Node.js 18+, Deno, Bun, and Cloudflare Workers — and adds nothing to your bundle. Axios adds meaningful weight (roughly 40KB or more before compression) but that cost buys interceptors, automatic error throwing, and one consistent API that behaves identically in the browser and on the server, which matters for frameworks that share HTTP client code between client and server code paths.

Which One Should You Use?

  • Choose Fetch for simple projects, serverless functions, or anywhere zero dependencies matters more than convenience
  • Choose Axios for larger applications that need interceptors, automatic JSON handling, consistent error throwing, or a shared client between browser and server code
  • Either one is a defensible default in 2026 — the mistake is picking one and never learning the other, since most codebases eventually touch both

Frequently Asked Questions

Is Axios still necessary now that Fetch is built into every browser and Node.js?
Not strictly necessary, but still valuable. Fetch covers the basics natively, but Axios’s automatic error throwing, interceptors, and JSON handling remove enough boilerplate that many teams still prefer it for anything beyond simple requests.
Why doesn’t Fetch throw an error on a 404 response?
By design, Fetch only treats network-level failures (like a lost connection) as promise rejections; any completed HTTP response, including error status codes, is considered a “successful” fetch that you’re expected to check manually via response.ok.
Can I use Axios and Fetch in the same project?
Yes, and it’s common — some teams use Fetch for simple, one-off requests and Axios for anything that benefits from interceptors or shared configuration, like authenticated API calls across a large app.

Want more JavaScript deep dives like this? Explore more Web Development articles.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top