Skip to content
AF
Health Data

Cycling Power API: Power, Cadence and Speed Data Across Platforms

Last verified October 18, 2026 · 5 min read

Cycling power and cadence reach an app either as samples another app wrote into a platform store or straight from a Bluetooth sensor, and the two have different shapes. Apple HealthKit has had cyclingPower, cyclingCadence, cyclingSpeed and cyclingFunctionalThresholdPower since iOS 17.0 as discrete samples, and Apple describes both power types as estimated; Health Connect has PowerRecord, CyclingPedalingCadenceRecord and SpeedRecord as series records, with cadence read under the general exercise permission. The Bluetooth Cycling Power and CSC characteristics send instantaneous watts plus cumulative wheel and crank revolution counts with event times, not a cadence or speed value, so your code derives those. The Google Health API has no power or cadence type, and Wear OS Health Services offers only a general SPEED.

Covered here:HealthKitHealth Connect

A rider's power and cadence come from sensors on the bike, not the wrist. The platform stores hold those values after some app has read the sensor and written them, and the Bluetooth profiles carry them on the way in. This page is about the types on both ends. For pairing several sensors, choosing one source of truth and the FTMS overlap, see reading cycling power, cadence and speed sensors.

Where each value lives#

MetricApple HealthKitAndroid Health ConnectWear OS Health ServicesBluetooth GATT
PowercyclingPower: discrete, power unitsPowerRecord: a Series, POWER_AVG, POWER_MAX, POWER_MINnoneCycling Power Measurement 0x2A63: Instantaneous Power, a sint16 in watts
CadencecyclingCadence: discrete, counts per minuteCyclingPedalingCadenceRecord: a Series, RPM_AVG, RPM_MAX, RPM_MINnonecrank revolution data in Cycling Power Measurement and CSC Measurement 0x2A5B
SpeedcyclingSpeed: discrete, distance per timeSpeedRecord: a Series, SPEED_AVG, SPEED_MAX, SPEED_MINSPEED: meters per secondwheel revolution data in the same two characteristics
Threshold powercyclingFunctionalThresholdPower: discrete, power unitsnonenonenone

Read from Apple's documentation on 2026-10-02, Google's Health Connect reference on 2026-10-03, its Health Services reference on 2026-10-04 and the Bluetooth SIG's files on 2026-10-17. All four HealthKit types are available from iOS 17.0 and watchOS 10.0.

The Google Health API is the platform with nothing here. It has no power, cadence or cycling speed data type, and the per-exercise summary its exercise type carries, which this page does not cover, has an average speed and pace but no power or cadence field in the discovery document.

Estimated, generated, or instantaneous#

The descriptions differ in a way that matters for labels. Apple's cyclingPower "measures the estimated power being used while riding a bike," and cyclingFunctionalThresholdPower "measures the estimated maximum average power sustained while riding a bike for 60 minutes." Google's PowerRecord "Captures the power generated by the user, e.g. during cycling or rowing with a power meter." The Bluetooth characteristic reports an Instantaneous Power from the sensor itself.

Apple's word is "estimated," and the identifier data does not say what produces the estimate. As our cycling app guide puts it, the HealthKit types are a place to write and read a value, not a source of one. Show the writing app's name beside any power value you read from a store.

Samples versus series#

HealthKit stores each value as a discrete quantity sample, so a statistics query averages or takes the minimum or maximum, and summing power or cadence gives a meaningless number. Health Connect stores a ride's values as a Series record: one record per stretch of time, holding a list of samples, with averages, maxima and minima as aggregates. Wear OS delivers SPEED as a SampleDataPoint during an exercise, with SPEED_STATS for the session.

Cadence has a unit question on top. Health Connect's aggregates are named in revolutions per minute (RPM); Apple's cadence uses counts-per-minute units, and its identifier text does not say what one count is. Check one against the other on a device before you map them.

Revolutions, not RPM, on the wire#

Neither Bluetooth characteristic has a cadence or speed field. Each sends counters and times, and your code turns two consecutive notifications into a rate:

FieldCycling Power MeasurementCSC Measurement
Cumulative Wheel Revolutionsuint32, present when Flags bit 4 is setuint32, present when Flags bit 0 is set
Last Wheel Event Timeuint16 in 1/2048 seconduint16 in 1/1024 second
Cumulative Crank Revolutionsuint16, present when Flags bit 5 is setuint16, present when Flags bit 1 is set
Last Crank Event Timeuint16 in 1/1024 seconduint16 in 1/1024 second

Two details from that table catch people. The wheel event time has twice the resolution in the power characteristic as in the speed and cadence one, so one shared parser is wrong for one of them. And turning wheel revolutions into a speed needs a distance per revolution that neither characteristic carries.

Cycling Power Measurement can carry much more, each behind its own bit of a 16-bit Flags field: Pedal Power Balance in half-percent units, Accumulated Torque in 1/32 newton meter with a bit saying whether it is wheel- or crank-based, extreme force and torque magnitudes, extreme angles, top and bottom dead spot angles, and Accumulated Energy in kilojoules. Because every optional field shifts the ones after it, offsets depend on which bits are set; the byte-layout page shows how. Cycling Power Vector 0x2A64 adds arrays of instantaneous force and torque magnitudes, with the crank angle of the first measurement.

Permissions#

Health Connect reads power under android.permission.health.READ_POWER and speed under READ_SPEED, but cadence under android.permission.health.READ_EXERCISE, the same permission as exercise sessions, rather than a cadence permission of its own. Wear OS SPEED sits under ACTIVITY_RECOGNITION in Google's Health Services permissions table. A cadence feature on Android therefore asks the user for exercise access.

Traps#

  • One parser for two time bases. 1/2048 second in Cycling Power Measurement, 1/1024 second in CSC Measurement.
  • Counters wrap. The crank counter is a uint16; handle rollover between notifications.
  • Estimated in Apple's words. Do not relabel a HealthKit power value as measured.
  • Exercise permission for cadence. On Android, plan for the broader consent screen.
  • Nothing to read in the cloud. A Fitbit or Pixel Watch user's power and cadence are not in the Google Health API types.

Before you ship#

Re-read the identifier, record and characteristic pages before each release; they regenerate from Apple's, Google's and the SIG's sources. Parse each characteristic with its own time base, derive cadence and speed in one tested place, and store which app or sensor produced every value you read from a store.

Cycling power, cadence and speed, by platform

Each type links its reference page on this site. The quote is the platform's own description of the type, copied from the generated reference data, and it is the reason the type is listed: nothing here is paired by name. A platform with nothing listed has no type with a page here whose description names this metric.

Google Health API · read 2026-10-17

Nothing listed.

Apple HealthKit · read 2026-10-02

  • cyclingPower — discrete values · power units · iOS 17.0+
    “A quantity sample type that measures the estimated power being used while riding a bike.” — Apple
  • cyclingCadence — discrete values · counts per minute units · iOS 17.0+
    “A quantity sample type that represents the rate at which the user is pedaling.” — Apple
  • cyclingSpeed — discrete values · distance per time units · iOS 17.0+
    “A quantity sample type that measures how fast you are traveling while riding a bike.” — Apple
  • cyclingFunctionalThresholdPower — discrete values · power units · iOS 17.0+
    “A quantity sample type that measures the estimated maximum average power sustained while riding a bike for 60 minutes.” — Apple

Android Health Connect · read 2026-10-03

  • PowerRecord — Series record · Activity category · aggregates: POWER_AVG, POWER_MAX, POWER_MIN
    “Captures the power generated by the user, e.g. during cycling or rowing with a power meter.” — Google
  • CyclingPedalingCadenceRecord — Series record · Activity category · aggregates: RPM_AVG, RPM_MAX, RPM_MIN
    “Captures the user's cycling pedaling cadence.” — Google
  • SpeedRecord — Series record · Activity category · aggregates: SPEED_AVG, SPEED_MAX, SPEED_MIN
    “Captures the user's speed, e.g. during running or cycling.” — Google

Wear OS Health Services · read 2026-10-04

  • DataType.SPEED — DeltaDataType · SampleDataPoint<Double> · permission ACTIVITY_RECOGNITION
    “Speed at a specific point in time, expressed as meters/second.” — Google

Bluetooth GATT · read 2026-10-17

  • Cycling Power Measurement — 0x2A63 · 12 fields · flags-dependent layout
    “The Cycling Power Measurement characteristic is used to represent data related to a cycling power sensor.” — Bluetooth SIG
  • Cycling Power Vector — 0x2A64 · 5 fields · flags-dependent layout
    “The Cycling Power Vector characteristic is used to represent power vector data related to a cycling power sensor.” — Bluetooth SIG
  • CSC Measurement — 0x2A5B · 3 fields · flags-dependent layout
    “The CSC Measurement characteristic is used to represent data related to a cycling speed and cadence (CSC) sensor.” — Bluetooth SIG

Frequently asked questions

Which Health Connect permission covers cycling cadence?
The exercise permission. Google's data-types table puts CyclingPedalingCadenceRecord under android.permission.health.READ_EXERCISE and WRITE_EXERCISE, the same strings as exercise sessions, rather than a cadence permission of its own. Power and speed have their own: PowerRecord uses READ_POWER and WRITE_POWER, and SpeedRecord uses READ_SPEED and WRITE_SPEED. All three are Series records with average, maximum and minimum aggregates.
Does the Bluetooth CSC characteristic send cadence in RPM?
No. CSC Measurement (0x2A5B) sends a cumulative crank revolution count as a uint16 and the time of the last crank event in units of 1/1024 second, present when bit 1 of its Flags field is set, and the same pair for the wheel when bit 0 is set. Your code computes cadence from the change between two notifications, handling the counter's rollover.
Why does Apple describe HealthKit cycling power as estimated?
That is Apple's wording: cyclingPower measures the estimated power being used while riding a bike, and cyclingFunctionalThresholdPower the estimated maximum average power sustained for 60 minutes. Apple's identifier documentation does not say what produces the estimate, and the value in the store is whatever an app wrote. Health Connect's PowerRecord, by contrast, describes power generated by the user with a power meter.
Can I get cycling power from the Google Health API?
Not from a data type. None of the Google Health API's 44 data types is power or cadence, and the exercise summary in its discovery document has average speed and pace but no power or cadence field. For power on Android, read Health Connect's PowerRecord, which Google describes with cycling and rowing as examples, or read the sensor over Bluetooth.

All 132 questions in Health Data →

Keep reading

Elsewhere on the site

Pages that share this one’s concepts and sources, from other sections.

Next steps

Was this page useful?

Independent comparison, last reviewed October 18, 2026. Pricing, rate limits, and feature availability change often — confirm current details in each provider’s official documentation before you commit. Product and company names are trademarks of their respective owners; AIFitnessAPI is not affiliated with, endorsed by, or sponsored by any product listed here.

← All health data · by AIFitnessAPI