Skip to main content

Overview

The Whoop 4.0 device communicates primarily through Bluetooth Low Energy (BLE) using a custom service alongside the standard Heart Rate service. Most data exchange between the device and app occurs through the CUSTOM SERVICE.

Standard Services

Heart Rate Service

The device exposes a standard BLE Heart Rate service, which means heart rate data can be read without additional reverse engineering. However, this service must be enabled through the custom service (see Broadcast Heart Rate).

Custom Service

The custom service contains five characteristics that handle commands, events, and data transfer:
Characteristic UUIDNameWritableReadableNotifiableHandle
0x61080002CMD_TO_STRAP--0x0010
0x61080003CMD_FROM_STRAP--0x0012
0x61080004EVENTS_FROM_STRAP--0x0015
0x61080005DATA_FROM_STRAP--0x0018
0x61080007MEMFAULT--0x001b
Characteristic names were extracted from the decompiled APK.

CMD_TO_STRAP (0x61080002)

This is the only writable characteristic in the custom service. All commands sent to the device use this characteristic. Full UUID: 61080002-8d6d-82b8-614a-1c8cb0f8dcc6 Handle: 0x0010 Example commands:
aa0800a823070e00c7e40f08  # Broadcast Heart Rate Off
aa0800a823080e016c935474  # Broadcast Heart Rate On
aa0800a8238c03017d5ec627  # Start Activity
aa0800a8238d0300dc040351  # Stop Activity

CMD_FROM_STRAP (0x61080003)

Receives notification responses from certain commands sent to the device. Full UUID: 61080003-8d6d-82b8-614a-1c8cb0f8dcc6 Handle: 0x0012

EVENTS_FROM_STRAP (0x61080004)

Receives event notifications from the device. These packets contain timestamps and event data, though their exact purpose is still being researched. Full UUID: 61080004-8d6d-82b8-614a-1c8cb0f8dcc6 Handle: 0x0015 Example packets:
aa2400fa30 b0 0300 2e316966 901f 140002 e900 0000 e90e 0000 01 01 0f 03 01 00 2f 01 000000 699d4a60
aa2400fa30 64 0300 6a316966 d02e 140002 f100 0000 ed0e 0000 01 01 01 04 01 00 2e 01 000000 2d6beb1e

DATA_FROM_STRAP (0x61080005)

Receives continuous data notifications from the device, including:
  • Real-time heart rate data during activities
  • Respiratory rate (RR) data
  • Historical data during sync operations
Full UUID: 61080005-8d6d-82b8-614a-1c8cb0f8dcc6 Handle: 0x0018 Example real-time data:
Header          Unix        S       HR  RR  RR data                 Checksum
aa1800ff2802    ad896566    f065    42  01  67060000000000000101    3ba00d4d
aa1800ff2802    ae896566    f860    43  00  00000000000000000101    5025f793
aa1800ff2802    af896566    085c    42  00  00000000000000000101    add7df13

MEMFAULT (0x61080007)

Purpose currently unknown, likely related to crash reporting or diagnostics. Full UUID: 61080007-8d6d-82b8-614a-1c8cb0f8dcc6 Handle: 0x001b

Broadcast Heart Rate

The standard Heart Rate service must be explicitly enabled through the custom service:
import subprocess

# Enable heart rate broadcast
subprocess.run([
    'sudo', 'gatttool', '-i', 'hci0', '-t', 'random',
    '-b', 'XX:XX:XX:XX:XX:XX',
    '--char-write', '-a', '0x0010',
    '-n', 'aa0800a823080e016c935474'
])

# Now you can read from the standard Heart Rate service (UUID: 00002a37-0000-1000-8000-00805f9b34fb)
The device becomes non-discoverable when heart rate broadcast is disabled. Enable broadcast before attempting to connect.

Connection Methods

Multiple tools can be used to connect to the Whoop 4.0:

Using pygatt (Python)

from pygatt import GATTToolBackend, BLEAddressType

adapter = GATTToolBackend(hci_device='hci0')
adapter.start()

# Scan for devices
for device in adapter.scan(timeout=5):
    print(device)

# Connect to device
device = adapter.connect('XX:XX:XX:XX:XX:XX', address_type=BLEAddressType.random)

# Write to CMD_TO_STRAP
device.char_write(
    "61080002-8d6d-82b8-614a-1c8cb0f8dcc6",
    bytearray.fromhex("aa0800a823080e016c935474"),
    wait_for_response=False
)

Using gatttool (Command Line)

sudo gatttool -i hci0 -t random -b XX:XX:XX:XX:XX:XX \
  --char-write -a 0x0010 -n aa0800a823080e016c935474

Using bleak (Python, for notifications)

python3 enable_notifications.py --address XX:XX:XX:XX:XX:XX \
  61080005-8d6d-82b8-614a-1c8cb0f8dcc6

Wireshark Capture

To capture BLE traffic for analysis:
  1. Enable Bluetooth HCI snoop logging in Android Developer Settings
  2. Extract logs:
adb bugreport logs
unzip logs.zip
wireshark FS/data/log/bt/btsnoop_hci.log
  1. Or stream live:
# Ensure device is connected
adb devices -l

# Launch Wireshark with sudo
sudo wireshark
# Select "Android Bluetooth Btsnoop Net"
  1. Filter for btatt to see only Bluetooth Attribute Protocol packets
  2. Further filter for specific handles:
btatt.handle == 0x10  # CMD_TO_STRAP only

Build docs developers (and LLMs) love