axios, got, node-fetch, and request are tools for making HTTP requests in JavaScript. axios works in both browsers and Node.js. got and node-fetch are built for Node.js environments. request is an older library that is no longer maintained. These tools help developers connect their applications to APIs, download files, and send data to servers.
Making HTTP requests is a daily task for JavaScript developers. Whether you are fetching data for a website or calling a microservice on the server, you need a reliable tool. axios, got, node-fetch, and request have all been popular choices, but they serve different needs today. Let's compare how they handle real-world tasks.
Before writing any code, you must know which tools are safe to use. This is the most critical difference in this group.
request is officially deprecated.
// request: DEPRECATED - Do not use in new projects
const request = require('request');
// This library is no longer maintained
axios, got, and node-fetch are actively maintained.
// axios, got, node-fetch: Actively maintained
import axios from 'axios';
import got from 'got';
import fetch from 'node-fetch';
// All safe for current development
Where your code runs matters. Some tools work everywhere, while others are built specifically for the server.
axios works in both browsers and Node.js.
// axios: Works everywhere
import axios from 'axios';
// Runs in Chrome, Firefox, Node.js, etc.
const response = await axios.get('/api/data');
got is for Node.js only.
// got: Node.js only
import got from 'got';
// Will fail if bundled for browser
const response = await got.get('/api/data');
node-fetch is for Node.js only.
fetch API to the server.fetch built-in, reducing the need for this package.// node-fetch: Node.js only
import fetch from 'node-fetch';
// Modern Node has global fetch built-in
const response = await fetch('/api/data');
request was for Node.js only.
// request: Node.js only (Legacy)
const request = require('request');
// Cannot be used in browser environments
How much code do you need to fetch simple data? Syntax clarity impacts daily development speed.
axios returns the data directly in a data property.
// axios: Auto JSON parse
const response = await axios.get('/api/users');
console.log(response.data); // The actual JSON content
got also returns the body directly by default.
axios for simple cases.// got: Auto JSON parse
const response = await got.get('/api/users');
console.log(response.body); // The actual JSON content
node-fetch returns a Response object.
.json() to parse the data.// node-fetch: Manual JSON parse
const response = await fetch('/api/users');
const data = await response.json(); // Must parse manually
console.log(data);
request uses callbacks instead of Promises.
// request: Callback based (Legacy)
request('/api/users', (error, response, body) => {
const data = JSON.parse(body); // Manual parse
console.log(data);
});
What happens when the server returns a 404 or 500 error? Some tools throw errors for you, while others make you check manually.
axios throws an error for bad status codes.
try/catch blocks.// axios: Throws on 4xx/5xx
try {
await axios.get('/api/broken');
} catch (error) {
console.log('Request failed automatically');
}
got also throws an error for bad status codes.
axios.// got: Throws on 4xx/5xx
try {
await got.get('/api/broken');
} catch (error) {
console.log('Request failed automatically');
}
node-fetch does NOT throw on bad status codes.
response.ok yourself.// node-fetch: Does NOT throw on HTTP error
const response = await fetch('/api/broken');
if (!response.ok) {
throw new Error('Request failed'); // Must check manually
}
request passes errors to the callback.
error argument first.// request: Callback error handling
request('/api/broken', (error, response, body) => {
if (error) {
console.log('Network error'); // Check error arg
}
});
Large applications often need to modify requests or responses globally. This is useful for adding auth tokens or logging.
axios has built-in interceptors.
// axios: Interceptors
axios.interceptors.request.use(config => {
config.headers.Authorization = 'Bearer token';
return config;
});
got uses hooks for similar functionality.
// got: Hooks
const client = got.extend({
hooks: {
beforeRequest: [
options => {
options.headers.authorization = 'Bearer token';
}
]
}
});
node-fetch has no built-in interceptor system.
// node-fetch: Manual wrapper
async function fetchWithAuth(url) {
return fetch(url, {
headers: { Authorization: 'Bearer token' }
});
}
request used plugins and jars.
// request: Plugins (Legacy)
// Required external libraries for complex logic
// No native interceptor concept like axios
| Feature | axios | got | node-fetch | request |
|---|---|---|---|---|
| Status | β Active | β Active | β Active | β Deprecated |
| Environment | π Browser + Node | π₯οΈ Node Only | π₯οΈ Node Only | π₯οΈ Node Only |
| Promise Based | β Yes | β Yes | β Yes | β Callbacks |
| Auto JSON | β Yes | β Yes | β Manual | β Manual |
| Error Handling | β Throws | β Throws | β Check .ok | β οΈ Callback |
| Interceptors | β Built-in | β Hooks | β Manual | β Plugins |
axios is the safe bet for full-stack teams π§°. It works everywhere and handles common tasks automatically. Choose it if you want to write less code and share logic between frontend and backend.
got is the power tool for Node.js backends π§. It offers the best performance and features for server-side scripts. Choose it if you are building microservices or CLI tools.
node-fetch is the lightweight standard πͺΆ. It mimics the browser API perfectly. Choose it if you want minimal dependencies and your team already knows the fetch API.
request is history π. It is deprecated and should not be used. If you see it in an old project, plan to replace it soon.
Final Thought: For most new projects, start with axios for versatility or got for pure Node.js power. Avoid request entirely, and consider using native fetch if you are on Node.js 18 or higher.
Choose got if you are building backend services in Node.js. It offers the best developer experience for server-side code with strong stream support. It is not suitable for browser applications.
Do not choose this package. It is deprecated and no longer receives security updates. You should migrate existing projects to axios, got, or native fetch.
Choose axios if you need one library for both browser and server code. It handles JSON automatically and has built-in request interceptors. Good for teams wanting consistency across platforms without switching tools.
Choose node-fetch if you want a lightweight API that matches the browser fetch standard. It is ideal for simple Node.js scripts where you do not need advanced features like automatic JSON parsing.
Sindre's open source work is supported by the community.
Special thanks to:
Human-friendly and powerful HTTP request library for Node.js
See how Got compares to other HTTP libraries
You probably want Ky instead, by the same people. It's smaller, works in the browser too, and is more stable since it's built on Fetch. Or fetch-extras for simple needs.
Support questions should be asked here.
npm install got
Warning: This package is native ESM and no longer provides a CommonJS export. If your project uses CommonJS, you will have to convert to ESM. Please don't open issues for questions regarding CommonJS / ESM.
Got v11 is no longer maintained and we will not accept any backport requests.
A quick start guide is available.
Got has a dedicated option for handling JSON payload.
Furthermore, the promise exposes a .json<T>() function that returns Promise<T>.
import got from 'got';
const {data} = await got.post('https://httpbin.org/anything', {
json: {
hello: 'world'
}
}).json();
console.log(data);
//=> {"hello": "world"}
For advanced JSON usage, check out the parseJson and stringifyJson options.
For more useful tips like this, visit the Tips page.
By default, Got will retry on failure. To disable this option, set options.retry.limit to 0.
got4aws - Got convenience wrapper to interact with AWS v4 signed APIsgh-got - Got convenience wrapper to interact with the GitHub APIgl-got - Got convenience wrapper to interact with the GitLab APIgotql - Got convenience wrapper to interact with GraphQL using JSON-parsed queries instead of stringsgot-fetch - Got with a fetch interfacegot-scraping - Got wrapper specifically designed for web scraping purposesgot-ssrf - Got wrapper to protect server-side requests against SSRF attacksgot | node-fetch | ky | axios | superagent | |
|---|---|---|---|---|---|
| HTTP/2 support | :heavy_check_mark: | :x: | :heavy_check_mark: | :x: | :heavy_check_mark:** |
| Browser support | :x: | :heavy_check_mark:* | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| Promise API | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| Stream API | :heavy_check_mark: | Node.js only | :x: | :x: | :heavy_check_mark: |
| Pagination API | :heavy_check_mark: | :x: | :x: | :x: | :x: |
| Request aborting | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| RFC 7234 caching | :heavy_check_mark: | :x: | :x: | :x: | :x: |
| Cookies (out-of-the-box) | :heavy_check_mark: | :x: | :x: | :x: | :x: |
| Follows redirects | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| Retries on failure | :heavy_check_mark: | :x: | :heavy_check_mark: | :x: | :heavy_check_mark: |
| Progress events | :heavy_check_mark: | :x: | :heavy_check_mark: | Browser only | :heavy_check_mark: |
| Handles gzip/deflate | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| Advanced timeouts | :heavy_check_mark: | :x: | :x: | :x: | :x: |
| Timings | :heavy_check_mark: | :x: | :x: | :x: | :x: |
| Errors with metadata | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: |
| JSON mode | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| Custom defaults | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: |
| Composable | :heavy_check_mark: | :x: | :x: | :x: | :heavy_check_mark: |
| Hooks | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: |
| Issues open | |||||
| Issues closed | |||||
| Downloads | |||||
| Coverage | TBD | ||||
| Build | |||||
| Bugs | |||||
| Dependents | |||||
| Install size | |||||
| GitHub stars | |||||
| TypeScript support | |||||
| Last commit |
* It's almost API compatible with the browser fetch API.
** Need to switch the protocol manually. Doesn't accept PUSH streams and doesn't reuse HTTP/2 sessions.
:sparkle: Almost-stable feature, but the API may change. Don't hesitate to try it out!
:grey_question: Feature in early stage of development. Very experimental.
Click here to see the install size of the Got dependencies.
![]() | ![]() |
|---|---|
| Sindre Sorhus | Szymon Marczak |