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

@proxyscrape_org/sdk

v1.0.3

Published

Official ProxyScrape JavaScript / TypeScript SDK. Free proxy list, proxy checker, residential / datacenter / dedicated / mobile proxies, and SERP API — one client.

Readme

proxyscrape

Official ProxyScrape JavaScript / TypeScript SDK. Free proxy list, one-call proxy fetch, and public-IP lookup — one fully-typed client.

npm version Downloads Bundle size Node CI License: MIT Types: TypeScript ProxyScrape

Install

npm install @proxyscrape_org/sdk
# or
pnpm add @proxyscrape_org/sdk
# or
yarn add @proxyscrape_org/sdk

Or drop it in a browser without a build step

<script src="https://cdn.jsdelivr.net/npm/@proxyscrape_org/sdk@latest/dist/proxyscrape.min.js"></script>
<script>
  // The IIFE bundle exposes a namespace at `window.ProxyScrape`.
  // Construct the client via `.ProxyScrape`; error classes live alongside it.
  const ps = new ProxyScrape.ProxyScrape();
  ps.proxy({ country: 'us' }).then((p) => console.log(p?.url));

  try { /* ... */ } catch (e) {
    if (e instanceof ProxyScrape.NetworkError) console.warn('Network down');
  }
</script>

The minified bundle is ~10 KB and runs identically in modern browsers, Bun, Deno, and any environment with fetch.

Node 18+ (uses native fetch). Works in Bun, Deno, and modern browsers. Ships ESM + CJS + a minified IIFE bundle, all with types.

Quick start

import { ProxyScrape } from '@proxyscrape_org/sdk';

const ps = new ProxyScrape();

// One-liner: give me a working US elite proxy
const p = await ps.proxy({ country: 'us', anonymity: 'elite' });
if (p) console.log(p.url); // → "socks5://1.2.3.4:1080"

// Or a full page with filters + pagination metadata
const { proxies, totalRecords } = await ps.free.list({
  protocol: 'socks5',
  country: 'us',
  anonymity: 'elite',
  minUptimePercent: 70,
  limit: 100,
});

console.log(`${totalRecords} matches; first 3:`);
for (const proxy of proxies.slice(0, 3)) {
  console.log(`${proxy.url}  ${proxy.country}/${proxy.city}  uptime=${proxy.uptimePercent}%`);
}

Verify a proxy actually works

const before = await ps.getPublicIp();
console.log('Real IP:', before.ip);

const proxy = await ps.proxy({ anonymity: 'elite' });
// ... route a request through proxy.url using your HTTP client of choice ...
// then re-call getPublicIp via that route. If the IP didn't change,
// the proxy is transparent or broken.

getPublicIp() defaults to ipinfo.io's free tier (no key needed up to 50k req/month). For production volume, pass an ipinfoToken or override the endpoint entirely.

Stream every match (no manual pagination)

for await (const p of ps.free.stream({ protocol: 'http', country: 'de' })) {
  console.log(p.url);
  // stop whenever you want — the iterator stops fetching pages on `break`
}

Random pick (for one-off use)

const p = await ps.free.random({ anonymity: 'elite', country: 'jp' });
if (p) {
  // p.url, p.ip, p.port, p.countryCode, p.anonymity, p.uptimePercent, ...
}

Text / CSV export (no JSON round-trip)

const txt = await ps.free.listText({ protocol: 'socks5' });
// "socks5://1.2.3.4:1080\nsocks5://5.6.7.8:1080\n..."

const csv = await ps.free.listCsv({ protocol: 'http' });
// "protocol,ip,port,country,...\nhttp,1.2.3.4,8080,US,...\n"

Module surface

The SDK is intentionally namespaced so every ProxyScrape product gets one entry point on the client.

| Surface | What's there | |---|---| | ps.proxy(filters?) | one-call shortcut for ps.free.random() | | ps.getPublicIp(opts?) | IP + geo via ipinfo (default) or ipify | | ps.free | list, stream, random, listText, listCsv |

More ProxyScrape products will land on the same client over upcoming versions — the namespaced shape means they slot in without breaking the existing API.

Configuration

const ps = new ProxyScrape({
  baseUrl: 'https://api.proxyscrape.com/v4', // override for staging / mocks
  timeoutMs: 15_000,                         // per-request, default 30s
  maxRetries: 3,                             // 5xx / 429 / network. Default 3
  userAgent: 'my-app/1.0',                   // appended after our SDK UA
  fetch: customFetch,                        // bring your own (undici, mocks…)
});

Errors

Every error inherits from ProxyScrapeError. Discriminate by subclass:

import { ProxyScrape, RateLimitError, NetworkError } from '@proxyscrape_org/sdk';

try {
  await ps.free.list({ country: 'us' });
} catch (err) {
  if (err instanceof RateLimitError) {
    console.warn(`Backed off too aggressively, retry in ${err.retryAfterSeconds}s`);
  } else if (err instanceof NetworkError) {
    console.error('Network down', err.message);
  } else {
    throw err;
  }
}

Cancellation

Pass any AbortSignal to abort mid-flight:

const ctrl = new AbortController();
setTimeout(() => ctrl.abort(), 5_000);

const { proxies } = await ps.free.list({ country: 'us' }, { signal: ctrl.signal });

Why one client class

Grouping calls under a namespace like ps.free.list() keeps things tidy, and lets tree-shakers drop the modules you don't use (import the module class directly: import { FreeProxyListClient } from '@proxyscrape_org/sdk').

Privacy & what we transmit

Every API call from this SDK contains exactly what you put in it — no version pings, no client IDs, no _referrer query params, no anonymous telemetry. Open your network tab and verify.

getPublicIp() reaches out to a third-party (ipinfo.io by default, ipify if you ask for it) — that request goes from your machine directly to the chosen provider. If you'd rather avoid the third-party entirely, point endpoint at your own IP-echo service.

Development

git clone https://github.com/ProxyScrape/proxyscrape-sdk.git
cd proxyscrape-sdk
npm install

npm run typecheck   # tsc --noEmit
npm run lint        # biome check
npm run test        # vitest run
npm run build       # tsup -> dist/{index.js,index.cjs,index.d.ts}
npm run ci          # all of the above, in order

Integration tests that hit the real API are gated by SDK_RUN_INTEGRATION=1 so default npm test stays hermetic.

Releases

Managed by changesets. Every PR touching src/ should ship a changeset:

npm run changeset           # interactive prompt; creates .changeset/<id>.md
git add .changeset

The Release workflow opens a "Version Packages" PR collecting pending changesets. Merging that PR publishes to npm with provenance.

License

MIT — see LICENSE.

Links