Skip to main content

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.

Metadata

Release files for accept-ch-parse 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for accept-ch-parse 0.1.2
File Size Uploaded
accept_ch_parse-0.1.2.tar.gz 6.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for accept-ch-parse 0.1.2
File Interpreter ABI Platform
accept_ch_parse-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 13.0 kB

Release files / accept_ch_parse-0.1.2.tar.gz

Download URL accept_ch_parse-0.1.2.tar.gz
Size 6.4 kB
Tags Source
SHA-256 checksum
How to use checksums
023b9d2d07431b750dc6b864fba7cc442a13c357f508883f9d15cb19719f163a
BLAKE2b-256 checksum
How to use checksums
890a449c5d53334c841a6160d23c23f70389b141cf172849d712bd020630ba59
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.15

Release files / accept_ch_parse-0.1.2-py3-none-any.whl

Download URL accept_ch_parse-0.1.2-py3-none-any.whl
Size 6.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ff57b858465beb41005ee1da3070161c015a1fe15252f923925ccea999d1f14b
BLAKE2b-256 checksum
How to use checksums
f3a32d7352867674177b434611d2f9087a032c679ea46c6e45d3c384c2ad4f5b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.15

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page