by RSS Axelle Apvrille  |  Dec 09, 2016  |  Filed in: Security Research

Quite strangely, there is no easy way to check the battery level of your Fitbit tracker. You can configure your profile to send you notifications when the battery is low, but that's about all.

As I was researching Bluetooth Low Energy (BLE), I noticed however that Fitbit trackers do offer the standard Battery Service (0x180f) along with the (standard) Battery Level characteristic (0x2a19).

So, it looks like the feature is there, it's just that there's no UI to read it. I immediately tried to read the value from the Battery Level characteristic, as that's supposed to be the battery level in percentage. And I got 0 as answer. Ok, perhaps the battery is indeed low. I charged it the best I could, and tried again: 0. The tracker did operate normally however, meaning that the battery was certainly not completely empty. So, I decided to investigate.

In BLE, if characteristics support notifications then when their value changes the device is able to send a notification with the new value. Fortunately, the Battery Level is one of those characteristics: it supports notifications. I can check its configuration using gatttool:, I can connect to the tracker, and I can read the values for configurable characteristics (2902 lists Client Characteristic Configuration attributes on the device). The handle for the Battery Level is 0x1c.

[XX:XX:XX:XX:XX:XX][LE]> char-read-uuid 2902
handle: 0x000c   value: 00 00 
handle: 0x0012   value: 00 00 
handle: 0x001c   value: 00 00

The value 0x0000 means that neither notification nor indications are enabled. That's why I was not being notified of battery level changes. When I changed that, just a few seconds later I received a battery level notification (it was at 64%).

[XX:XX:XX:XX:XX:XX][LE]> char-write-cmd 0x001c 0100
Notification handle = 0x001b value: 64

I have released source code to automate this and reading your battery level percentage,using a standard BLE USB dongle (those are cheap – I got mine for 13 euros.) The implementation basically issues the BLE ATT commands we have seen above:

  • Connect to the tracker
  • Enable notifications for the Battery Level characteristic
  • Read value for Battery Level

For example, below you can see that my tracker is fully charged. Option -v is for verbose information.

$ sudo python read-battery.py --target aa:bb:cc:dd:ee:ff -v
============ Fitbit Flex Battery Level Utility =========
> read_battery(): value_handle=0x1b notif_handle=0x1c
> connect(): Connecting...
< connect(): Connected
    Configuring tracker to get battery level notification
    Waiting for battery level notification...
> on_notification()
    From handle=0x1b, value=1b
< on_notification()
    Reading battery level...
    GATT response: 64
    Value: 100 percent
    Disconnect required
Disconnected
< read_battery()
Battery level percentage 100.0 %

And later, it shows that it is at 96%:

sudo python read-battery.py --target aa:bb:cc:dd:ee:ff 
============ Fitbit Flex Battery Level Utility =========
Battery level percentage 96.0 %

Note this tool does not work with Fitbit's USB dongle, because that dongle provides an additional (Fitbit) layer above BLE that cannot be accessed directly.

-- the Crypto Girl

by RSS Axelle Apvrille  |  Dec 09, 2016  |  Filed in: Security Research