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

corsbridge

v1.0.2

Published

Zero-Config CORS Proxy Client for Developers

Readme

📘 CorsBridge

Zero-Config CORS Proxy Client for Developers

NPM Version NPM Downloads License: MIT

CorsBridge is a lightweight, type-safe CORS proxy client that automatically routes requests through cors.syrins.tech backend.


⚡ Quick Start

Installation

npm install corsbridge

CLI Usage (NEW! 🚀)

You can also use CorsBridge directly from the command line:

# Install globally
npm install -g corsbridge

# Simple GET request
corsbridge https://api.github.com/users/github

# POST request with JSON body
corsbridge https://api.example.com/users -X POST -d '{"name":"John"}'

# With custom headers
corsbridge https://api.example.com/data -H "Authorization: Bearer TOKEN"

# Verbose output
corsbridge https://api.github.com/data -v

# Point to your own proxy
corsbridge https://api.example.com --proxy http://localhost:3000

# Show help
corsbridge --help

Basic Usage (Library)

import { corsFetch } from 'corsbridge';

// Simple GET request
const data = await corsFetch('https://api.github.com/users/github');
console.log(data);

// POST request with body
const response = await corsFetch('https://api.example.com/users', {
  method: 'POST',
  body: { name: 'John Doe' }
});

// With query parameters
const bitcoin = await corsFetch('https://api.coingecko.com/api/v3/simple/price', {
  params: {
    ids: 'bitcoin',
    vs_currencies: 'usd'
  }
});

That's it! No configuration, no API keys, just install and use.


🎯 Features

  • ✅ Zero Config - No setup required
  • 🖥️ CLI Support - Use from command line
  • ✅ Type Safe - Full TypeScript support
  • ✅ Secure - SSRF protection on backend
  • ✅ Fast - Cached responses & optimized
  • ✅ Framework Agnostic - Works everywhere
  • ✅ Error Handling - Structured error types
  • ✅ Browser & Node.js - Universal support

📚 API Reference

corsFetch(url, options?)

Main function to make proxied requests.

interface CorsFetchOptions {
  method?: string;                    // HTTP method (GET, POST, etc.)
  headers?: Record<string, string>;   // Request headers
  body?: any;                         // Request body
  params?: Record<string, any>;       // Query parameters
  timeout?: number;                   // Request timeout (ms)
  responseType?: 'json' | 'text' | 'arrayBuffer' | 'blob';
  proxyUrl?: string;                  // Override proxy endpoint for this call
}

Convenience Methods

import { corsGet, corsPost, corsPut, corsPatch, corsDelete } from 'corsbridge';

// GET
const users = await corsGet('https://api.example.com/users');

// POST
const newUser = await corsPost('https://api.example.com/users', {
  name: 'John',
  email: '[email protected]'
});

// PUT
await corsPut('https://api.example.com/users/1', { name: 'Jane' });

// PATCH
await corsPatch('https://api.example.com/users/1', { email: '[email protected]' });

// DELETE
await corsDelete('https://api.example.com/users/1');

🛡️ Error Handling

CorsBridge maps backend errors to typed error classes:

import {
  corsFetch,
  ValidationError,
  HostBlockedError,
  SSRFBlockedError,
  InvalidURLError,
  RateLimitError,
  TimeoutError,
  TargetError,
  NetworkError
} from 'corsbridge';

try {
  const data = await corsFetch('https://api.example.com/data');
} catch (error) {
  if (error instanceof HostBlockedError) {
    console.error('Host blocked (private IP/localhost):', error.message);
    console.error('Request ID:', error.requestId);
  } else if (error instanceof SSRFBlockedError) {
    console.error('SSRF attempt blocked:', error.message);
  } else if (error instanceof InvalidURLError) {
    console.error('URL too long or invalid:', error.message);
  } else if (error instanceof ValidationError) {
    console.error('Validation error:', error.message);
    console.error('Status:', error.statusCode); // 400, 403, 414
  } else if (error instanceof RateLimitError) {
    console.error('Rate limit exceeded (429)');
    if (error.details?.retryAfter) {
      console.error('Retry after:', error.details.retryAfter, 'seconds');
    }
  } else if (error instanceof TimeoutError) {
    console.error('Request timeout (504)');
  } else if (error instanceof TargetError) {
    console.error('Target server error (502)');
  } else if (error instanceof NetworkError) {
    console.error('Network connection failed');
  }
}

Error Types

| Error Class | Status Code | Description | |------------|-------------|-------------| | ValidationError | 400, 403, 414 | Base validation error | | HostBlockedError | 403 | Private IP, localhost, internal hosts | | SSRFBlockedError | 403 | SSRF attempt detected | | InvalidURLError | 414 | URL exceeds maximum length | | PayloadTooLargeError | 413 | Request body too large | | RateLimitError | 429 | Rate limit exceeded | | TargetError | 502 | Target server error (alias: BadGatewayError) | | TimeoutError | 504 | Request timeout (alias: GatewayTimeoutError) | | NetworkError | - | Client-side network error |

Note: HostBlockedError, SSRFBlockedError, and InvalidURLError all extend ValidationError, so you can catch them individually or as ValidationError.

All errors expose requestId, traceId, and spanId fields when the backend provides them, making it straightforward to correlate failures with proxy logs.


⚙️ Advanced Usage

With Authentication

await corsFetch('https://api.example.com/protected', {
  headers: {
    'Authorization': 'Bearer YOUR_TOKEN'
  }
});

With Timeout

await corsFetch('https://slow-api.com/data', {
  timeout: 10000 // 10 seconds
});

### Custom Proxy Endpoint

Point the client to your self-hosted backend without touching global env vars:

```typescript
await corsFetch('https://api.example.com/data', {
  proxyUrl: 'https://my-proxy.internal'
});

Or set CORS_PROXY_URL once in your environment (works for both the library and CLI):

export CORS_PROXY_URL="https://proxy.example.com"

### Different Response Types

```typescript
// Text
const html = await corsFetch('https://example.com', {
  responseType: 'text'
});

// Binary
const buffer = await corsFetch('https://example.com/file.pdf', {
  responseType: 'arrayBuffer'
});

// Blob
const image = await corsFetch('https://example.com/image.png', {
  responseType: 'blob'
});

🎨 Framework Examples

React

import { useEffect, useState } from 'react';
import { corsFetch } from 'corsbridge';

function App() {
  const [data, setData] = useState(null);

  useEffect(() => {
    corsFetch('https://api.github.com/users/github')
      .then(setData)
      .catch(console.error);
  }, []);

  return <div>{JSON.stringify(data)}</div>;
}

Vue 3

<script setup>
import { ref, onMounted } from 'vue';
import { corsFetch } from 'corsbridge';

const data = ref(null);

onMounted(async () => {
  data.value = await corsFetch('https://api.github.com/users/github');
});
</script>

<template>
  <div>{{ data }}</div>
</template>

Next.js

'use client';
import { useEffect, useState } from 'react';
import { corsFetch } from 'corsbridge';

export default function Page() {
  const [data, setData] = useState(null);
  
  useEffect(() => {
    corsFetch('https://api.example.com/data').then(setData);
  }, []);
  
  return <div>{JSON.stringify(data)}</div>;
}

🔐 Security

CorsBridge backend includes:

  • ✅ SSRF protection (blocks private IPs)
  • ✅ URL validation & sanitization
  • ✅ Rate limiting
  • ✅ Header filtering
  • ✅ Request size limits
  • ✅ Timeout enforcement

All requests are validated server-side before proxying.


🌐 Backend Integration

This package works with the CorsBridge backend at cors.syrins.tech.

Backend features:

  • Express.js + TypeScript
  • Redis caching
  • Rate limiting (per IP)
  • Circuit breakers
  • Health checks
  • Prometheus metrics
  • Comprehensive logging

📄 License

MIT License - see LICENSE file


🔗 Links


💖 Support

If you find this useful, please ⭐ the repo!

☕ Buy me a coffee