Introduction
Node.js 18+ inch, axios, and got` are the popular choices. This guide covers all options with practical examples. See Javascript Guide for more context. See Javascript Guide for more context.
Native fetch (Node.js 18+)
Since Node.js 18, fetch is available globally — no installation needed:
// GET request
const response = await fetch('https://api.github.com/users/github');
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const user = await response.json();
console.log(user.name);
// POST request
const.example.com/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Alice', email: '[email protected]' }),
});
const created = await response.json();
Check your Node.js version:
node --version # need 18.0.0 or higher for native fetch
node-fetch (Node.js < 18)
For older Node.js versions, node-fetch provides the same Fetch API:
npm install node-fetch
// ESM (package.json: “type”: “module”) import fetch from ’node-fetch';
// CommonJS const fetch = require(’node-fetch’);
The API is identical to native `fetch` — the same code works with both.
### Fetching Text and JSON
import fetch from ’node-fetch';
// Fetch HTML/text const response = await fetch(‘https://example.com/'); const html = await response.text(); console.log(html.slice(0, 200));
// Fetch JSON
const res = await fetch(‘https://api.github.com/users/github');
new Error(HTTP error: ${res.status});
const data = await res.json();
console.log(data.login, data.public_repos);
### POST with JSON Body
const response = await fetch(‘https://api.example.com/login', { method: ‘POST’, headers: { ‘Content-Type’: ‘application/json’, ‘Accept’: ‘application/json’, }, body: JSON.stringify({ email: ‘[email protected]’, password: ‘secret’ }), });
if (!response.ok) {
const error = await response.json().catch(() => ({}));
throw new Error(error.message || HTTP ${response.status});
}
const { token } = await response.json();
### Handling HTTPS with Self-Signed Certificates
In development, you may need to bypass certificate verification:
import https from ‘https’; import fetch from ’node-fetch’;
// Only use in development — never in production const agent = new https.Agent({ rejectUnauthorized: false });
Resources
- Node.js fetch documentation
- node-fetch on npm
- axios documentation
- got documentation ile’, new Blob([fs.readFileSync(‘photo.jpg’)]), ‘photo.jpg’); form.append(‘description’, ‘My photo’);
const response = await fetch(‘https://api.example.com/upload', { method: ‘POST’, body: form, // Don’t set Content-Type — fetch sets it with boundary });
## Which Should You Use?
- **Node.js 18+, simple use case:** native `fetch` — zero dependencies
- **Need interceptors, wide ecosystem:** `axios`
- **Need retry, streaming, TypeScript:** `got`
- **Node.js < 18, want fetch API:** `node-fetch`out(r, 1000 * (i + 1))); // backoff
}
}
Parallel Requests
// All at once
const [users, posts] = await Promise.all([
fetch('/api/users').then(r => r.json()),
fetch('/api/posts').then(r => r.json()),
]);
// With axios
const [usersRes, postsRes] = await Promise.all([
api.get('/users'),
api.get('/posts'),
]);
File Upload
import { FormData, Blob } from 'node-fetch'; // node-fetch v3
import fs from 'fs';
const form = new FormData();
form.append('f out after ${timeoutMs}ms`);
}
throw err;
}
}
Retry Logic
async function fetchWithRetry(url, options = {}, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
const response = await fetch(url, options);
if (response.ok) return response;
if (response.status < 500) return response; // don't retry 4xx
} catch (err) {
if (i === retries - 1) throw err;
}
await new Promise(r => setTimeCommon Patterns
### Timeout with AbortController (fetch/node-fetch)
async function fetchWithTimeout(url, timeoutMs = 5000) { const controller = new AbortController(); const id = setTimeout(() => controller.abort(), timeoutMs);
try {
const response = await fetch(url, { signal: controller.signal });
clearTimeout(id);
return response;
} catch (err) {
clearTimeout(id);
if (err.name === 'AbortError') {
throw new Error(`Request timed user = await api.post('users', { json: { name: 'Alice' } }).json();
## Comparison
| Feature | native fetch | node-fetch | axios | got |
|---|---|---|---|---|
| Node.js 18+ built-in | Yes | No | No | No |
| Browser compatible | Yes | No | Yes | No |
| Automatic JSON | No (manual) | No (manual) | Yes | Yes (`.json()`) |
| Interceptors | No | No | Yes | Hooks |
| Retry built-in | No | No | No | Yes |
| TypeScript | Good | Good | Excellent | Excellent |
| Bundle size | 0 | Small | Medium | Medium |
## ,
}).json();
// With options
const data = await got('https://api.example.com/data', {
headers: { Authorization: `Bearer ${token}` },
searchParams: { page: 1, limit: 20 },
timeout: { request: 5000 },
retry: { limit: 3 },
}).json();
got Instance
const api = got.extend({
prefixUrl: 'https://api.example.com',
headers: { Authorization: `Bearer ${token}` },
timeout: { request: 10000 },
retry: { limit: 2 },
});
const users = await api.get('users').json();
const received');
} else {
// Request setup error
console.error('Request error:', error.message);
}
}
}
got
got is a modern, feature-rich HTTP client with excellent TypeScript support:
npm install got
import got from 'got';
// GET JSON
const data = await got('https://api.github.com/users/github').json();
// POST
const response = await got.post('https://api.example.com/users', {
json: { name: 'Alice', email: '[email protected]' }s', { name: 'Alice' });
axios Error Handling
try {
const response = await axios.get('/api/users/999');
} catch (error) {
if (axios.isAxiosError(error)) {
if (error.response) {
// Server responded with error status
console.error('Status:', error.response.status);
console.error('Data:', error.response.data);
} else if (error.request) {
// Request made but no response (network error)
console.error('No response 'application/json' },
});
// Add auth token to every request
api.interceptors.request.use((config) => {
config.headers.Authorization = `Bearer ${getToken()}`;
return config;
});
// Handle 401 globally
api.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 401) {
redirectToLogin();
}
return Promise.reject(error);
}
);
// Use the instance
const users = await api.get('/users');
const user = await api.post('/user'https://api.example.com/users', {
name: 'Alice',
email: '[email protected]',
});
console.log(response.data);
// With config
const response = await axios.get('https://api.example.com/data', {
headers: { Authorization: `Bearer ${token}` },
params: { page: 1, limit: 20 }, // adds ?page=1&limit=20
timeout: 5000,
});
axios Instance (Recommended for APIs)
const api = axios.create({
baseURL: 'https://api.example.com',
timeout: 10000,
headers: { 'Content-Type':json();
Production alternative: Set the NODE_EXTRA_CA_CERTS environment variable to point to your CA certificate file instead of disabling verification.
axios
axios is the most popular HTTP client for Node.js and browsers. It has a cleaner API than fetch for many use cases:
npm install axios
import axios from 'axios';
// GET
const { data } = await axios.get('https://api.github.com/users/github');
console.log(data.name);
// POST
const response = await axios.post(const response = await fetch('https://localhost:8443/api/data', { agent });
const data = await response.
Comments