platform-comparison
Purpose
Compare the two major mobile health data platforms and document methods for extracting personal health data from each.
Overview
Both Android and iOS provide on-device health data storage with API access for developers. Neither platform offers cloud-based APIs - all data access must occur through native mobile apps on the user’s device.
Critical Clarification: Local API, Not HTTP API
These are NOT web/HTTP APIs. Health Connect and HealthKit are local operating system APIs that can only be accessed by native mobile apps running on the device. There is no REST endpoint, no cloud service, no way to call these from a server or web browser.
❌ Cannot do: curl https://healthconnect.googleapis.com/v1/steps❌ Cannot do: fetch('https://api.apple.com/healthkit/data')
✅ Must do: Build native app → User grants permission → App reads local dataWhy? Privacy. Your health data never leaves your device unless you explicitly use an app that sends it somewhere.
FAQ: Common Questions
Q1: As an engineer, do I need to build an app to extract data?
Yes. You must build a native mobile app:
| Platform | Required |
|---|---|
| Android | Kotlin/Java app using Health Connect SDK |
| iOS | Swift/Objective-C app using HealthKit framework |
There is no alternative. You cannot:
- Query from a server or backend
- Use a web app or browser extension
- Run a Python/Node script on your computer to pull data
- Use any HTTP/REST API
The only way to programmatically access this data is through a native app installed on the user’s phone.
Q2: As a normal user, is there an export/dump feature?
| Platform | Built-in Export? | Details |
|---|---|---|
| iOS | ✅ Yes | Health app → Profile icon → Export All Health Data → Produces ZIP with XML |
| Android | ❌ No | No built-in export. Must install a third-party app that uses Health Connect |
iOS Export Details:
- Exports everything: steps, heart rate, sleep, workouts, etc.
- Format: XML files in a ZIP archive
- Size: Can be several GB for long-time users
- Location: Can AirDrop, save to Files, email, etc.
Android Workaround:
- Install an app like “Health Connect Toolbox” or similar
- The app reads your data via Health Connect API
- The app provides its own export feature (JSON, CSV, etc.)
Q3: What is HKExportSession?
HKExportSession is an Apple API introduced in iOS 19 (2025) for programmatic bulk exports.
Before HKExportSession:
- Apps had to query data type by type
- No standardized export format
- Manual export was the only bulk option
With HKExportSession:
- Apps can trigger bulk exports programmatically
- Exports up to 10GB of data as XML/JSON ZIP
- Can be integrated with iOS Shortcuts
- Still requires a native iOS app to use
// Example: Using HKExportSession (iOS 19+)let exportSession = HKExportSession(healthStore: healthStore)exportSession.exportData(to: destinationURL) { result in // Handle exported ZIP file}Use cases:
- Health apps offering “Download my data” feature
- Backup utilities
- Data portability tools
Q4: What is FHIR?
FHIR (Fast Healthcare Interoperability Resources) is a healthcare data standard - not an Apple or Google product.
What it is:
- An international standard for exchanging healthcare data
- Defines JSON/XML schemas for medical records
- Created by HL7 (Health Level Seven International)
- Used by hospitals, EHRs, insurance companies, health apps
Example FHIR resource (Patient):
{ "resourceType": "Patient", "id": "example", "name": [{"family": "Smith", "given": ["John"]}], "birthDate": "1990-01-15", "gender": "male"}FHIR resource types:
- Patient, Practitioner, Organization
- Condition (diagnoses), Medication, Allergy
- Observation (lab results, vitals)
- Immunization, Procedure
How it relates to Health Connect / HealthKit:
| Platform | FHIR Support |
|---|---|
| Apple HealthKit | Health Records feature - imports FHIR data from 500+ hospitals/clinics |
| Android Health Connect | Medical Records API - reads/writes FHIR-formatted clinical data |
Practical meaning: If you connect your health app to your hospital’s patient portal, your lab results and medications come in FHIR format and are stored in Health Connect / HealthKit.
Q5: Can I build an app that syncs users’ health data to my server?
Yes, this is a common and supported use case.
Architecture:
┌─────────────────────────────────────────────────────────────┐│ User's Phone ││ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││ │ Fitbit App │ ──▶ │ Health │ ◀── │ Apple Watch │ ││ │ Garmin App │ │ Connect / │ │ Sensors │ ││ │ MyFitnessPal│ │ HealthKit │ │ │ ││ └─────────────┘ └──────┬──────┘ └─────────────┘ ││ │ ││ ▼ ││ ┌─────────────────┐ ││ │ Your App │ ││ │ (Native iOS or │ ││ │ Android) │ ││ └────────┬────────┘ │└──────────────────────────────┼──────────────────────────────┘ │ HTTPS ▼ ┌─────────────────┐ │ Your Server │ │ (REST API) │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ Your Database │ │ (PostgreSQL, │ │ MongoDB, etc) │ └─────────────────┘What you need to build:
-
Native mobile app (or cross-platform with React Native/Flutter)
- Requests health data permissions from user
- Reads data from Health Connect / HealthKit
- Sends data to your backend via HTTPS
-
Backend API
- Receives health data from mobile app
- Stores in your database
- Handles authentication, rate limiting, etc.
Example sync flow (Android):
// In your Android appsuspend fun syncHealthData() { val steps = healthConnectClient.readRecords( ReadRecordsRequest(StepsRecord::class, timeRangeFilter = lastSync..now) )
// Send to your server yourApi.postHealthData( userId = currentUser.id, data = steps.records.map { it.toJson() } )}Existing services that do this for you:
- Thryve - aggregates Health Connect + HealthKit, provides unified API
- Human API - similar aggregation service
- Health Auto Export (iOS) - user-facing app that syncs to REST endpoints
- Vital - health data API platform
Privacy/compliance considerations:
- Health data is sensitive - ensure HIPAA compliance if in US
- Get explicit user consent
- Encrypt data in transit (HTTPS) and at rest
- Provide data deletion capability
- Consider GDPR if serving EU users
| Aspect | Android Health Connect | Apple HealthKit |
|---|---|---|
| Platform | Android 9+ (SDK 28) | iOS 8+ |
| Framework Location | Android Framework (14+) / Jetpack | iOS SDK |
| Data Storage | On-device, encrypted | On-device, encrypted |
| Cloud API | None | None |
| Current Version | Jetpack 1.1.0 (Jan 2026) | iOS 19+ |
| Replaces | Google Fit APIs (deprecated 2026) | N/A (original platform) |
Android Health Connect
What is Health Connect?
Health Connect is Android’s unified platform for health and fitness data management. It serves as a centralized hub where multiple health apps can read and write data with user permission. Starting in 2026, it replaces the deprecated Google Fit APIs.
Key Features
- 50+ data types: Steps, heart rate, sleep, nutrition, body measurements, vitals
- Medical records: FHIR format support for clinical data
- Background sync: Continuous data access even when app isn’t active
- On-device steps: Android 14+ automatically captures mobile steps
- User control: Granular permissions, data deletion, access revocation
Supported Data Types
Activity & Fitness:
- Steps (cumulative over time)
- Exercise sessions and routes (GPS)
- Distance, calories, power, speed
Body Measurements:
- Weight, height, body fat
- Basal metabolic rate
Vitals:
- Heart rate, blood pressure
- Blood glucose, oxygen saturation
- Body temperature
Sleep & Wellness:
- Sleep sessions and stages
- Mindfulness sessions
Nutrition:
- Meals, hydration
- Macro/micronutrients
Medical Records (FHIR):
- Allergies, conditions, medications
- Immunizations, lab results
API Access
Setup
// Add dependencyimplementation("androidx.health.connect:connect-client:1.1.0")
// Check availabilityval availabilityStatus = HealthConnectClient.getSdkStatus(context)if (availabilityStatus == HealthConnectClient.SDK_AVAILABLE) { val healthConnectClient = HealthConnectClient.getOrCreate(context)}Request Permissions
val PERMISSIONS = setOf( HealthPermission.getReadPermission(StepsRecord::class), HealthPermission.getReadPermission(HeartRateRecord::class), HealthPermission.getReadPermission(SleepSessionRecord::class))
// Request via ActivityResultContractval requestPermissionLauncher = registerForActivityResult( PermissionController.createRequestPermissionResultContract()) { granted -> // Handle permission result}requestPermissionLauncher.launch(PERMISSIONS)Read Data
// Read raw recordssuspend fun readSteps( client: HealthConnectClient, start: Instant, end: Instant): List<StepsRecord> { val response = client.readRecords( ReadRecordsRequest( StepsRecord::class, timeRangeFilter = TimeRangeFilter.between(start, end) ) ) return response.records}
// Read aggregated data (recommended for cumulative types)suspend fun readTotalSteps( client: HealthConnectClient, start: Instant, end: Instant): Long? { val response = client.aggregate( AggregateRequest( metrics = setOf(StepsRecord.COUNT_TOTAL), timeRangeFilter = TimeRangeFilter.between(start, end) ) ) return response[StepsRecord.COUNT_TOTAL]}Historical Data Access
By default, apps can only read 30 days of data. To access older data:
// Request history permissionval HISTORY_PERMISSION = HealthPermission.PERMISSION_READ_HEALTH_DATA_HISTORY
// Then read with data origin filterval response = client.readRecords( ReadRecordsRequest( recordType = HeartRateRecord::class, timeRangeFilter = TimeRangeFilter.between(startTime, endTime), dataOriginFilter = setOf(DataOrigin("com.example.app")) ))Pagination
var pageToken: String? = nullval allRecords = mutableListOf<HeartRateRecord>()
do { val response = client.readRecords( ReadRecordsRequest( recordType = HeartRateRecord::class, timeRangeFilter = TimeRangeFilter.between(start, end), pageToken = pageToken ) ) allRecords.addAll(response.records) pageToken = response.pageToken} while (pageToken != null)Data Export Methods
- Build Android app: Full programmatic access via Health Connect SDK
- Third-party apps: Apps like Thryve provide Health Connect integration
- No manual export: Unlike Apple Health, no built-in export feature in Settings
Apple HealthKit
What is HealthKit?
HealthKit is Apple’s framework for health and fitness data on iOS and watchOS. Introduced in iOS 8, it provides a centralized, secure repository for health data that apps can access with user permission.
Key Features
- 150+ data types: Comprehensive health metrics
- Health Records: FHIR-based medical records from 500+ hospitals
- Workout routes: GPS tracking for exercises
- On-device storage: All data encrypted with device passcode
- Manual export: Built-in XML export feature
- HKExportSession (iOS 19+): Bulk exports up to 10GB
Supported Data Types
Activity:
- Steps, distance, flights climbed
- Workouts with routes
- Stand hours, exercise minutes
Body Measurements:
- Weight, height, BMI
- Body fat percentage, lean body mass
Vitals:
- Heart rate, HRV, resting heart rate
- Blood pressure, respiratory rate
- Blood oxygen, body temperature
Sleep:
- Sleep analysis
- Time in bed
Nutrition:
- Dietary energy, water
- Macronutrients, vitamins, minerals
Reproductive Health:
- Menstrual cycle tracking
- Ovulation, fertility
Medical Records (FHIR):
- Allergies, conditions, immunizations
- Lab results, medications, procedures, vitals
API Access
Setup
import HealthKit
let healthStore = HKHealthStore()
// Check availabilityif HKHealthStore.isHealthDataAvailable() { // HealthKit is available}Request Authorization
let readTypes: Set<HKObjectType> = [ HKObjectType.quantityType(forIdentifier: .stepCount)!, HKObjectType.quantityType(forIdentifier: .heartRate)!, HKObjectType.categoryType(forIdentifier: .sleepAnalysis)!]
healthStore.requestAuthorization(toShare: nil, read: readTypes) { success, error in if success { // Authorization granted }}Query Data
// Sample query for stepsfunc readSteps(from start: Date, to end: Date, completion: @escaping ([HKQuantitySample]) -> Void) { let stepType = HKQuantityType.quantityType(forIdentifier: .stepCount)! let predicate = HKQuery.predicateForSamples(withStart: start, end: end)
let query = HKSampleQuery( sampleType: stepType, predicate: predicate, limit: HKObjectQueryNoLimit, sortDescriptors: [NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: true)] ) { query, samples, error in guard let samples = samples as? [HKQuantitySample] else { return } completion(samples) }
healthStore.execute(query)}
// Statistics query for aggregated datafunc readTotalSteps(from start: Date, to end: Date, completion: @escaping (Double?) -> Void) { let stepType = HKQuantityType.quantityType(forIdentifier: .stepCount)! let predicate = HKQuery.predicateForSamples(withStart: start, end: end)
let query = HKStatisticsQuery( quantityType: stepType, quantitySamplePredicate: predicate, options: .cumulativeSum ) { query, statistics, error in let sum = statistics?.sumQuantity()?.doubleValue(for: .count()) completion(sum) }
healthStore.execute(query)}Background Delivery
// Enable background delivery for a data typehealthStore.enableBackgroundDelivery( for: HKObjectType.quantityType(forIdentifier: .heartRate)!, frequency: .immediate) { success, error in // Handle result}Data Export Methods
1. Manual Export (Built-in)
- Open Health app on iPhone
- Tap profile picture → Export All Health Data
- Produces
export.zipcontaining XML files - Can be up to 10GB for long-time users
2. Build iOS App
Full programmatic access via HealthKit SDK (see code examples above)
3. Third-Party Apps
Health Auto Export (recommended for non-developers):
- Exports 150+ metrics
- Syncs to REST API, CSV, JSON
- Supports automations via Shortcuts
- TCP server for direct device access
Limitations:
- Automations don’t run while device is locked
- iOS restricts background execution
4. Python Parsing (Post-Export)
After manual export, use apple-health-parser:
from apple_health_parser import HealthData
# Load exported datahealth_data = HealthData("path/to/export.xml")
# Access specific metricssteps = health_data.get_record_type("StepCount")heart_rate = health_data.get_record_type("HeartRate")
# Convert to DataFrame for analysisdf = steps.to_dataframe()Comparison Summary
Data Access
| Feature | Health Connect | HealthKit |
|---|---|---|
| Historical data | 30 days default, unlimited with permission | Unlimited |
| Background sync | Yes (with permission) | Yes (with background delivery) |
| Aggregation | Built-in aggregate() API | Statistics queries |
| Pagination | pageToken-based | Anchor queries |
| Real-time updates | Change notifications | Observer queries |
Export Options
| Method | Health Connect | HealthKit |
|---|---|---|
| Manual export UI | No | Yes (XML) |
| Programmatic export | Yes (build app) | Yes (build app) |
| Third-party apps | Limited | Health Auto Export, others |
| Export format | JSON (programmatic) | XML (manual), any (programmatic) |
Development
| Aspect | Health Connect | HealthKit |
|---|---|---|
| Language | Kotlin/Java | Swift/Objective-C |
| Min SDK | Android 9 (API 28) | iOS 8 |
| Framework | Jetpack library | iOS SDK built-in |
| Testing tools | Health Connect Toolbox | Xcode Health simulator |
Recommendations
For Personal Data Extraction
If you use Android:
- Use a third-party app with Health Connect integration
- Or build a simple Android app to export your data
If you use iOS:
- Easiest: Manual export from Health app (Settings → Export)
- Automated: Use Health Auto Export app
- Custom: Build iOS app with HealthKit
For Developers Building Health Apps
- Support both platforms for maximum reach
- Use standardized formats (FHIR) for medical data
- Implement proper permission flows - users are sensitive about health data
- Consider using aggregation services like Thryve or Human API for cross-platform support