I’ve been reading about HRV (Heart Rate Variability) for a while and wanted a way to record it on my computer and actually understand the underlying calculations, rather than just consume a number from a proprietary app. I also wanted an excuse to finally play with the Web Bluetooth API, which lets a browser connect directly to Bluetooth LE devices with no native app or server involved. The result is web-hr-monitor, a small app that runs entirely in the browser — no backend, no install.
The live version is at guyru.github.io/web-hr-monitor. Open it in Chrome or Edge, click Connect to HR Monitor, pair your BLE heart rate monitor, and you get a live readout along with running average, maximum, minimum, and a heart rate distribution histogram for the session.
HRV Analysis
The more interesting part is the HRV analysis. After connecting, you can run a 2-minute test that collects RR intervals — the time between successive heartbeats — and computes two standard metrics:
- RMSSD (Root Mean Square of Successive Differences): measures short-term variability.
- SDNN (Standard Deviation of NN intervals): measures overall variability.
I did most of my testing with a Polar H7, which worked well.

Synthesized RR Intervals
While testing I ran into something worth knowing: not all heart rate monitors
report real RR intervals. Some devices don’t actually measure the time between
beats — instead they synthesize a value as 60000 / HR. The result is
mathematically consistent with the reported heart rate but has no actual
beat-to-beat variability, making HRV analysis meaningless.
I discovered this when I switched from the Polar H7 to a Decathlon ANT+/Bluetooth
heart rate monitor I had lying around. The app detects this automatically: if the
reported RR intervals consistently fall within 1 ms of 60000 / HR, it warns you
that the data is likely synthesized and HRV results are unreliable.
Browser Support
The Web Bluetooth API works in Chrome and Edge. Firefox and Safari don’t support it.
On Linux (and older Windows versions) you need to enable an experimental flag before it works:
- Open
chrome://flags#enable-experimental-web-platform-features - Enable the flag and restart the browser
On Windows 10/11 and Android it works out of the box. The app also requires an
HTTPS connection — the GitHub Pages deployment covers that, and http://localhost
works fine for local development.