Polling rate is a USB story. This is a browser story.
A high-end wired controller can interrupt the host a thousand times a second. Your browser does not get those interrupts. It gets a Gamepad object, refreshed when the user-agent feels like it, usually aligned with animation frames. Gamepad.timestamp is a millisecond clock of the last change the browser noticed. The reciprocal of the median delta between distinct timestamps is a browser-observed update rate. That is the only honest Hz figure a website can print.
CTRLCHK records those deltas while the pad is live. Eight or more advances are required before we publish Hz, so a single connect event cannot become “125 Hz.” Jitter is the 5–95 percentile spread of the same deltas. If timestamps never advance — a still DualSense on several browsers — we print that fact. Capture for drift and range keeps running, because samples are timestamped with the animation clock, not with the frozen Gamepad field. That distinction is also why the hands-off countdown no longer stalls when you set the pad down.
How to read the live label
Overview shows Hz in the status strip. Move a stick if you want more timestamp advances; a perfectly still pad may never tick. Demo mode (?demo=true) advances every frame because it synthesizes timestamps from performance.now(). Real hardware will not match demo Hz, and it should not.
If you came here to debug input delay in a cloud game, this number is a ceiling for what JavaScript saw, not a diagnosis of the stream. If you came here because a store listing said “1000 Hz polling” and a web tester “confirmed” it, treat that confirmation as marketing. For drift, circularity and snapback — measurements this API can support — use the guided gamepad tester.