Webhid Api

The Gamepad API gives you buttons and axes. WebHID gives you everything else -- LED color, rumble, accelerometer inside the controller, Stream Deck keys. It is also low-level, Chromium-only, and requires user permission.

June 10, 20264 min read11 / 17

The Gamepad API normalized controllers into a simple interface: buttons and axes. That covers the basics. It does not cover anything the device manufacturer added beyond the basics.

A PS4 DualShock controller has an LED light bar you can change to any color. It has a rumble motor. It has an accelerometer and gyroscope inside the controller itself. None of those are accessible from the Gamepad API.

WebHID is the low-level API that gets you to the rest.

What HID Is

HID stands for Human Interface Device. It is a protocol layer that sits on top of USB and Bluetooth, designed to standardize how input and output devices communicate with a host computer. Your keyboard, mouse, and most gamepads all use HID.

The protocol defines two concepts: input reports (data flowing from the device to the computer) and output reports (commands flowing from the computer to the device). A button press is an input report. Turning an LED on is an output report. A vibration command is an output report.

The HID protocol is bidirectional. Devices can both send and receive data. WebHID exposes that bidirectional channel to JavaScript.

What You Can Access That Gamepad API Cannot

The contrast is sharpest with a PS4/PS5 controller:

FeatureGamepad APIWebHID
Buttons and axesYesYes
LED color controlNoYes
Rumble / vibrationNoYes
Controller accelerometerNoYes
Touchpad on DualShockNoYes

Beyond controllers, WebHID works with any USB or Bluetooth HID device:

  • Elgato Stream Deck -- read button presses, write images to each key's LCD display
  • Presentation clickers -- receive button events and accelerometer data from pointer pens
  • USB LED lights -- send color commands to RGB strips or illuminated buttons
  • Custom macro pads -- any non-standard input device using the HID protocol

The Permission Model

Unlike the Gamepad API, WebHID requires explicit user permission per device. The browser shows a chooser dialog listing available devices. This dialog can only appear from a user gesture -- a button click or similar.

JavaScript
document.getElementById('connect-btn').addEventListener('click', async () => { const devices = await navigator.hid.requestDevice({ filters: [] // empty = show all devices }) if (devices.length === 0) return // user cancelled const device = devices[0] await device.open() // Now you can communicate with the device })

The filters array can narrow the chooser to specific devices by vendorId and productId, which you find in the device's datasheet or by inspecting what the OS sees.

Once opened, previous grants are remembered. On the next visit, navigator.hid.getDevices() returns previously approved devices without prompting again.

Sending and Receiving Reports

The API communicates through binary data. Each HID report has a report ID and a byte payload. The structure depends entirely on the device -- there is no universal format.

JavaScript
// Receive data from device (input report) device.addEventListener('inputreport', (event) => { const { reportId, data } = event // data is a DataView -- parse according to device spec const byte0 = data.getUint8(0) }) // Send data to device (output report) const reportId = 0x05 const data = new Uint8Array([0x01, 0xFF, 0x00, 0x00]) // device-specific bytes await device.sendReport(reportId, data)

This is the low-level part. To know what 0x05 means or what bytes to send for a specific LED color, you need the device's HID report descriptor -- essentially its documentation or reverse-engineered protocol spec. This is why WebHID is not for general use. It is for developers who know the specific device they are targeting.

WebHID vs Gamepad API: what each gives you, and the WebHID permission and report model ExpandWebHID vs Gamepad API: what each gives you, and the WebHID permission and report model

Security Boundaries

Not every HID device is accessible. The browser deliberately blocks access to keyboards and mice even through WebHID -- because a page that can read raw keyboard reports could log every keypress. The API can access non-standard devices but not the ones that handle system-level input. This is the same reasoning behind the permission model for sensitive capabilities -- the browser draws hard lines around what JavaScript can silently access.

Light-Green Tier

WebHID is Chromium only. Safari and Firefox do not implement it. Mozilla explicitly declined to ship it due to security concerns about low-level device access from web pages.

Feature detection:

JavaScript
if ('hid' in navigator) { // WebHID is available }

All the APIs covered so far have been about reading hardware -- sensors, location, controllers, keyboards. The next one turns that around: speech recognition lets the browser listen to the user's voice and hand you back text.

The Essentials

  1. WebHID is the low-level alternative to the Gamepad API -- same physical devices, but full protocol access instead of just buttons and axes.
  2. Requires user permission via browser chooser dialog. Only triggers from a user gesture.
  3. Communicates via HID reports (binary payloads). You need the device's protocol spec to know what bytes to send and receive.
  4. Works with any USB/Bluetooth HID device: Stream Decks, custom controllers, LED arrays, presentation clickers.
  5. Chromium only. Safari declines to ship it. Always feature-detect with 'hid' in navigator.

Further Reading and Watching