open_oura: A Cloud-Free Rust Toolkit to Sync and Analyze Oura Ring Data Locally
A Rust toolkit for the Oura Ring (Gen 3/4/5): reverse-engineered BLE protocol, event decoders, and reimplemented data-processing algorithms. Sync, store, and analyze your data locally.
At a glance
- What is it?
- open_oura is a Rust library and CLI that reverse-engineers the Oura Ring BLE protocol, letting users sync raw health data directly from a Ring 3, 4, or 5 to local storage without an Oura account or cloud connection. The repository also reimplements the on-device algorithms that compute Readiness, Sleep, and Activity scores, but the proprietary PyTorch models those algorithms need are not included.
- Who is it for?
- Privacy-focused Oura Ring users who want their PPG, IBI, SpO2, temperature, sleep-stage, and HRV data in a local SQLite database without sending it to Oura's cloud will find open_oura technically solid and actively developed. The project cannot compute Readiness, Sleep, and Activity scores out of the box because the required PyTorch models are Oura's proprietary files that must be sourced from the native app installation.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The case for a cloud-free Oura Ring client
The official Oura Ring synchronizes data through a proprietary app that uploads everything to Oura's cloud. Users who want their biometric data to stay local have no official path: there is no export-to-local-database option, and disconnecting from the cloud stops score computation.
open_oura takes a different approach. It reverse-engineers the BLE GATT protocol used by Oura Ring Gen 3, 4, and 5 (which the README states share the same GATT layout, packet framing, and authentication flow), implements a Rust library that speaks that protocol directly, and stores the results in a local SQLite database. No Oura account is required for pairing, syncing, or analyzing data. The auth key that secures BLE communication is derived during pairing and stored in a local key file.
The repository has been tested live against a Ring 3 Horizon and a Ring 5 with pairing, authentication, and event sync confirmed on both. The README notes that Ring 4 compatibility is expected from the shared GATT layout but has not been separately confirmed.
What data the ring emits and what stays on-device or cloud-only
The README maps three categories of data by their location.
Directly from the ring with no Oura account: device info, battery level, live heart rate (converted from IBI intervals to BPM), the latest HR and SpO2 readings, and the full history-event stream. That event stream contains raw PPG, IBI, temperature, motion, and SpO2 samples, plus the ring's own on-device sleep stages, activity MET levels, and HRV.
Computable offline: the Readiness, Sleep, Activity, and Stress scores. The README makes a point that is not widely known: these scores are not computed in Oura's cloud. They are computed on the phone by the native ecore engine using on-device PyTorch models, then uploaded; the cloud only stores and syncs them back. This means they are reproducible offline. The open_oura repository reimplements the algorithms. The PyTorch model files are Oura's proprietary IP and are gitignored; users must supply their own copies sourced from their native app installation.
Cloud-only: workout auto-classification, which calls `POST /api/activity-tagging/v2`. This is the one genuine cloud-only step documented in the README, and there is no current offline alternative.
Building the Rust CLI and first commands
The Rust workspace is split across five crates: oura-protocol for BLE decode, oura-link for fetching data, oura-analysis for computing metrics, oura-store for SQLite persistence, and oura-cli as the command-line entry point. Build with cargo:
cargo build --release
./target/release/oura scan
./target/release/oura --key-file key.hex infoThe scan command lists nearby BLE devices to find the ring's address. The info command reads device metadata once the auth key file is available. The key file is created during the pair command; after that, all commands that access ring data require --key-file.
The README lists the full command set: scan, pair, factory-reset, info, sync, latest, live-hr, accel, features, rdata, events, redecode, sleep-analyze, subscribe, feature-mode, and feature-status. Destructive commands (factory-reset) require an explicit --yes flag. State-changing commands are separated from read-only commands to make accidental destructive use harder.
The Python research bench for protocol exploration
Alongside the Rust CLI, the repository includes a Python research bench in the tools/ directory for protocol exploration. It requires only two packages:
python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
.venv/bin/python tools/oura_protocol.py --listThe requirements.txt specifies bleak>=0.22,<1 for BLE communication and pycryptodome>=3.20,<4 for cryptographic operations. The README notes that on macOS, Bluetooth permission must be granted to the terminal before the research tools can scan for devices.
The tools directory includes oura_protocol.py for issuing protocol commands and oura_realtime_listener.py for streaming live data. State-changing and destructive commands are hidden behind --include-state and --include-danger flags, matching the safety model of the Rust CLI. The research bench was the original exploration environment from which the Rust implementation was derived.
Documentation depth: protocol, algorithms, and security
The docs/ directory is one of the most complete parts of the repository. It covers: the full Ring 3 BLE protocol command reference with authentication and feature flags; the Android app reversing notes showing how BLE constants, auth operations, key generation, and nonce encryption were recovered; a data recovery map explaining what the ring emits versus what the cloud computes; the sync orchestration flow; Ring 5 first-contact observations; the cardiovascular-age (CVA) algorithm with raw PPG decoding; SpO2 R-ratio to percentage calibration using Oura's own formula; the DFU/OTA firmware update opcodes; and security observations about model and firmware encryption.
The TRACEABILITY.md file links source code changes to the specific protocol observations or decompiled sections that informed them. The CLAUDE.md file in the repository root provides context for AI coding assistants working with the codebase.
Prior art is credited in the README: the ringverse Oura Ring 4 BLE notes project at https://github.com/ringverse/protocol/blob/main/oura/BLE.md. The open_oura documentation substantially extends that earlier work.
Limitations and what the project explicitly excludes
The most significant limitation is the missing PyTorch models. The README states clearly: these are Oura's proprietary IP and are not included in the repository. The model runners in the codebase reference them by local file path; users must decrypt and supply their own copies. The README provides no instructions for obtaining the model files and notes they are gitignored. Anyone intending to use the sleep-analyze or score-computation features should review docs/model-runners.md in the companion open_health repository before assuming those features will work out of the box.
Workout auto-classification has no offline implementation. It depends on a cloud API endpoint and is documented as the one step that cannot be replicated locally.
On the hardware safety side, the README advises preferring passive, read-only requests during normal use. Commands that modify ring state (factory-reset, DFU, flight-mode) are explicitly gated behind flags. The README also advises against committing the ring's auth key to version control, since it provides persistent BLE access to the device.
Comparison to the official Oura app and maintenance status
The official Oura app computes and displays all Readiness, Sleep, and Activity scores, syncs automatically over BLE, and stores data in Oura's cloud. It does not provide a local export or an offline mode. Users who want score computation without cloud upload cannot get it from the official app.
open_oura inverts this: sync and raw storage work without any cloud account, and score computation is possible offline if the user supplies the model files. The trade-off is complexity: setting up the Rust toolchain, pairing the ring, managing an auth key file, and sourcing model files requires significantly more effort than using the official app.
The last push to the repository was on 2026-09-28. The project is not archived and is under MIT licence. There are no published GitHub releases; the main branch is the current reference.
Editorial conclusion
Privacy-focused Oura Ring users who want their PPG, IBI, SpO2, temperature, sleep-stage, and HRV data in a local SQLite database without sending it to Oura's cloud will find open_oura technically solid and actively developed. The project cannot compute Readiness, Sleep, and Activity scores out of the box because the required PyTorch models are Oura's proprietary files that must be sourced from the native app installation. Anyone planning to run sleep-analyze should read docs/algorithms/README.md first to understand which algorithms are ported and what model files are expected before attempting to build.
Frequently asked questions
Does open_oura require an Oura account to use?
No. The README states that pairing, authentication, and event sync work with no Oura account. After running the pair command, the 16-byte auth key is stored locally in a key file that all subsequent commands reference.
Can open_oura compute Readiness and Sleep scores offline?
The repository reimplements the on-device algorithms for Readiness, Sleep, and Activity scores. However, those algorithms need Oura's proprietary PyTorch model files, which are gitignored and not included in the repository. Users must supply their own copies from their native app installation before the sleep-analyze command will work.
Which Oura Ring generations are compatible with open_oura?
The README targets Ring 3, 4, and 5, which share the same GATT layout, packet framing, and authentication flow. Live testing has confirmed pairing, authentication, and event sync on a Ring 3 Horizon and a Ring 5.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/th0rgal-open-oura)