Choosing between fetch and axios in React comes down to how much request handling you want to write by hand. Fetch is a built-in browser function that returns a promise you parse yourself. Axios is an installable promise-based HTTP client that parses JSON automatically and adds timeouts, interceptors, and progress events.
The core difference in one table
The main difference is ownership. Fetch ships with the browser and does the minimum: it returns a Response and leaves parsing, error handling, and timeouts to you.
Axios wraps that work in a package with sensible defaults. Axios 1.x is the current major version.
| Feature | fetch | Axios |
|---|---|---|
| Installation | Built into the browser | npm install axios |
| JSON parsing | Call response.json() yourself | response.data is parsed automatically |
| Error handling | Rejects only on network failure | Rejects on non-2xx statuses too |
| Timeouts | None built in | timeout option in milliseconds |
| Interceptors | None | Request and response interceptors |
| Cancellation | AbortController signal | AbortController signal |
| Upload progress | Manual with streams | onUploadProgress callback |
The two most noticeable differences are JSON parsing and error behavior. Axios gives you response.data ready to render and rejects on HTTP errors by default, while fetch makes you read and check both yourself. This is why a one-off request rarely justifies adding Axios, while an app with many endpoints often does.
Make the same GET request in both
A request that loads one user looks similar in both libraries. The fetch version below checks the status, parses JSON, and catches failures explicitly.
import { useEffect, useState } from "react";
useEffect(() => {
fetch("/api/user/1")
.then((res) => {
if (!res.ok) throw new Error("Request failed");
return res.json();
})
.then((data) => setUser(data))
.catch(() => setError("Could not load user"));
}, []);With fetch you own the happy path and the failure path. The Axios version below does the same job with less ceremony, after running npm install axios and importing the default export.
import axios from "axios";
useEffect(() => {
axios
.get("/api/user/1")
.then((response) => setUser(response.data))
.catch(() => setError("Could not load user"));
}, []);The get call resolves directly to a response object, and response.data is already the parsed JSON. A failed status rejects the promise on its own, so one catch block handles both network and HTTP errors. That difference alone removes a check from every request you write.
What Axios adds out of the box
The extras matter once requests grow beyond a single GET. Three features each need custom code with fetch but come free with Axios.
- Timeouts. Passing a timeout option aborts slow requests. With fetch you combine AbortController with a timer.
- Interceptors. You can attach an auth header or refresh a token in one place instead of repeating it in every request.
- Progress. The onUploadProgress and onDownloadProgress callbacks drive file transfer bars.
None of these are impossible with fetch. They are simply already written in Axios, which is why teams reach for it when requests multiply. These features are available in Axios 1.x, which keeps the same API in browsers and Node.js.
The basic pattern behind both libraries is the same and is explained in how to fetch API data in React.
Which should you use?
Choose fetch when the app is small, the endpoints are few, and you want zero dependencies. Choose Axios when you find yourself writing the same parsing, error, timeout, and header code in several places. Start with fetch and introduce Axios when that boilerplate shows up in three or more requests.
A third option matters here too. A data library such as TanStack Query adds caching, retries, and request deduplication on top of either client, so setting up TanStack Query in React can matter more than the fetch versus Axios choice. Both libraries also support cancellation through the same signal, which is covered in how to cancel fetch requests in React with AbortController.
Rune AI
Key Insights
- fetch is built in; Axios is a package you install.
- fetch returns raw JSON; Axios gives you response.data parsed.
- fetch rejects only on network errors; Axios rejects non-2xx statuses too.
- Axios adds timeouts, interceptors, and progress callbacks.
- Start with fetch, move to Axios when you repeat the same request boilerplate.
Frequently Asked Questions
Is fetch enough for most React apps?
Does Axios work in Node.js too?
Is fetch built into every browser?
Conclusion
Fetch is the zero-dependency baseline and needs manual JSON parsing and error checks. Axios adds parsed data, automatic error rejection, timeouts, interceptors, and progress events, which pay off as request handling grows.
More in this topic
How to Build a Dropdown Menu in React
Build a React dropdown menu with the ARIA menu button pattern. Handle open and close, keyboard arrows, and clicks outside the menu.
How to Animate React Components with Motion
Animate React components with the Motion library. Set up motion, add enter, hover, and exit animations, and respect reduced motion.
Headless UI Components Explained: Logic Without Locked Styling
Understand headless UI components and how libraries like Radix give you unstyled, accessible behavior that you style yourself.