🕵️♂️ Parse client hints headers and provide a convenient API to access device information and user preferences
Use client hints, where available
import { ClientHints } from "client-hints";
import { userAgentParser } from "some-user-agent-parser-library";
app.get("/api-endpoint", (req, res) => {
const hints = new ClientHints(req);
const isMobile =
hints.mobile ?? // cheap
userAgentParser(req.get("user-agent")).device?.type === "mobile"; // more expensive
const browserName =
hints.vendorName ?? // cheap
userAgentParser(req.get("user-agent")).browser?.name; // more expensive
console.log(JSON.stringify(hints, null, 2)); // Serialises all available hints
res.send(`${isMobile ? "Mobile" : "Desktop"} browser: ${browserName}`);
});
All detections return undefined
if the relevant header is not available.
Feature | Type | Header | Meaning | Adoption level |
---|---|---|---|---|
arch , architecture |
string | Sec-CH-UA-Arch | CPU architecture | Experimental |
bitness |
number | Sec-CH-UA-Bitness | CPU bitness (32, 64) | Experimental |
contentDpr , contentDevicePixelRatio |
number | Content-DPR | Image device pixel ratio | Deprecated |
deviceMemory |
number | Device-Memory | Appr. available RAM | Experimental |
downlink |
number | Downlink | Network speed (Mbps) | Experimental |
dpr , devicePixelRatio |
number | DPR | Device pixel ratio | Deprecated |
ect , effectiveConnectionType |
string | ECT | Network profile (G) | Experimental |
fetchDest , fetchDestination |
string | Sec-Fetch-Dest | Resource type | |
fetchMode |
string | Sec-Fetch-Mode | Navigation type | |
fetchSite |
string | Sec-Fetch-Site | Relationship to origin | |
fetchUser |
boolean | Sec-Fetch-User | Was the request triggered by user action | |
gpc |
boolean | Sec-GPC | Consents to sell or share personal information | Experimental |
mobile |
boolean | Sec-CH-UA-Mobile | Boolean: Is this a mobile device | Experimental |
model |
string | Sec-CH-UA-Model | Device model | Experimental |
platform |
string | Sec-CH-UA-Platform | Operating system name | Experimental |
platformVersion |
string | Sec-CH-UA-Platform-Version | Operating system version | Experimental |
prefersColorScheme |
string | Sec-CH-Prefers-Color-Scheme | User's preferred color scheme | Experimental |
prefersReducedMotion |
boolean | Sec-CH-Prefers-Reduced-Motion | User prefers reduced motion | Experimental |
prefersReducedTransparency |
boolean | Sec-CH-Prefers-Reduced-Transparency | User prefers reduced transparency | Experimental |
purpose |
string | Sec-Purpose | Resource purpose (prefetch) | Experimental |
vendorName |
string | Sec-CH-UA / Sec-CH-UA-Full-Version-List | Browser Name | Experimental |
vendorVersion |
string | Sec-CH-UA-Full-Version / Sec-CH-UA / Sec-CH-UA-Full-Version-List | Browser version | Experimental |
viewportWidth |
number | Viewport-Width | Layout viewport width | Deprecated |
width |
number | Width | Resource desired width | Deprecated |
Set the value of Accept-CH
header to include the headers you want the browse to send.
Accept-CH: Sec-CH-UA-Mobile,Sec-CH-UA-Full-Version,Sec-CH-UA-Full-Version-List,Sec-CH-UA-Model,Sec-CH-UA-Platform,Sec-CH-UA-Platform-Version,ECT
Include all available hints:
Accept-CH: *