fetch() is everywhere now — but it's still verbose. No auto-retry, no JSON parsing, no error throwing, no interceptors. ofetch adds all of that in 1KB.
What Is ofetch?
ofetch is a better fetch API from the UnJS ecosystem. It works in Node.js, browsers, service workers, and edge runtimes — with auto-JSON, retries, and interceptors built in.
Quick Start
npm install ofetch
import { ofetch } from 'ofetch';
// Auto-parses JSON, throws on errors, retries on failure
const data = await ofetch('/api/users');
// No need for: const res = await fetch(); if (!res.ok) throw; const data = await res.json();
Why ofetch Over fetch()
// Native fetch — 6 lines for a simple GET
const res = await fetch('https://api.example.com/users');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
// ofetch — 1 line, same result
const data = await ofetch('https://api.example.com/users');
Key Features
Auto JSON
// Response automatically parsed as JSON
const users = await ofetch('/api/users');
// Request body automatically serialized
await ofetch('/api/users', {
method: 'POST',
body: { name: 'John', email: 'john@example.com' },
// Content-Type: application/json set automatically
});
Auto Retry
// Retries 1 time by default on network errors
const data = await ofetch('/api/flaky-endpoint');
// Custom retry count
const data = await ofetch('/api/endpoint', { retry: 3 });
// Custom retry delay
const data = await ofetch('/api/endpoint', {
retry: 3,
retryDelay: 1000, // 1 second between retries
});
Error Handling
try {
const data = await ofetch('/api/users/999');
} catch (error) {
// error.status — HTTP status code
// error.data — parsed response body
// error.message — "404 Not Found"
console.log(error.status); // 404
console.log(error.data); // { message: "User not found" }
}
Interceptors
const api = ofetch.create({
baseURL: 'https://api.example.com',
onRequest({ options }) {
options.headers.set('Authorization', `Bearer ${getToken()}`);
},
onResponse({ response }) {
console.log(`${response.status} ${response.url}`);
},
onResponseError({ response }) {
if (response.status === 401) {
refreshToken();
}
},
});
const users = await api('/users');
Query Parameters
const users = await ofetch('/api/users', {
query: {
page: 1,
limit: 10,
sort: 'name',
filter: ['active', 'verified'],
},
});
// GET /api/users?page=1&limit=10&sort=name&filter=active&filter=verified
Comparison
| Feature | ofetch | fetch | axios |
|---|---|---|---|
| Auto JSON | Yes | No | Yes |
| Auto retry | Yes | No | Plugin |
| Error throwing | Yes | No | Yes |
| Interceptors | Yes | No | Yes |
| Bundle size | 1KB | 0 | 13KB |
| Node.js | Yes | 18+ | Yes |
| Edge/Workers | Yes | Yes | No |
| TypeScript | First-class | Basic | Good |
Get Started
- GitHub — 4K+ stars
- Docs
- UnJS ecosystem
Fetching data from APIs? My Apify scrapers handle the heavy lifting. Custom solutions: spinov001@gmail.com
Top comments (0)