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

@stricaud/libpcapng

v0.18.3

Published

JavaScript/WebAssembly bindings for libpcapng — read and dissect pcap/pcapng in the browser

Readme

libpcapng — JavaScript / WebAssembly bindings

Read-only capture analysis in the browser (or Node), powered by the same C dissection engine as the rest of libpcapng, compiled to WebAssembly with Emscripten.

Parse .pcap / .pcapng buffers entirely in memory — nothing is uploaded anywhere — list packets with Wireshark-style summary columns, dissect any packet into a field tree with byte offsets, and load your own declarative (posa) dissectors at runtime.

No live capture. lib/capture.c (OS-level BPF / packet sockets) is deliberately excluded from this build — it cannot run in a browser and is not needed to analyse saved captures.

Building

Requires Emscripten.

cd bindings/js
./build.sh            # emcc on PATH, or: EMSDK=~/emsdk ./build.sh

Output: dist/libpcapng.mjs — a self-contained ES module (the .wasm is embedded via SINGLE_FILE, so it works from any path, including a GitHub Pages sub-directory). Prebuilt modules are also published as artifacts by the js-bindings GitHub Actions workflow and attached to js-v* releases.

Usage

import createLibpcapng from "./libpcapng.mjs";

const M = await createLibpcapng();

// bytes: a Uint8Array of a .pcap or .pcapng file (e.g. from <input type=file>)
const count = M.loadCapture(bytes);

for (const p of M.getSummaries()) {
  // { no, time, src, dst, proto, length, info }
  console.log(`#${p.no} ${p.src} → ${p.dst} ${p.proto}  ${p.info}`);
}

// Full dissection of one packet: an array of protocol layers.
const layers = M.getDetail(0);
// each node: { abbrev, label, value, off, len, children: [...] }
// `off`/`len` are absolute byte offsets — use them to highlight the hex view.

const rawBytes = M.getPacketBytes(0);  // Uint8Array

Loading a file in the browser

const buf = new Uint8Array(await file.arrayBuffer());  // file: a File object
M.loadCapture(buf);

API

| Function | Returns | Description | | --- | --- | --- | | loadCapture(u8) | number | Parse a Uint8Array (.pcap/.pcapng). Returns packet count. Replaces any previously loaded capture. | | getPacketCount() | number | Number of packets in the loaded capture. | | getSummaries() | Array | Packet list: {no, time, src, dst, proto, length, info}. time is seconds relative to the first packet. | | getDetail(i) | Array \| null | Protocol layers of packet i, each a field node (see below). | | getPacketBytes(i) | Uint8Array \| null | Raw captured bytes of packet i. | | loadPosaText(src) | {ok, added, error} | Load one or more declarative dissectors from .posa text. Redefining a protocol by name replaces it. | | listPosa() | Array | Loaded posa dissectors: {name, display, abbrev}. | | listProtocols() | Array<string> | Field abbrevs the built-in C dissector can emit. |

Field node

interface Field {
  abbrev: string;   // Wireshark-style, e.g. "ip.src", "tcp.dstport" ("" = structural)
  label: string;    // human-readable, e.g. "Source Address: 10.0.0.1"
  value: string;    // formatted value ("" for structural nodes)
  off: number;      // absolute byte offset within the packet
  len: number;      // byte length
  children: Field[];
}

Declarative dissectors (posa)

The engine ships with built-in decoders (RDP negotiation, TPKT, COTP). You can add more at runtime from .posa text — handy for a UI that lets users define and persist their own dissectors:

const res = M.loadPosaText(myPosaSource);
if (!res.ok) console.error(res.error);
console.log(M.listPosa());   // now includes the new protocol(s)

Testing

node test/smoke.mjs