Show HN: Convert the raw HealthKit DB from an iPhone backup to SQLite

circleoncircles1 pts0 comments

GitHub - ninyawee/healthkit-from-backup-to-sqlite: Convert the raw HealthKit database from an iPhone backup (healthdb_secure.sqlite) into a clean, queryable SQLite file for Datasette. The backup-store companion to dogsheep/healthkit-to-sqlite. · GitHub

/" data-turbo-transient="true" />

Skip to content

Search or jump to...

Search code, repositories, users, issues, pull requests...

-->

Search

Clear

Search syntax tips

Provide feedback

--><br>We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Cancel

Submit feedback

Saved searches

Use saved searches to filter your results more quickly

-->

Name

Query

To see all available qualifiers, see our documentation.

Cancel

Create saved search

Sign in

/;ref_cta:Sign up;ref_loc:header logged out"}"<br>Sign up

Appearance settings

Resetting focus

You signed in with another tab or window. Reload to refresh your session.<br>You signed out in another tab or window. Reload to refresh your session.<br>You switched accounts on another tab or window. Reload to refresh your session.

Dismiss alert

{{ message }}

ninyawee

healthkit-from-backup-to-sqlite

Public

Notifications<br>You must be signed in to change notification settings

Fork

Star

main

BranchesTags

Go to file

CodeOpen more actions menu

Folders and files<br>NameNameLast commit message<br>Last commit date<br>Latest commit

History<br>2 Commits<br>2 Commits

.gitignore

.gitignore

LICENSE

LICENSE

README.md

README.md

healthkit_from_backup_to_sqlite.py

healthkit_from_backup_to_sqlite.py

View all files

Repository files navigation

healthkit-from-backup-to-sqlite

Turn the raw HealthKit database from an iPhone backup into a clean, queryable<br>SQLite file you can browse with Datasette — no slow<br>on-device "Export All Health Data" step required.

This is the missing companion to Simon Willison's<br>healthkit-to-sqlite: that tool ingests the<br>Health app's export.zip (the "Export All Health Data" file). This one reads the raw<br>healthdb_secure.sqlite directly — the store Apple keeps on the device and syncs via iCloud —<br>which you get from an iPhone backup. The raw store is richer and avoids the slow, sometimes-failing<br>on-device XML export entirely.

healthkit-to-sqlite<br>this tool

Input<br>Health app export.zip<br>raw healthdb_secure.sqlite from a backup

Get the input<br>on-device export (slow, can fail/time out)<br>extract once from an encrypted backup

Fidelity<br>re-serialized XML<br>the original store Apple actually keeps

Output<br>SQLite for Datasette<br>SQLite for Datasette

healthdb_secure.sqlite ──[this tool]──> health.db ──> datasette<br>(source of truth, read-only) (derived, disposable lens)">iPhone backup ──> healthdb_secure.sqlite ──[this tool]──> health.db ──> datasette<br>(source of truth, read-only) (derived, disposable lens)

Why bother

The raw store is faithful but unfriendly: integer type enums with no string table, Apple-absolute<br>timestamps, per-type canonical units, and values split across quantity / original_quantity<br>columns. This tool resolves all of that into one readable database:

Readable type names — the data_type integer enum is mapped to names like HeartRate,<br>StepCount, SleepAnalysis (mapping cross-checked against<br>christophhagen/HealthDB and verified against<br>each DB's own row counts).

ISO-8601 timestamps — Apple-absolute seconds (since 2001-01-01) converted to UTC; daily<br>rollups bucket on a timezone offset you pass in.

Normalized units — pulse rates normalized to bpm (HealthKit stores some types as count/s and<br>others as count/min), distances in metres, energy in kcal.

Daily rollups — daily_steps, daily_distance_km, daily_active_energy,<br>daily_heart_rate, daily_sleep_hours.

Provenance — each sample keeps its source device and recorded timezone.

The raw DB is opened read-only and immutable — it is never modified. health.db is fully<br>regenerable: delete it and re-run any time.

Getting the raw database

Make an encrypted local backup of the iPhone (Finder/iTunes, or idevicebackup2).<br>Encryption is required — health data is only included in encrypted backups.

Extract HealthDomain/Health/healthdb_secure.sqlite from the backup (e.g. with<br>iMazing, or a backup-decryption library such as<br>iphone_backup_decrypt).

Usage

Requires uv (the script declares its own deps — none beyond<br>the stdlib — via PEP 723):

./healthkit_from_backup_to_sqlite.py healthdb_secure.sqlite health.db 7<br># ^raw (read-only) ^out ^UTC offset for daily rollups

All three args are optional (defaults: ./healthdb_secure.sqlite, ./health.db, +0/UTC).<br>Then explore:

uvx datasette health.db

What you get

The importer prints a summary as it builds (≈4 s for ~10 years of data). Illustrative run:

built health.db (220 MB)

row counts:<br>quantity_samples 1,300,000<br>category_samples 28,000<br>workouts 420

date range: ('2016-09-13 21:21:48', '2026-06-12 03:59:14')

top quantity types:<br>ActiveEnergyBurned 460,000<br>HeartRate 220,000<br>BasalEnergyBurned 170,000<br>StepCount 148,000<br>DistanceWalkingRunning 138,000

…and then the...

sqlite backup health healthkit from healthdb_secure

Related Articles