Body Temperature API: Core, Skin and Wrist Temperature Data
Last verified October 18, 2026 · 7 min read
Covered here:Health ConnectHealthKitOuraWHOOP
Temperature looks like the simplest vital a health store holds: one number, one unit. In the platform data it is three different measurements that happen to share a word. One is a reading of the body, taken with a thermometer. One is the same kind of reading taken at rest, which both mobile stores file under cycle tracking rather than vitals. The third is skin temperature measured overnight by a wearable, and that one is often not an absolute temperature at all. Mixing them is the main way a temperature feature goes wrong.
Three temperatures, not one#
| Kind | Google Health API | Apple HealthKit | Android Health Connect | Bluetooth GATT |
|---|---|---|---|---|
| Body or core reading | core-body-temperature: a Sample in Celsius | bodyTemperature: discrete, temperature units, group Vital signs | BodyTemperatureRecord: instantaneous, Vitals | Temperature Measurement 0x2A1C |
| Basal, at rest | none | basalBodyTemperature: group Reproductive health | BasalBodyTemperatureRecord: Cycle Tracking | none |
| Skin, during sleep | daily-sleep-temperature-derivations: one Daily record a night; skin-temperature-sensors: v4beta samples | appleSleepingWristTemperature: read-only, group Body measurements | SkinTemperatureRecord: a Series of deltas, Vitals | none |
Every cell comes from this site's generated references: Google Health API types read from Google's documentation on 2026-10-17, HealthKit identifiers from Apple's on 2026-10-02, Health Connect records from Google's on 2026-10-03, and the Bluetooth SIG's GATT files read on 2026-10-17. Wear OS Health Services has no row because none of the 65 DataType constants in Google's reference, read 2026-10-04, is a temperature.
The descriptions say plainly that these are different measurements. Google describes core-body-temperature as a "Core body temperature measurement, distinct from peripheral body temperature," that "reflects the temperature of the body's internal organs." Health Connect's basal record "Captures the body temperature of a user when at rest (for example, immediately after waking up). Can be used for checking the fertility window." On both mobile stores the basal type sits with reproductive data and has its own permission, android.permission.health.READ_BASAL_BODY_TEMPERATURE on Android, separate from READ_BODY_TEMPERATURE. The menstrual cycle API guide covers basal temperature as a cycle input.
Absolute readings and deltas#
The skin-temperature types are where the shapes split.
Health Connect's SkinTemperatureRecord is a Series record that "can represent a series of measurements of temperature differences." Its deltas field is "a list of skin temperature Delta. If baseline is set, these values are expected to be relative to it. Otherwise, they are deltas against an unspecified starting baseline." The baseline itself is optional and null by default. Its aggregates are TEMPERATURE_DELTA_AVG, TEMPERATURE_DELTA_MAX and TEMPERATURE_DELTA_MIN, typed TemperatureDelta, and the record sits behind a feature check: Google's reference says to call getFeatureStatus with FEATURE_SKIN_TEMPERATURE before reading or writing it.
The Google Health API reports the same idea as a daily summary. Its daily-sleep-temperature-derivations type "Provides derived sleep temperature values, calculated from skin or internal device temperature readings during sleep." The required nightlyTemperatureCelsius is "the mean of skin temperature samples taken from the user’s sleep"; the optional baselineTemperatureCelsius is "the median of the user's nightly skin temperature over the past 30 days"; and relativeNightlyStddev30dCelsius gives the spread of nightly minus baseline over 30 days. Google's migration table maps the Fitbit Web API's skin temperature data to it, and the type supports webhooks.
Apple's appleSleepingWristTemperature is a discrete sample in temperature units, available from iOS 16.0 and watchOS 9.0, and Apple states "These samples are read-only." Apple's longer discussion of how Apple Watch builds the nightly value is quoted on our menstrual cycle API page.
So a Health Connect value may be relative to nothing you can see, a Google value is an absolute nightly mean with its baseline beside it, and an Apple value is a sample whose shape Apple sets. If you want one series across platforms, our recommendation is to store Google's nightly mean and baseline separately and compute any difference yourself, and to keep Health Connect deltas in a column of their own until a record tells you its baseline.
Among the wearable vendors, our Oura vs WHOOP comparison describes Oura's temperature as a nightly deviation from the user's own baseline rather than an absolute reading, and WHOOP's skin temperature as available to 4.0 members. Verify both in each vendor's current documentation.
Units, ranges and the Fahrenheit flag#
- Google Health API: Celsius in the field name.
core-body-temperaturetakestemperatureCelsiusin the range[0, 100]; the nightly and sensor types report Celsius too. - Health Connect: a
Temperatureunit object. Body, basal and skin baseline values share the documented valid range of 0 to 100 Celsius degrees. - HealthKit: temperature units chosen by you on read and write, as for every quantity type; store the
HKUnityou used beside the value. - Bluetooth: bit 0 of the Temperature Measurement Flags field decides the unit. At 0 the value field is Celsius; at 1 it is Fahrenheit. The value is a
medfloat32either way, so a parser that ignores the flag reads a plausible number in the wrong scale.
Where the reading was taken#
Each platform records the body site differently, and only some make it a field:
- Google:
core-body-temperaturehas an optionalmeasurementLocationenum of 18 values, fromARMPIT,EAR,MOUTHandFOREHEADtoTEMPORAL_ARTERY,WRISTandGASTRO_INTESTINAL, plusOTHERandMEASUREMENT_LOCATION_UNSPECIFIED. - Health Connect:
BodyTemperatureRecordhasmeasurementLocation, which Google's data-types table lists among the mandatory fields while the Kotlin reference calls it optional; check both against your SDK version.SkinTemperatureRecordtakesMEASUREMENT_LOCATION_FINGER,MEASUREMENT_LOCATION_TOE,MEASUREMENT_LOCATION_WRISTorMEASUREMENT_LOCATION_UNKNOWN, the default. - HealthKit: no field; Apple keeps the site in
HKMetadataKeyBodyTemperatureSensorLocation, "The location where a specific body temperature reading was taken." - Bluetooth: an optional Temperature Type field, present when bit 2 of Flags is set, in the format of the Temperature Type characteristic, which the SIG ties to IEEE 11073-10408-2008.
How each one is read#
- Google Health API:
core-body-temperaturelistslist,get,reconcile,rollupanddailyRollup, and its rollup returns an average, maximum and minimum in Celsius; Google's table marks it with no webhook support and names no compatible device.daily-sleep-temperature-derivationslistslistandreconcileonly.skin-temperature-sensorsis on the v4beta preview channel, lists onlylist, and Google's table names two compatible devices, Pixel Watch 4 and Pixel Watch 5. - HealthKit: all three temperature identifiers are discrete, so a statistics query averages or takes the minimum or maximum; summing them is meaningless.
- Health Connect:
BodyTemperatureRecordand the basal record have no aggregate metrics; read the records. The skin record aggregates deltas only. - Bluetooth: a thermometer can also send Intermediate Temperature 0x2A1E, which the SIG describes as values sent "for display purposes while a measurement is in progress." It has the same layout as the final measurement, so subscribe to both only if you show progress, and store the final one.
Traps#
- A delta is not a temperature. Plotting Health Connect skin deltas on the same axis as a Google nightly mean draws a line that means nothing.
- Basal is its own permission. An app granted body temperature on Android has not been granted basal temperature, and the two live in different categories on both stores.
- The feature check is not optional. On a device without the skin temperature feature,
SkinTemperatureRecordcannot be read or written at all; design the empty state. - Preview channel.
skin-temperature-sensorsis v4beta; build against it knowing Google can change it before it reaches v4. - Unit flags on the wire. Read the Bluetooth Flags byte before the value, every notification.
Keep the claims small#
Body temperature is a vital sign, and an app that flags a fever, predicts illness or reads meaning into a skin-temperature change is making a different product from one that shows a trend. Our FDA fitness app regulation page sets out how the general-wellness line is usually drawn. Nothing on this page is medical advice, and none of the platforms above documents a threshold your UI should apply.
Before you ship#
Re-read each type's reference page here before release; they regenerate from Google's, Apple's and the SIG's sources. Store the kind of temperature, the unit, the site and whether the value is a delta. On Android, gate skin temperature behind the feature check and request basal temperature separately. On Bluetooth, read the unit flag first.
Body temperature, 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
- core-body-temperature — Sample record · operations: list, get, reconcile, rollup, dailyRollup · no webhook support in Google's table
“Core body temperature measurement, distinct from peripheral body temperature, reflects the temperature of the body's internal organs.” — Google
- daily-sleep-temperature-derivations — Daily record · operations: list, reconcile · webhook support
“Provides derived sleep temperature values, calculated from skin or internal device temperature readings during sleep.” — Google
- skin-temperature-sensors — Sample record · operations: list · no webhook support in Google's table · v4beta (preview channel)
“Skin temperature sensor data containing multi-sensor readings.” — Google
Apple HealthKit · read 2026-10-02
- bodyTemperature — discrete values · temperature units · iOS 8.0+
“A quantity sample type that measures the user’s body temperature.” — Apple
- appleSleepingWristTemperature — discrete values · temperature units · iOS 16.0+ · read-only
“A quantity sample type that records the wrist temperature during sleep.” — Apple
- basalBodyTemperature — discrete values · temperature units · iOS 9.0+
“A quantity sample type that records the user’s basal body temperature.” — Apple
Android Health Connect · read 2026-10-03
- BodyTemperatureRecord — Instantaneous record · Vitals category · Temperature unit · no aggregate metrics
“Captures the body temperature of a user.” — Google
- SkinTemperatureRecord — Series record · Vitals category · Temperature unit · aggregates: TEMPERATURE_DELTA_AVG, TEMPERATURE_DELTA_MAX, TEMPERATURE_DELTA_MIN · behind FEATURE_SKIN_TEMPERATURE
“Captures the skin temperature of a user.” — Google
- BasalBodyTemperatureRecord — Instantaneous record · Cycle Tracking category · Temperature unit · no aggregate metrics
“Captures the body temperature of a user when at rest (for example, immediately after waking up).” — Google
Wear OS Health Services · read 2026-10-04
Nothing listed.
Bluetooth GATT · read 2026-10-17
- Temperature Measurement — 0x2A1C · 5 fields · flags-dependent layout
“The Temperature Measurement characteristic is used to represent data related to a temperature measurement.” — Bluetooth SIG
- Intermediate Temperature — 0x2A1E · 5 fields · flags-dependent layout
“The Intermediate Temperature characteristic is used to send intermediate temperature values to a device for display purposes while a measurement is in progress. The Intermediate Temperature characteristic has the same format as the Temperature Measurement characteristic in \autoref{sec:org.bluetooth.characteristic.temperature_measurement} except that, due to a different context, the Measurement Value field is referred to as the Intermediate Temperature field.” — Bluetooth SIG
Frequently asked questions
- Is Health Connect skin temperature an absolute reading or a change?
- A change. Google documents SkinTemperatureRecord as a Series record that can represent a series of measurements of temperature differences. Its deltas are relative to the record's baseline when one is set, and otherwise to an unspecified starting baseline, and the baseline field is optional and null by default. The aggregates it offers, TEMPERATURE_DELTA_AVG, MAX and MIN, are temperature deltas too. Check FEATURE_SKIN_TEMPERATURE before reading it.
- Does Wear OS Health Services have a temperature data type?
- No. None of the 65 DataType constants in Google's Health Services reference, read on 2026-10-04, is a temperature, so a Wear OS app cannot ask Health Services for one. The temperature types this site documents for Android are Health Connect's BodyTemperatureRecord, BasalBodyTemperatureRecord and SkinTemperatureRecord, read through the Health Connect client, and the Google Health API's cloud types for Fitbit and Pixel devices.
- How does a Bluetooth thermometer say whether a reading is Celsius or Fahrenheit?
- With bit 0 of the Flags field that opens the Temperature Measurement characteristic, 0x2A1C. When the bit is 0 the measurement value is in degrees Celsius, and when it is 1 the value is in degrees Fahrenheit, a medfloat32 in both cases. Bit 1 adds a time stamp and bit 2 a temperature type giving the body site. Intermediate Temperature, 0x2A1E, uses the same layout for values shown while a measurement is still in progress.
- What does the Google Health API report for nightly skin temperature?
- One Daily record per night from daily-sleep-temperature-derivations. Google describes nightlyTemperatureCelsius as the mean of skin temperature samples taken during sleep, an optional baselineTemperatureCelsius as the median of the nightly value over the past 30 days, and an optional standard deviation of nightly minus baseline over 30 days. The type supports list and reconcile with webhooks, and Google maps the Fitbit Web API's skin temperature data to it.
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