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

h2-fingerprint-client

v1.0.1

Published

HTTP/2 fingerprint-aware request library for Node.js — mimics real browser SETTINGS frames, pseudo-header order, and header ordering for research purposes.

Readme

h2-fingerprint-client

HTTP/2 fingerprint-aware request library for Node.js — mimics real browser SETTINGS frames, pseudo-header order, and header casing for research and educational purposes.


Background

Modern bot detection systems don't just inspect your IP or User-Agent. They fingerprint the structure of your HTTP/2 connection at the transport layer — analyzing:

  • SETTINGS frames — every browser sends unique HEADER_TABLE_SIZE, INITIAL_WINDOW_SIZE, MAX_HEADER_LIST_SIZE values on session open
  • Pseudo-header order — Chrome sends :method :authority :scheme :path, Firefox sends :method :path :authority :scheme
  • Header casing and order — real browsers send headers in a consistent, deterministic sequence
  • WINDOW_UPDATE size — the initial flow control window increment differs per browser

A standard Node.js http2 or axios request is immediately identifiable because it sends none of these signals correctly.

This library lets you make HTTP/2 requests that structurally match a real browser's fingerprint.


Install

npm install h2-fingerprint-client

Usage

Basic GET request

const { get } = require("h2-fingerprint-client");

const res = await get("https://example.com", {
  profile: "chrome120", // chrome120 | firefox121 | safari17
});

console.log(res.status);   // 200
console.log(res.body);     // HTML response
console.log(res.timings);  // { connect: 120, total: 340 }
console.log(res.profile);  // "Chrome 120 / Windows 11"

POST request

const { post } = require("h2-fingerprint-client");

const res = await post("https://example.com/api/data", {
  profile: "firefox121",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ key: "value" }),
});

Custom headers (merged with profile)

const { request } = require("h2-fingerprint-client");

const res = await request("https://example.com", {
  profile: "safari17",
  method: "GET",
  headers: {
    "accept-language": "fr-FR,fr;q=0.9",
    "cookie": "session=abc123",
  },
  timeout: 10000,
});

Profiles

| Profile | Browser | OS | SETTINGS | |---|---|---|---| | chrome120 | Chrome 120 | Windows 11 | HEADER_TABLE_SIZE=65536, ENABLE_PUSH=0, INITIAL_WINDOW_SIZE=6291456, MAX_HEADER_LIST_SIZE=262144 | | firefox121 | Firefox 121 | Windows 11 | HEADER_TABLE_SIZE=65536, INITIAL_WINDOW_SIZE=131072, MAX_FRAME_SIZE=16384, ENABLE_PUSH=0 | | safari17 | Safari 17 | macOS Sonoma | HEADER_TABLE_SIZE=4096, ENABLE_PUSH=0, INITIAL_WINDOW_SIZE=4194304, MAX_FRAME_SIZE=16384 |


Response Object

{
  status: 200,              // HTTP status code
  headers: { ... },        // Response headers (pseudo-headers stripped)
  body: "...",             // Response body as string
  profile: "Chrome 120 / Windows 11",
  timings: {
    connect: 112,          // ms to establish HTTP/2 session
    total: 348,            // ms total
  }
}

How It Works

1. SETTINGS Frame

On session open, Node.js's http2.connect() accepts a settings object. This library passes the exact settings values that each real browser sends, rather than the Node.js defaults.

2. Pseudo-Header Order

HTTP/2 uses pseudo-headers (:method, :path, :authority, :scheme) that must appear before regular headers. The order of these pseudo-headers differs between browsers and is a key fingerprinting signal. This library replicates the correct order per profile.

3. Header Order

Regular headers are ordered to match the real browser's typical output — not alphabetically or randomly as most HTTP clients do.

4. Header Values

Each profile ships with the correct user-agent, accept, sec-ch-ua, sec-fetch-* and other headers matching that browser version.


Examples

# Basic request
node examples/basic.js

# Compare all profiles side by side
node examples/compare-profiles.js

Limitations

  • HTTP/2 requires HTTPS. HTTP/1.1 sites are not supported.
  • TLS fingerprinting (JA3/JA4) is a separate layer — this library does not spoof TLS ClientHello. For that, look into solutions using BoringSSL or curl-impersonate.
  • WINDOW_UPDATE frame timing is not yet controllable.

Research References


License

MIT — for research and educational use.