Signal · signalsVersion 14

device_apis

Whether 18 device and platform APIs (HID, USB, serial, Bluetooth, XR, Web Share and others) exist, presence only, as a bit mask. Reported, not in either id.

device_apis at a glance (from the library code, signalsVersion 14)
Component namedevice_apis
In the visitorIdno (reported, kept out of both ids)
structuredId groupnone
Hashingplain value; a digest only when longer than 128 characters or not printable ASCII
Excluded underno browser class
Inner timeout1000 ms
Added insignalsVersion 12
Collector revision1 (reported as revision with every result)
In plain words

Browsers offer web pages different ways to reach hardware: USB, Bluetooth, game controllers, virtual reality headsets, NFC tags. WhiskerJS only checks whether each of 18 such features exists, without using any of them, and writes the answer as one short code.

What it reads

Whether each of these names exists, in this order (bit 0 first):

Bit API Bit API
0 navigator.bluetooth 9 navigator.virtualKeyboard
1 navigator.hid 10 navigator.wakeLock
2 navigator.usb 11 navigator.ink
3 navigator.serial 12 window.NDEFReader
4 navigator.xr 13 window.PressureObserver
5 navigator.share 14 window.showOpenFilePicker
6 navigator.contacts 15 window.EyeDropper
7 navigator.devicePosture 16 window.IdleDetector
8 navigator.windowControlsOverlay 17 window.documentPictureInPicture

How the technique works

Each name is tested with the in operator only: no getter runs and no method is called, so nothing can prompt or open a device chooser. The answers become a bit mask in hex, bit i for entry i (0 when none exists). The order is fixed and new entries are appended.

Why it helps

These APIs differ between engines, between desktop and mobile builds and between browsers built on the same engine, because a browser may remove some of them. Most need a secure context. It adds a little detail about the browser build for your server.

Stability

Policies and browser settings switch these APIs on and off, and new browser versions add them. That is why it is reported outside both ids. Added in library PR #33 (2026-10-27) at signalsVersion 12: it is outside both ids, so the ids did not change. No integrity check uses it: a missing API is never a sign of anything.

Browser support and what blocks it

In the self-hosted CI browser matrix of PR #33 on Linux:

Browser Value Notes
Chrome, Chromium, Edge, Opera 3ef9e no Bluetooth, Web Share, Contacts or Web NFC there
Brave 3af9e no showOpenFilePicker
Opera beta (Chromium 142) 1ef9e
Firefox 20408 serial, wakeLock, documentPictureInPicture
Playwright’s WebKit 400 wakeLock

Expect other values on Windows, macOS, Android and iOS, where other APIs exist. unavailable / no_api only without a navigator. No browser class excludes it.

Privacy

It reads whether interfaces exist, never their contents: no device list, no prompt, no request. Leave it out with collect({ exclude: ['device_apis'] }) if you do not need it; no id changes.

How WhiskerJS handles noise and failures

Status ruleId When
ok a bit mask in hex
unavailable no_api no navigator
blocked threw, security_error the read threw
excluded caller_excluded you excluded it
timed_out timeout, aborted budget or abort

Example value

"device_apis": { "status": "ok", "value": "3ef9e", "hashed": false, "durationMs": 0.1, "revision": 1 }

Questions and answers

Can device_apis show a permission prompt?

No. It only asks whether a name exists, with the in operator. No getter runs and no method is called, so no device chooser or prompt can appear.

Does a missing API raise a flag?

No. Policies, browser settings and builds remove these APIs for good reasons, so a missing API is never treated as a sign of anything.