A better fetch API. Works on node, browser and workers.
ofetch is a modern HTTP client library that wraps the native Fetch API with developer-friendly enhancements and intelligent defaults. It addresses common pain points in fetch usage like manual JSON parsing, inconsistent error handling, and environment-specific compatibility issues. With over 4 million weekly downloads, it's become a foundational dependency in the Nuxt.js ecosystem and many other JavaScript projects.
The library automatically parses JSON responses using the destr library, which safely handles edge cases and falls back to text when parsing fails. Unlike native fetch, ofetch throws errors when responses aren't successful (response.ok is false), eliminating the need for manual status code checking. It provides a unified API that works identically across Node.js, browsers, and web workers, with conditional exports that apply platform-specific optimizations automatically.
ofetch shines in modern application architectures where you need consistent HTTP handling across multiple environments. Its TypeScript-first design provides full type safety with generic support, while features like request/response interceptors enable advanced patterns like authentication token injection, request retry logic, and centralized error handling. The ability to create customized fetch instances with preset configurations makes it particularly useful for managing multiple API endpoints with different base URLs and authentication schemes.
import { ofetch } from 'ofetch';
// Create a configured instance with base URL and interceptors
const api = ofetch.create({
baseURL: 'https://api.example.com',
async onRequest({ request, options }) {
const token = await getAuthToken();
options.headers = {
...options.headers,
Authorization: `Bearer ${token}`
};
},
async onResponseError({ response }) {
if (response.status === 401) {
await refreshToken();
throw new Error('Token expired, retry needed');
}
}
});
// Make requests with automatic JSON handling
const users = await api('/users', {
query: { page: 1, limit: 10 }
});
// POST with automatic body serialization
const newUser = await api('/users', {
method: 'POST',
body: { name: 'John Doe', email: 'john@example.com' }
});
// Handle errors with rich context
try {
await api('/protected-resource');
} catch (error) {
console.error(error.data); // Parsed error response body
console.error(error.status); // HTTP status code
}
// Mock function placeholders for example
async function getAuthToken() { return 'token123'; }
async function refreshToken() { /* refresh logic */ }API client libraries: Build type-safe API wrappers for your services with automatic JSON serialization, error handling, and response transformation using interceptors.
Universal SSR applications: Handle data fetching in frameworks like Nuxt.js or Next.js where the same code runs on both server and client, benefiting from automatic environment detection and optimizations.
Microservice communication: Create pre-configured fetch instances for different services with specific base URLs, authentication headers, and timeout settings, reducing boilerplate across your codebase.
Request/response transformation pipelines: Implement authentication token refresh flows, request logging, error tracking integration, and response caching using the lifecycle hook system.
Binary data handling: Download or upload files, images, and streams with automatic duplex configuration and proper handling of Buffer, ReadableStream, and other binary response types.
npm install ofetchpnpm add ofetchbun add ofetch