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

accept-ch-parse

v0.1.2

Published

Zero-dependency parser for the HTTP Accept-CH Client Hints header (RFC 8942) for Node.js (>=18, ESM+CJS) and Python (>=3.11)

Readme

accept-ch-parse

Zero-dependency parser for the HTTP Accept-CH Client Hints header (RFC 8942) — for Node.js and Python.

  • Parses Accept-CH into a list of tokens with quality (q) values
  • Sorts output by descending q (stable: ties keep input order)
  • Token names are case-sensitive per RFC 8942
  • Forward-compatible: unregistered tokens are still parsed
  • Empty / whitespace-only headers yield [] (not an error)
  • Zero runtime dependencies on both platforms

Why

HTTP Client Hints (RFC 8942) let servers request device / connection information via the Accept-CH response header. Example:

Accept-CH: Width, Viewport-Width, Content-DPR;q=0.8

When this library was first published (2026-08-08), no zero-dependency parser for Accept-CH existed on either registry — the names were free:

  • npm accept-ch-parse — confirmed 404 at build time (2026-08-08)
  • PyPI accept-ch-parse — confirmed 404 at build time (2026-08-08)

This library fills that gap. It is small, dual-language, has zero runtime deps, and gets out of your way. If you are reading this README after 2026-08-08 and the names are no longer 404, someone has published a typosquat or fork — please verify the package you install matches the GitHub repo at prasad-a-abhishek/accept-ch-parse before depending on it.

Install

Node.js (≥18)

npm install accept-ch-parse

ESM:

import { parseAcceptCH, serializeAcceptCH, getAcceptCHTokens } from 'accept-ch-parse';

CJS:

const { parseAcceptCH, serializeAcceptCH, getAcceptCHTokens } = require('accept-ch-parse');

Python (≥3.11)

pip install accept-ch-parse
from accept_ch_parse import parse_accept_ch, serialize_accept_ch, get_accept_ch_tokens

Usage

Basic parse

import { parseAcceptCH } from 'accept-ch-parse';

parseAcceptCH('Viewport-Width, Width, Content-DPR');
// → [
//     { token: 'Viewport-Width', q: 1.0, raw: 'Viewport-Width' },
//     { token: 'Width',          q: 1.0, raw: 'Width' },
//     { token: 'Content-DPR',    q: 1.0, raw: 'Content-DPR' }
//   ]
from accept_ch_parse import parse_accept_ch

parse_accept_ch('Viewport-Width, Width, Content-DPR')
# → [AcceptCHToken(token='Viewport-Width', q=1.0, raw='Viewport-Width'),
#     AcceptCHToken(token='Width',          q=1.0, raw='Width'),
#     AcceptCHToken(token='Content-DPR',    q=1.0, raw='Content-DPR')]

Quality weights — sorted by descending q

parseAcceptCH('Width;q=0.5, Viewport-Width, Content-DPR;q=0.8');
// → [
//     { token: 'Viewport-Width', q: 1.0, raw: 'Viewport-Width' },
//     { token: 'Content-DPR',    q: 0.8, raw: 'Content-DPR;q=0.8' },
//     { token: 'Width',          q: 0.5, raw: 'Width;q=0.5' }
//   ]

Serialize

import { serializeAcceptCH } from 'accept-ch-parse';

serializeAcceptCH([
  { token: 'Viewport-Width', q: 1.0, raw: 'Viewport-Width' },
  { token: 'Width',          q: 0.5, raw: 'Width' }
]);
// → 'Viewport-Width, Width;q=0.5'

Just the token names

import { getAcceptCHTokens } from 'accept-ch-parse';

getAcceptCHTokens('Width;q=0.5, Viewport-Width, Content-DPR;q=0.8');
// → ['Viewport-Width', 'Content-DPR', 'Width']   (already q-sorted)

Recognized Client Hints

The parser is forward-compatible — any syntactically valid token is accepted. The eight registered per RFC 8942 are:

| Token | Meaning | |---|---| | Viewport-Width | Layout viewport width in CSS pixels | | Width | Resource width in CSS pixels | | Content-DPR | Resource's intrinsic DPR (paired with Content-Length) | | DPR | Current device pixel ratio | | Device-Memory | Approximate device RAM in GiB | | ECT | Effective connection type (slow-2g, 2g, 3g, 4g) | | RTT | Round-trip time in ms | | Downlink | Downlink speed in Mbps |

API

Node.js

parseAcceptCH(header: string): AcceptCHToken[]
serializeAcceptCH(tokens: AcceptCHToken[]): string
getAcceptCHTokens(header: string): string[]

interface AcceptCHToken {
  token: string;   // case-sensitive
  q: number;       // 0..1, default 1.0
  raw: string;     // exact substring parsed (trimmed)
}

Throws TypeError if header is not a string (including null / undefined).

Python

parse_accept_ch(header: str) -> list[AcceptCHToken]
serialize_accept_ch(tokens: list[AcceptCHToken]) -> str
get_accept_ch_tokens(header: str) -> list[str]

class AcceptCHToken(NamedTuple):
    token: str
    q: float
    raw: str

Raises TypeError if header is not a string (including None).

Errors

| Input | Behaviour | |---|---| | '' / ' ' | Returns [] | | null / undefined / non-string (Node) | TypeError | | None / non-str (Python) | TypeError | | Width;q=0.5 | Parsed; q = 0.5 | | Width;Q=0.5 | Parsed; param names are case-insensitive (RFC 7230) | | Width;q=0, X | Width sorts last; q clamped to [0, 1] | | Width;q=2.5 | Clamped to 1.0 | | Width;q=-0.5 | Clamped to 0.0 | | Width;q= (malformed) | Treated as q = 1.0 (forgiving) | | Width,,X | Empty entry dropped; Width and X parsed | | viewport-width | Parsed as-is (case-sensitive, NOT folded to Viewport-Width) |

Run the tests

# Node
npm install
npm test

# Python
pip install -e .[test]
python -m pytest

The full suite is 60 Node.js tests + 61 Python tests, all green.

Limitations / Non-goals

Out of scope for this library (intentionally, per spec):

  • Sending Accept-CH or any other HTTP header — this library parses only.
  • Save-Data header parsing — different header, different spec.
  • Vary header parsing — different header, different semantics.
  • A token registry — unregistered tokens are still accepted (forward compatibility). If you need to reject unknown tokens, do that at a higher layer.
  • Quality value arithmetic (sum, threshold checks, etc.) — just parse and sort.
  • Browser or HTTP client implementation.

References

License

MIT — see LICENSE.