WebUSB API: connecting to non-standard USB devices from the web
Published
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
Section titled “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
Section titled “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
Section titled “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
Section titled “Requesting and reusing a device”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:
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
Section titled “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
Section titled “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
Section titled “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
Section titled “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
Section titled “Practical checklist”- Feature-detect
navigator.usbbefore 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 withSecurityError. - 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.