Web Bluetooth is a browser API, exposed as navigator.bluetooth, that lets a web page connect to a nearby Bluetooth Low Energy device and read or write its GATT characteristics. It is a Web Bluetooth Community Group draft, not a W3C Recommendation, and it works only in secure contexts. MDN marks it experimental and not Baseline, so check browser support before relying on it.
Everything starts with navigator.bluetooth.requestDevice(options), which shows a browser chooser. The user must pick a device, and the call needs a user gesture. Your options must include filters, such as a list of services, or set acceptAllDevices to true. A site that uses acceptAllDevices can only touch services it also lists in optionalServices.
After the user picks a device, the typical sequence is:
A single written value cannot exceed 512 bytes, the maximum attribute value length. A longer buffer rejects with InvalidModificationError. Writing while disconnected rejects with NetworkError.
The spec keeps a blocklist of GATT services, characteristics and manufacturer data that are unsafe to expose. Using a blocklisted one rejects with SecurityError.
Services are identified by UUIDs. Bluetooth shortens them to 16 or 32 bits by replacing the top 32 bits of a fixed 128-bit base value, 00000000-0000-1000-8000-00805f9b34fb. The spec's own BluetoothUUID.canonicalUUID() does this, and the sample below re-implements it. The spec requires full UUID strings to be lowercase, with no short forms.
const BASE = "00000000-0000-1000-8000-00805f9b34fb";
function canonicalUUID(alias) {
return alias.toString(16).padStart(8, "0") + BASE.slice(8);
}
console.log(canonicalUUID(0xDEADBEEF));
console.log(canonicalUUID(0x1234));
console.log(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(canonicalUUID(0x1234)));
console.log(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test("180D"));
Output:
deadbeef-0000-1000-8000-00805f9b34fb
00001234-0000-1000-8000-00805f9b34fb
true
false
A service is missing after connecting when it was not named in filters or optionalServices during requestDevice(). Access is granted only for the services you listed in that call. Add the service UUID to optionalServices, request the device again, and the service will appear.