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

libping

v1.0.0

Published

Browser Trickle ICE latency probes for WebRTC STUN gateways — pick the fastest regional gateway without a full WebRTC call.

Downloads

172

Readme

libping

Measure UDP latency to WebRTC STUN gateways in the browser using Trickle ICE — without a full WebRTC call, signaling, or microphone access.

Use it to pick the fastest regional media gateway before connecting.

Install

npm install libping

Browser (jsDelivr):

<script src="https://cdn.jsdelivr.net/npm/libping/libping.js"></script>
<script>
  const { pingGateways, TWILIO_GATEWAYS } = LibPing;
</script>

Requirements

  • A secure context: https:// or http://localhost
  • A browser with RTCPeerConnection (Chrome, Firefox, Safari, Edge)

Quick start

import LibPing from 'libping';

const results = await LibPing.pingGateways(LibPing.TWILIO_GATEWAYS);
const fastest = results.find((r) => r.rtt < Infinity);

console.log(fastest?.code, fastest?.rtt); // e.g. "ie1", 42

Pass your own gateways:

const gateways = [
  { code: 'us1', region: 'US East', url: 'stun:ashburn.stun.twilio.com:3478' },
  { code: 'de1', region: 'Europe', url: 'stun:frankfurt.stun.twilio.com:3478' },
];

const results = await LibPing.pingGateways(gateways);

Each result includes your gateway fields plus:

| Field | Type | Description | |-------|------|-------------| | rtt | number | Estimated RTT in ms, or Infinity if unreachable | | status | 'success' \| 'timeout' \| 'failed' | Probe outcome |

Results are sorted fastest first.

How it works

  1. Create an isolated RTCPeerConnection pinned to one STUN server.
  2. Open a dummy data channel (no mic/camera permission).
  3. Generate a local offer and call setLocalDescription() to start ICE gathering.
  4. On the first server-reflexive (srflx) candidate, record elapsed time and close the connection immediately.
  5. Estimate RTT as elapsed − 15ms (browser ICE thread overhead).

No SDP answer is sent. No media flows.

API

pingGateways(gateways, options?)

Probe all gateways and return sorted results.

gateways — non-empty array of { url: string, code?: string, region?: string, ... }.

options

| Option | Default | Description | |--------|---------|-------------| | warmup | false | One discarded probe per unique hostname before measuring (dedupes shared domains) | | randomOrder | false | Shuffle probe order each round | | rounds | 1 | Repeat count; values > 1 probe sequentially and rank by median RTT | | timeoutMs | 1500 | Per-gateway timeout (ms) | | roundSettleMs | 100 | Pause between rounds when rounds > 1 |

Execution strategy

| rounds | randomOrder | Behavior | |----------|---------------|----------| | 1 | false | All gateways in parallel (fastest) | | 1 | true | One sequential pass in shuffled order | | > 1 | either | Sequential each round; median RTT when rounds > 1 |

// Warm DNS/ICE cache, then measure
await LibPing.pingGateways(gateways, { warmup: true });

// Robust selection: 3 shuffled rounds, median RTT
const results = await LibPing.pingGateways(LibPing.TWILIO_GATEWAYS, {
  warmup: true,
  randomOrder: true,
  rounds: 3,
});

When rounds > 1, each result also includes samples, successCount, and rounds.

TWILIO_GATEWAYS

Default Twilio regional STUN endpoints:

| Code | Region | STUN URL | |------|--------|----------| | us1 | US East (Ashburn) | stun:ashburn.stun.twilio.com:3478 | | us2 | US West (Oregon) | stun:umatilla.stun.twilio.com:3478 | | de1 | Europe (Frankfurt) | stun:frankfurt.stun.twilio.com:3478 | | ie1 | Europe (Ireland) | stun:dublin.stun.twilio.com:3478 | | jp1 | Asia Pacific (Tokyo) | stun:tokyo.stun.twilio.com:3478 | | sg1 | Asia Pacific (Singapore) | stun:singapore.stun.twilio.com:3478 | | au1 | Australia (Sydney) | stun:sydney.stun.twilio.com:3478 | | br1 | South America (São Paulo) | stun:sao-paulo.stun.twilio.com:3478 | | in1 | India (Mumbai) | stun:mumbai.stun.twilio.com:3478 |

parseStunHostname(url)

Extract the hostname from a stun:, stuns:, turn:, or turns: URL.

uniqueGatewaysByDomain(gateways)

Return one gateway per unique hostname — used internally for warmup deduplication.

Constants

  • ICE_OVERHEAD_MS — 15
  • PROBE_TIMEOUT_MS — 1500

CommonJS

const LibPing = require('libping');

LibPing.pingGateways(LibPing.TWILIO_GATEWAYS).then(console.log);

Limitations

What is measured: time to first srflx candidate, not pure ICMP-style RTT. This includes browser ICE overhead and, on a cold DNS cache, hostname resolution (~50–150 ms). Use { warmup: true } or { rounds: 2 } to reduce DNS skew.

Browser only: requires RTCPeerConnection in a secure context. Not for Node.js server-side use.

STUN-specific: measures reachability and latency to a STUN endpoint, not end-to-end media path quality.

Demo UI

This repo includes a browser demo (index.html) with parallel and robust test modes, optional DNS warmup, and resource-usage metrics.

git clone <repo-url>
cd ping
python3 -m http.server 8080

Open http://localhost:8080.

| File | Purpose | |------|---------| | libping.js | Library (published to npm) | | index.html, app.js | Strike UI demo | | ping.js, metrics.js | Demo-only probe orchestration and metrics |

License

MIT