cd /news/developer-tools/th0rgal-open-oura-a-rust-toolkit-for… · home topics developer-tools article
[ARTICLE · art-42433] src=github.com ↗ pub= topic=developer-tools verified=true sentiment=· neutral

Th0rgal/open_oura: a Rust toolkit for the Oura Ring (Gen 3/4/5)

A Rust toolkit for reverse-engineering the Oura Ring's BLE protocol enables cloud-free data access from Gen 3/4/5 rings, including live heart rate, SpO2, sleep stages, and activity MET levels, bypassing Oura's cloud dependency. The project reproduces on-device PyTorch models for scores like Readiness and Sleep, but excludes proprietary model files.

read3 min views1 publishedJun 28, 2026
Th0rgal/open_oura: a Rust toolkit for the Oura Ring (Gen 3/4/5)
Image: source

Reverse-engineering the Oura ring BLE protocol, plus an independent, cloud-free client that reads your data straight from the ring.

Tested live against a Ring 3 Horizon and a Ring 5 (pairing, auth, and event sync confirmed on both). Designed for Ring 3/4/5, which share the same GATT layout, packet framing, and authentication flow.

Straight from the ring, with no Oura account: device info, battery, live heart rate (IBI to BPM), latest HR / SpO2, and the full history-event stream. That stream carries raw PPG/IBI/temperature/motion/SpO2 samples plus the ring's on-device sleep stages, activity MET levels, and HRV.

The ring itself does not emit the 0-100 Readiness / Sleep / Activity / Stress scores. But those are not computed in Oura's cloud either: they're computed on the phone by the native ecore

engine and a set of on-device PyTorch models (the same .pt

we run here), then uploaded; the cloud only stores and syncs them back. So they're reproducible offline. The one genuine cloud-only step is workout auto-classification (POST /api/activity-tagging/v2

). See docs/data-recovery-map.md,

, and

docs/algorithms/README.md

for what runs.

docs/model-runners.md

Those PyTorch models are Oura's proprietary IP and are NOT included in this repo(gitignored undernotes/models/

). The runners reference them by path; you decrypt and supply your own locally. Nothing model-related is committed or pushed.

: the Rust client, split by concern (crates/

oura-protocol

decode,oura-link

fetch,oura-analysis

metrics,oura-store

SQLite,oura-cli

). Start here:andcrates/README.md

.docs/architecture.md

: Python research bench for protocol exploration.tools/

oura_protocol.py

(full command matrix, auth, danger-gated ops, JSONL capture) andoura_realtime_listener.py

.: protocol and reverse-engineering reference (index below).docs/

: local-only, gitignored. The decompiled app and raw captures (which may contain serials, MACs, and auth keys).reverse/

,captures/

cargo build --release
./target/release/oura scan
./target/release/oura --key-file key.hex info

See crates/README.md for all commands (

scan

, pair

, info

, sync

, latest

, live-hr

, accel

, viz

, game

, features

, rdata

, events

, redecode

, sleep-analyze

, sessions

) and the auth-key details. oura viz

opens a real-time 3D motion visualizer in the browser; oura game

is a tilt-controlled asteroid game driven by the ring.

python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
.venv/bin/python tools/oura_protocol.py --list

State-changing and destructive commands are hidden behind --include-state

and --include-danger

. On macOS, grant Bluetooth permission to the terminal.

: the protocol command reference (requests, responses, auth, features), Ring 3.docs/horizon-ring3-protocol-cheatsheet.md

: app internals, BLE constants, the auth operations, key generation, and nonce encryption.docs/android-app-reversing.md

: what the ring emits vs what only the cloud computes.docs/data-recovery-map.md

: when and how the app pulls each data channel, and the minimal client sync recipe.docs/sync-orchestration.md

: Ring 5 BLE surface and first-contact findings.docs/ring-5-observations.md

: the feature capabilities, runtime modes, what's on by default, and which event each enabled feature produces (incl. whatdocs/ring-features.md

experimental

does — and doesn't).: running Oura's decrypted on-device models on your synced data — what runs (activity, sleep, CVA, SpO2) vs what's blocked.docs/model-runners.md

: decoding the raw PPG (docs/cva-cardiovascular-age.md

cva_raw_ppg_data

0x81) and running the cardiovascular-age model.: turning the SpO2 R-ratio into a percentage with Oura's own calibration.docs/spo2-calibration.md

: the DFU/OTA opcodes, the working cloud download pipeline + codename map, per-device encryption status, and why the firmware key is unreachable (device-resident; not brute-forceable).docs/firmware-update.md

: findings-only notes on the model/firmware encryption (the "what", not the "how" — no keys, endpoints, or procedures).docs/security-observations.md

: the fetch/interpret/apply crate layering and where to add things.docs/architecture.md

: the on-device ecore metric algorithms (scores, sleep, baselines) and their porting status.docs/algorithms/README.md

: porting event-body decoders from the nativedocs/native-decoder.md

libringeventparser.so

(how the byte layouts were recovered with Ghidra).

  • Prefer passive, read-only requests. reset / DFU / factory-reset / flight-mode are gated behind explicit flags; do not send them during normal use.
  • App-gated operations need the ring's 16-byte auth key (re-sent each connection). Captures and keys are gitignored. Never commit a key.

ringverse Oura Ring 4 BLE notes: https://github.com/ringverse/protocol/blob/main/oura/BLE.md

── more in #developer-tools 4 stories · sorted by recency
── more on @oura 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/th0rgal-open-oura-a-…] indexed:0 read:3min 2026-06-28 ·