npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

zipfetch

v1.0.2

Published

Ultra-fast, lightweight HTTP client built on native fetch - retries, interceptors, caching, rate limiting

Readme

zipfetch

Ultra-fast, lightweight HTTP client built on native fetch - retries, interceptors, caching, rate limiting

npm version License: MIT

Why zipfetch?

  • Tiny: ~5KB minified (vs Axios 29KB, Got 48KB)
  • Zero dependencies: Built on native fetch (Node 18+)
  • Modern: ESM, TypeScript, async/await
  • Powerful: Retries, interceptors, caching, rate limiting
  • Familiar API: Similar to Axios, easy to migrate

Installation

npm install zipfetch

Quick Start

import zipfetch from 'zipfetch';

// Simple GET request
const { data } = await zipfetch.get('https://api.example.com/users');

// POST with data
const { data: user } = await zipfetch.post('https://api.example.com/users', {
  name: 'John',
  email: '[email protected]'
});

// With query params
const { data: results } = await zipfetch.get('https://api.example.com/search', {
  params: { q: 'typescript', page: 1 }
});

Comparison with Alternatives

| Feature | zipfetch | Axios | Got | node-fetch | |---------|----------|-------|-----|------------| | Size (gzip) | ~5KB | 29KB | 48KB | 8KB | | Dependencies | 0 | 8 | 11 | 0 | | Native fetch | Yes | No | No | Polyfill | | Retries | Built-in | No | Yes | No | | Interceptors | Yes | Yes | Hooks | No | | Caching | Built-in | No | Plugin | No | | Rate Limiting | Built-in | No | Plugin | No | | Progress Tracking | Built-in | Yes | Yes | No | | Request Cancellation | Built-in | Yes | Yes | No | | Streaming | Built-in | Yes | Yes | No | | Auth Helpers | Built-in | Yes | No | No | | Deduplication | Built-in | No | No | No | | Concurrency Control | Built-in | No | Plugin | No | | TypeScript | Yes | Yes | Yes | @types | | Node 18+ | Yes | Yes | Yes | Yes | | Browser | Yes | Yes | No | No |

API Reference

Creating an Instance

import { create } from 'zipfetch';

const api = create({
  baseURL: 'https://api.example.com',
  timeout: 10000,
  headers: {
    'Authorization': 'Bearer token'
  }
});

const { data } = await api.get('/users');

Request Methods

zipfetch.get(url, config?)
zipfetch.post(url, data?, config?)
zipfetch.put(url, data?, config?)
zipfetch.patch(url, data?, config?)
zipfetch.delete(url, config?)
zipfetch.head(url, config?)
zipfetch.options(url, config?)

Request Config

interface RequestConfig {
  url?: string;
  method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
  baseURL?: string;
  headers?: Record<string, string>;
  params?: Record<string, string | number | boolean>;
  data?: unknown;
  timeout?: number;
  retry?: {
    attempts?: number;
    delay?: number;
    backoff?: 'linear' | 'exponential';
    retryOn?: number[];
  };
  cache?: boolean;
  responseType?: 'json' | 'text' | 'blob' | 'arrayBuffer' | 'stream';
  auth?: {
    type: 'bearer' | 'basic' | 'custom';
    token?: string;
    username?: string;
    password?: string;
    headerValue?: string;
  };
  onUploadProgress?: (event: ProgressEvent) => void;
  onDownloadProgress?: (event: ProgressEvent) => void;
  skipDedupe?: boolean;
}

Instance Config

interface ZipFetchConfig {
  baseURL?: string;
  timeout?: number;
  headers?: Record<string, string>;
  retry?: RetryConfig;
  cache?: CacheConfig;
  rateLimit?: RateLimitConfig;
  concurrency?: number;      // Max concurrent requests
  dedupe?: boolean;          // Deduplicate identical in-flight requests
  auth?: AuthConfig;         // Default auth for all requests
}

Response Object

interface ZipResponse<T> {
  data: T;
  status: number;
  statusText: string;
  headers: Headers;
  config: RequestConfig;
  duration: number;          // Request duration in milliseconds
}

Features

Automatic Retries

import { create } from 'zipfetch';

const api = create({
  retry: {
    attempts: 3,              // Retry up to 3 times
    delay: 1000,              // Start with 1 second delay
    backoff: 'exponential',   // 1s, 2s, 4s
    retryOn: [500, 502, 503]  // Retry on these status codes
  }
});

// Will automatically retry on failure
const { data } = await api.get('/flaky-endpoint');

Interceptors

import zipfetch from 'zipfetch';

// Request interceptor
zipfetch.interceptors.request.use((config) => {
  config.headers = {
    ...config.headers,
    'X-Request-ID': crypto.randomUUID()
  };
  return config;
});

// Response interceptor
zipfetch.interceptors.response.use((response) => {
  console.log(`Response: ${response.status}`);
  return response;
});

// Error interceptor
zipfetch.interceptors.error.use((error) => {
  if (error.status === 401) {
    // Handle unauthorized
    window.location.href = '/login';
  }
  return error;
});

Response Caching

import { create } from 'zipfetch';

const api = create({
  cache: {
    enabled: true,
    ttl: 60000,           // Cache for 60 seconds
    methods: ['GET']      // Only cache GET requests
  }
});

// First request hits the network
await api.get('/users');

// Second request returns cached response
await api.get('/users');

// Clear cache manually
api.clearCache();

Rate Limiting

import { create } from 'zipfetch';

const api = create({
  rateLimit: {
    requests: 10,       // Max 10 requests
    interval: 1000      // Per second
  }
});

// Requests will automatically queue if rate limit is exceeded
for (let i = 0; i < 20; i++) {
  api.get('/endpoint'); // Will spread across 2 seconds
}

Timeout

import zipfetch from 'zipfetch';

try {
  await zipfetch.get('/slow-endpoint', {
    timeout: 5000  // 5 second timeout
  });
} catch (error) {
  if (error.code === 'TIMEOUT') {
    console.log('Request timed out');
  }
}

Authentication

Built-in auth helpers for Bearer, Basic, and custom authentication:

import { create } from 'zipfetch';

// Bearer token authentication
const api = create({
  baseURL: 'https://api.example.com',
  auth: {
    type: 'bearer',
    token: 'your-jwt-token'
  }
});

// Basic authentication
const api = create({
  auth: {
    type: 'basic',
    username: 'user',
    password: 'pass'
  }
});

// Custom header value
const api = create({
  auth: {
    type: 'custom',
    headerValue: 'ApiKey your-api-key'
  }
});

// Per-request auth override
await api.get('/protected', {
  auth: { type: 'bearer', token: 'different-token' }
});

Progress Tracking

Track upload and download progress for large files:

import zipfetch from 'zipfetch';

// Upload progress
await zipfetch.post('/upload', largeFile, {
  onUploadProgress: (event) => {
    console.log(`Uploaded: ${event.percent.toFixed(1)}%`);
    console.log(`${event.loaded} / ${event.total} bytes`);
  }
});

// Download progress
await zipfetch.get('/large-file', {
  onDownloadProgress: (event) => {
    console.log(`Downloaded: ${event.percent.toFixed(1)}%`);
  }
});

Request Cancellation

Cancel in-flight requests using CancelToken:

import { ZipFetch } from 'zipfetch';

// Create a cancel token
const source = ZipFetch.CancelToken.source();

// Make request with cancel token
const promise = zipfetch.get('/slow-endpoint', {
  signal: source.token.controller.signal
});

// Cancel the request
source.cancel('User cancelled');

// Check if cancelled
if (source.token.isCancelled) {
  console.log('Request was cancelled:', source.token.reason);
}

Streaming Responses

Get the raw response stream for large files or real-time data:

import zipfetch from 'zipfetch';

const { data: stream } = await zipfetch.get('/stream', {
  responseType: 'stream'
});

// Process the ReadableStream
const reader = stream.getReader();
while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  console.log('Received chunk:', value);
}

Request Deduplication

Automatically deduplicate identical in-flight GET requests:

import { create } from 'zipfetch';

const api = create({
  dedupe: true  // Enabled by default
});

// These two calls will result in only ONE network request
const [res1, res2] = await Promise.all([
  api.get('/users'),
  api.get('/users')  // Returns same promise as first call
]);

// Disable for specific requests
await api.get('/users', { skipDedupe: true });

Concurrency Control

Limit the number of concurrent requests:

import { create } from 'zipfetch';

const api = create({
  concurrency: 5  // Max 5 concurrent requests
});

// Only 5 requests will be in-flight at once
// Others will queue and execute as slots become available
const promises = urls.map(url => api.get(url));
await Promise.all(promises);

Error Handling

import zipfetch, { ZipError } from 'zipfetch';

try {
  await zipfetch.get('/not-found');
} catch (error) {
  if (error instanceof ZipError) {
    console.log(error.status);      // 404
    console.log(error.response);    // Full response object
    console.log(error.config);      // Request config
    console.log(error.code);        // 'TIMEOUT' | 'NETWORK' | 'ABORT' | undefined
  }
}

FormData & File Uploads

import zipfetch from 'zipfetch';

const formData = new FormData();
formData.append('file', fileInput.files[0]);
formData.append('name', 'My File');

const { data } = await zipfetch.post('/upload', formData);
// Content-Type is automatically set to multipart/form-data

Migration from Axios

// Axios
import axios from 'axios';
const api = axios.create({ baseURL: 'https://api.example.com' });
const { data } = await api.get('/users');

// zipfetch
import { create } from 'zipfetch';
const api = create({ baseURL: 'https://api.example.com' });
const { data } = await api.get('/users');

Migration from node-fetch

// node-fetch
import fetch from 'node-fetch';
const response = await fetch('https://api.example.com/users');
const data = await response.json();

// zipfetch
import zipfetch from 'zipfetch';
const { data } = await zipfetch.get('https://api.example.com/users');

TypeScript

Full TypeScript support with generics:

import zipfetch from 'zipfetch';

interface User {
  id: number;
  name: string;
  email: string;
}

// Type-safe response
const { data } = await zipfetch.get<User[]>('/users');
data.forEach(user => console.log(user.name));

// Type-safe post
const { data: newUser } = await zipfetch.post<User>('/users', {
  name: 'John',
  email: '[email protected]'
});

Browser Support

Works in all modern browsers that support native fetch:

  • Chrome 42+
  • Firefox 39+
  • Safari 10.1+
  • Edge 14+

For older browsers, use a fetch polyfill.

Node.js Support

Requires Node.js 18+ (native fetch support).

Support

If zipfetch saved you time and made HTTP requests easier, consider supporting the project:

License

MIT


Made for speed and simplicity