# BLE GATT Explorer

> Connect to a BLE device in Chrome and browse its GATT tree: named services and characteristics, decoded reads, guarded writes, a notify log with CSV export.

- URL: https://bytescope.dev/en/ble-explorer/
- Locale: en · Also: [ja](https://bytescope.dev/ja/ble-explorer.md) · [zh-Hant](https://bytescope.dev/zh-Hant/ble-explorer.md)
- Runs: Reads BLE GATT services locally in your browser — nothing is uploaded.
- Requires: Chrome, Edge or Opera on desktop, and Chrome on Android (Web Bluetooth). Not Firefox, Safari or iOS.
- Updated: 2026-09-08

## What it does

This explorer connects to a Bluetooth Low Energy device through the Web Bluetooth API: click Connect, pick your device from the browser's chooser, and the page walks the whole GATT tree — every service, characteristic and descriptor, with READ / WRITE / NOTIFY / INDICATE property badges on each characteristic. Recognised UUIDs get their proper names from the Bluetooth SIG assigned numbers (Battery Service, Heart Rate Measurement, Client Characteristic Configuration) plus common vendor UUIDs like Nordic UART, Nordic DFU and Improv Wi-Fi; an unrecognised UUID is shown as the raw value, never a guess. Everything runs locally in your browser — nothing you read from a device is ever uploaded. Web Bluetooth is a Chromium-only API: Chrome, Edge and Opera on desktop, with Chrome on Android reported to work but untested by us; Firefox and Safari don't implement it at all.

### Why a freshly connected device can look empty

Web Bluetooth has one gotcha that catches everybody the first time: `requestDevice` only grants access to services the page asked for up front. Either the services are named in `filters`/`optionalServices`, or the call uses `acceptAllDevices` together with an `optionalServices` list — there is no "just show me everything" mode in the API. This tool preloads a long list of standard and well-known vendor services into `optionalServices`, so most devices come up with the tree fully populated; if yours uses a custom service UUID, paste it into the connect options before choosing the device, or that service simply will not appear. A device that seems to "have no services" is almost always this, not broken hardware.

### Read, decode, write and subscribe

Reading a characteristic shows the raw bytes as hex and UTF-8, alongside every common numeric interpretation — uint8/16/32 and signed, little- and big-endian, float. Standard characteristics are fully decoded: a Heart Rate Measurement (`0x2A37`) reads as "72 bpm, contact detected, RR-interval 781.25 ms" instead of a byte puzzle. Writes take hex or text, with or without response, and always sit behind a confirmation step — the wrong bytes to the wrong characteristic can change a device's settings. Subscribe to a NOTIFY or INDICATE characteristic and every update lands in a timestamped log with pause/resume and CSV or JSONL export. One honest limit: `watchAdvertisements` — reading advertisement packets and RSSI without connecting — sits behind a browser flag and is not implemented here. This is a GATT client, exactly like a phone app, not a passive scanner.

## Limits

Does not pair Bluetooth Classic devices or sniff traffic between other devices; it browses GATT services on one connected BLE device.

WARNING: Writing to an unknown characteristic can change device configuration or trigger a reboot/bootloader state.

## FAQ

### I connected, but my device's service is missing — why?

Web Bluetooth only exposes services the page listed before connecting — that's how `requestDevice` is designed, not a fault in your device. This tool preloads a long list of standard and well-known vendor services into `optionalServices`, but a custom service UUID has to be added by hand: paste it into the connect options, reconnect, and the service appears. If a phone app can see the service and this page can't, a missing `optionalServices` entry is the answer virtually every time.

### Can I scan nearby devices or see RSSI without connecting?

Not here. Passive scanning — reading advertisement packets and RSSI without connecting — is the `watchAdvertisements` API, which sits behind an experimental browser flag and is not implemented in this tool; we'd rather say that plainly than ship a scanner that only works after you edit `chrome://flags`. This page connects to one device you pick from the browser's chooser and talks to it as a GATT client, exactly the way a phone app would. For sniffing advertisements you still want a native app like nRF Connect or a dedicated sniffer dongle.

### Is anything from my device uploaded?

No. Web Bluetooth talks directly between your browser and the device — the GATT tree, every value you read and every notification you log stay on your machine, and CSV/JSONL exports are generated locally. The site's analytics record only that the tool was used, never any device data.

### Is it safe to write to a characteristic?

Reading is always safe — writing is the part that deserves respect. A write goes straight to the device: the wrong bytes to a configuration characteristic can change its settings, and some characteristics (a DFU control point, for example) can reboot a device into its bootloader. That's why every write here sits behind a confirmation step that shows exactly which characteristic and which bytes are about to be sent. If you're reverse-engineering an unknown device, read and subscribe first, and write only to characteristics you've identified.

### Why does Chrome on Linux not find any devices?

On Linux, Web Bluetooth goes through BlueZ, and Chrome's support there is younger than on Windows or macOS — on some distributions it still sits behind an experimental flag in `chrome://flags`. Check that the bluetooth service is running (`systemctl status bluetooth`), that `bluetoothctl` can see your device, and update BlueZ if it's old: if `bluetoothctl` can't find the device, the browser never will either.
