Your API sets the shape.
Envelope, raw body, REST-style metadata, or problem details. Pick a preset or define a typed shape of your own.
preset: bare Explore presets One reusable client for your API. Typed results, thoughtful defaults, and room for your own conventions.
TypeScript-first. Fetch-native.
Version 0.2.0 · Not published yet
import { Http } from "fetchzen";
type User = { id: number; name: string };
const api = Http.create("https://api.example.com", { timeout: 5000, retry: 2,});
const { payload } = await api.get<User>("/me");// ^ Userimport { Http } from "fetchzen";
type User = { id: number; name: string };const api = Http.create("https://api.example.com");
const { data, error } = await api.safe.get<User>("/me");
if (error) { console.error(error.message);} else { console.log(data.payload.name);}import { Http, bare } from "fetchzen";
type User = { id: number; name: string };
const api = Http.create("https://api.example.com", { preset: bare, cache: false,});
const user = await api.get<User>("/me");// ^ User — just the parsed body
// Also included: envelope, rest, problem.fetch¹ Local build, browser GET + JSON fixture. Not the published release. Measurement details
Less wrapper code. More application code.
Keep the platform primitives. Add the behavior your application needs without making a new wrapper for every project.
Envelope, raw body, REST-style metadata, or problem details. Pick a preset or define a typed shape of your own.
preset: bare Explore presets Keep status, cause, response, and request context together. Handle errors as values when that fits your code.
const { data: result, error } = await api.safe.get("/me"); Handle errors Validate with Standard Schema-compatible tools such as Zod or Valibot. Your validator stays a separate dependency.
api.get("/me", { schema: User }) Validate a response Count only the bytes your server acknowledges. An opt-in chunk convention, not simulated Fetch upload events.
uploadConfirmed(file, { sendChunk }) Explore confirmed uploads The cost of a client
Bundle size is one part of the decision. Compare the code you ship, the work per request, and the dependencies you take on.
Same bundler, separate GET + JSON entrypoints. Includes client code and the request wrapper. Native fetch is built into the runtime; its bar is only the wrapper.
An in-memory test, not network speed. Median of sample means for GET + JSON, run in Bun with retries and timeouts disabled.
Package-level runtime dependencies, not transitive packages or code retained in your browser bundle. Axios also supports Node-specific transports.
Bun.build 1.4.4, minified ESM, gzip level 9. Separate exported GET + JSON functions with runtime URLs. Defaults remain in the size fixtures; HTTP uses the bare preset. Decimal kB = 1,000 bytes.
500 warmups, 9 samples of 2,000 sequential operations per client. Identical 103-byte JSON responses, parsing and payload checks. No DNS, TLS, server, or network latency.
macOS arm64, Apple M4 Pro. Browser bundles executed in Bun, not browser-engine timings. Reused instances; no retries or timeouts. These results do not measure uploads, failed requests, or end-to-end latency.
| Client | Minified bytes | Gzip bytes | Median µs/op | Min–max µs/op |
|---|---|---|---|---|
| fetchzen | 16,659 | 6,412 | 2.234 | 2.036–2.434 |
| axios | 52,184 | 19,639 | 14.064 | 13.000–15.618 |
| Native fetch | 118 | 129 | 0.623 | 0.496–0.651 |
FetchZen is measured from the local working tree, not the npm release with the same version. Source fingerprint: 3bee026ba3b20117a78c03024b7cf17cc138a0f9aa7cd47360d203b54538e588 . Timing varies with CPU load, garbage collection, and runtime. No statistical significance is claimed.
bun benchmarks/install-isolated.mjsbun benchmarks/run.mjsbun benchmarks/verify.mjsChoose the right abstraction
These clients make different choices. Here is what each provides directly, and what you would wire up yourself.
| Capability | fetchzen0.2.0 · local build | Axios1.20.0 | fetchWeb platform |
|---|---|---|---|
| Transport | Native fetch | XHR / HTTP / fetch | Native fetch |
| Typed response presets | 4 + custom presets | Transforms / wrapper | Custom wrapper |
| Request lifecycle | Async hooks | Interceptors | Custom wrapper |
| Automatic retry | Built-in option | Plugin / custom code | Custom code |
| Standard Schema validation | Built in | Custom integration | Custom integration |
| Data / error object | api.safe | Custom wrapper | Custom wrapper |
| Download progress | Built in | Built in | Read the stream |
| Native upload events | Not built in | Adapter-dependent | Custom code |
| Server-confirmed uploads | Chunk receipts | Custom code | Custom code |
References: FetchZen docsAxios 1.20.0 Fetch API
Use native fetch when a few requests and your own error handling are enough. Axios offers a mature interceptor ecosystem and multiple transport adapters. Choose this client when typed response conventions and an integrated error model are the parts you want to stop rebuilding.
No framework required
Set a base URL. Choose your conventions. Keep your stack.