Typed requests.
Clear results.

One reusable client for your API. Typed results, thoughtful defaults, and room for your own conventions.

TypeScript-first. Fetch-native.

bun add fetchzen

Version 0.2.0 · Not published yet

One client. Your API.client.ts
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");
// ^ User
An envelope by default. The payload type is yours.
  1. fetch
  2. Your preset
  3. Typed result

¹ Local build, browser GET + JSON fixture. Not the published release. Measurement details

Choose your shape.
Keep your flow.

Less wrapper code. More application code.

Keep the platform primitives. Add the behavior your application needs without making a new wrapper for every project.

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

Failure is part of the API.

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

Bring your own validator.

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

Real bytes. Honest progress.

Count only the bytes your server acknowledges. An opt-in chunk convention, not simulated Fetch upload events.

uploadConfirmed(file, { sendChunk }) Explore confirmed uploads

Small footprint.
Visible tradeoffs.

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.

What ships to the browser

kB, minified + gzip · lower is smaller
fetchzen Local 0.2.0
6.41 kB
axios 1.20.0
19.64 kB
Native fetch Bun 1.4.4
0.13 kB

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.

Measured · Bun 1.4.4 · Apple M4 ProHow we measured
Methodology, exact results, and reproduction

Browser bundle

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.

Client overhead

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.

Limits of this snapshot

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.

Min/max are sample means, not request percentiles. Lower is not necessarily better for your use case.
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.mjs
bun benchmarks/run.mjs
bun benchmarks/verify.mjs

More than a size contest.

Choose the right abstraction

These clients make different choices. Here is what each provides directly, and what you would wire up yourself.

“Custom” means implementable in application code, not impossible. Validation requires a compatible schema; progress support depends on the runtime.
Capability fetchzen0.2.0 · local build Axios1.20.0 fetchWeb platform
Transport Native fetchXHR / HTTP / fetchNative fetch
Typed response presets 4 + custom presetsTransforms / wrapperCustom wrapper
Request lifecycle Async hooksInterceptorsCustom wrapper
Automatic retry Built-in optionPlugin / custom codeCustom code
Standard Schema validation Built inCustom integrationCustom integration
Data / error object api.safeCustom wrapperCustom wrapper
Download progress Built inBuilt inRead the stream
Native upload events Not built inAdapter-dependentCustom code
Server-confirmed uploads Chunk receiptsCustom codeCustom code

When would you choose something else?

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.

Start with one request.

No framework required

Set a base URL. Choose your conventions. Keep your stack.