# WebUSB API: connecting to non-standard USB devices from the web

> How navigator.usb.requestDevice() pairs with USB devices outside the standard device classes, the transient-activation and secure-context requirements, the permission/chooser model, and the optional landing-page mechanism.

**In one line:** WebUSB lets a web page request access to a USB device that falls
outside the OS's standard device classes (keyboards, mice, and similar) — devices that
would otherwise need a native driver or app — by showing the user a permission prompt
to pair with a specific device, with no driver download required. It is a WICG
specification, not a W3C Standard or on the W3C Standards Track.

## Spec status

WebUSB is published by the Web Platform Incubator Community Group (WICG) as a Draft
Community Group Report; the spec states it "is not a W3C Standard nor is it on the W3C
Standards Track." MDN marks the API **experimental** and **not Baseline**, "because it
does not work in some of the most widely-used browsers."

## Why WebUSB exists

Many USB devices belong to standardized classes with OS-provided drivers and are also
reachable from the web via the WebHID API. Devices outside those standard classes
historically required native code to access, which "prevents these devices from being
used by the web." WebUSB exposes those non-standardized device services to the web
directly.

## Secure context and transient activation

WebUSB is available only in secure contexts. `requestDevice()` must be called while the
calling script has **transient activation** (a recent user gesture); calling it without
one rejects the returned promise with a `SecurityError`.

## Requesting and reusing a device

```js
navigator.usb
  .requestDevice({ filters: [{ vendorId: 0x2341 }] })
  .then((device) => {
    console.log(device.productName); // "Arduino Micro"
    console.log(device.manufacturerName); // "Arduino LLC"
  })
  .catch((error) => {
    console.error(error);
  });
```

`requestDevice()` filters candidates (e.g. by `vendorId`) and, per the spec, "the UA may
display a permission prompt when this function is called." Once a device has been
authorized, `navigator.usb.getDevices()` returns previously authorized devices without
prompting again:

```js
navigator.usb.getDevices().then((devices) => {
  devices.forEach((device) => {
    console.log(device.productName);
  });
});
```

The UA "may also display an indicator when a device connection is active."

## Permission model

WebUSB's security model relies on the `requestDevice()` permission prompt together with
Permissions Policy integration, rather than device-side allowlists (an approach similar
to CORS that the spec explains was considered and not adopted). A spec-defined **USB
Blocklist** additionally restricts access to specific devices, identified by
`vendorId`, `productId`, and `bcdDevice`. Separately, protected interface classes are
restricted from WebUSB access regardless of the Blocklist.

Only one execution context may claim a given USB interface at a time —
`claimInterface()` fails if multiple execution contexts attempt to claim the same
interface.

## Device structure

`USBDevice` exposes metadata about a paired device plus methods for controlling it.
Devices are organized into `USBConfiguration` → `USBInterface` →
`USBAlternateInterface` → `USBEndpoint`, each providing information about that layer of
the device. Transfers are represented by `USBInTransferResult` /
`USBOutTransferResult` (and isochronous variants for streaming endpoints).

## Landing page

A device can declare a landing page via the WebUSB Platform Capability Descriptor's
`iLandingPage` field — "a landing page which the device manufacturer would like the
user to visit in order to control their device." The UA's role is advisory only: it
"MAY suggest the user navigate to this URL when the device is connected." The browser
retrieves this via a defined `GET_URL` device request that returns a URL Descriptor
(scheme prefix plus UTF-8 URL string).

## Availability in workers

MDN notes this feature is available in Web Workers (`WorkerNavigator.usb`), in addition
to `Navigator.usb` on the main thread.

## Practical checklist

- [ ] Feature-detect `navigator.usb` before calling any WebUSB method.
- [ ] Serve the page over HTTPS — WebUSB is only available in secure contexts.
- [ ] Call `requestDevice()` only from a script with transient activation (a user
      gesture); calling it otherwise rejects with `SecurityError`.
- [ ] Use `filters` (e.g. `vendorId`) to scope the picker to your target device.
- [ ] Call `getDevices()` on subsequent visits to reuse a previously authorized device
      without prompting again.
- [ ] Check current browser compatibility before shipping — MDN marks WebUSB
      experimental and not Baseline.
- [ ] If your device declares an `iLandingPage`, remember the browser's navigation
      suggestion is optional (MAY), not guaranteed.