← Health Export AI

Guides → export.xml is too big

Apple Health export.xml is too big — what to do about it

Apple Health exports everything you have ever recorded into a single export.xml file. For anyone who has worn a Watch for a year or two that file is routinely hundreds of megabytes, which is why your text editor hangs, Numbers refuses it, and pasting it into ChatGPT or Claude is not an option. You do not need to open the whole thing — you need to pull out the few records you actually want.

Published 24 July 2026

Why is Apple Health's export.xml so large?

Because it is a complete, uncompressed event log rather than a summary. Every heart-rate reading your Watch has ever taken is its own XML element, and each one carries the full type identifier, source device, unit, and three timestamps. A single reading looks roughly like this:

<Record type="HKQuantityTypeIdentifierHeartRate" sourceName="Apple Watch"
        sourceVersion="10.2" unit="count/min" creationDate="2026-07-24 09:14:02 +0100"
        startDate="2026-07-24 09:14:00 +0100" endDate="2026-07-24 09:14:00 +0100"
        value="62"/>

That is around 250 bytes of markup to store one number. The Watch samples heart rate continuously, so a single active day can produce thousands of these. Multiply by every metric and every day since you got the device and the arithmetic explains itself — the payload is small, the wrapper is not.

Three consequences follow, and they are the three things people actually search for:

Why you cannot paste export.xml into ChatGPT or Claude

Because of context limits, and the gap is not close. You can check the arithmetic for your own file rather than trusting a number from an article.

A widely used rule of thumb for English text and markup is roughly 4 characters per token. XML tends to be somewhat denser in tokens than prose because punctuation and attribute names split frequently, so treat this as a floor, not a precise figure. To get the real character count of your own export:

# macOS / Linux — character count of your export
wc -c apple_health_export/export.xml

# rough token floor
echo $(( $(wc -c < apple_health_export/export.xml) / 4 ))
Do the maths on your own file. A 200 MB export is on the order of 50 million tokens by that floor. Current frontier models top out in the hundreds of thousands. The shortfall is two orders of magnitude, which is why "just paste it in" cannot be made to work by waiting for bigger context windows.

First, get the export off your phone

On iPhone: open Health → tap your profile picture (top right) → Export All Health Data → confirm. It takes several minutes and produces export.zip. Save it somewhere with room — the unzipped folder is considerably larger than the archive.

Unzip it and you get apple_health_export/ containing export.xml, usually export_cda.xml, and a workout-routes/ folder of GPX files.

Fix 1: extract only the records you need (free)

Do not load the file into memory. Stream it, keep only the record types you care about, and throw the rest away as you go. Python's iterparse does this in constant memory, so file size stops mattering:

import xml.etree.ElementTree as ET, csv

WANT = "HKQuantityTypeIdentifierHeartRateVariabilitySDNN"

with open("hrv.csv", "w", newline="") as out:
    w = csv.writer(out)
    w.writerow(["startDate", "value", "unit"])
    for event, el in ET.iterparse("apple_health_export/export.xml", events=("end",)):
        if el.tag == "Record" and el.get("type") == WANT:
            w.writerow([el.get("startDate"), el.get("value"), el.get("unit")])
        el.clear()          # free the element immediately — this is the important line

The el.clear() call is what keeps memory flat. Without it you are back to holding the whole document. Swap WANT for any identifier — HKQuantityTypeIdentifierStepCount, HKQuantityTypeIdentifierRestingHeartRate, and so on. Our reference of all 190 metrics lists the exact identifier for each.

To see which types your own file actually contains before you start:

grep -o 'type="HK[A-Za-z]*"' apple_health_export/export.xml | sort | uniq -c | sort -rn | head -30

Fix 2: collapse it to daily values (free)

Even one extracted metric is usually too granular. Thousands of heart-rate readings are not a useful input to a question like "how did my resting heart rate trend this year" — daily aggregates are. Aggregate as you stream:

import xml.etree.ElementTree as ET, json
from collections import defaultdict

daily = defaultdict(list)
WANT = "HKQuantityTypeIdentifierHeartRateVariabilitySDNN"

for event, el in ET.iterparse("apple_health_export/export.xml", events=("end",)):
    if el.tag == "Record" and el.get("type") == WANT:
        day = el.get("startDate")[:10]          # YYYY-MM-DD
        daily[day].append(float(el.get("value")))
    el.clear()

out = [{"d": d, "v": round(sum(v) / len(v), 2)} for d, v in sorted(daily.items())]
json.dump(out, open("hrv-daily.json", "w"), indent=0)
print(len(out), "days")

This is the step that makes the data answerable. A year of daily values is a few hundred rows — small enough to hand to any model, and small enough to read yourself. Sum instead of average for cumulative metrics such as steps or active energy; average is right for rates such as heart rate and HRV.

Fix 3: skip the XML entirely

The two fixes above are the honest answer if you want to stay in free tooling, and they work. The reason a dedicated tool exists is that this is a chore you have to repeat every time you want fresh data — Apple's export is a manual, all-or-nothing snapshot with no incremental option.

Health Export AI reads HealthKit directly on the phone and writes already-aggregated JSON, so there is no XML step at all. It also ships an open-source MCP server so an agent can query the result as live tools rather than being handed a file. The app is $2.99 once after a 7-day trial; the server is MIT-licensed and free.

Which approach should you pick?

If you want to…UseCost
Pull one metric out, onceFix 1 — stream and filterFree
Analyse trends, or feed a modelFix 2 — daily aggregatesFree
Refresh regularly, or query from an agentFix 3 — export directly from the phonePaid app, free server

Common questions

How big is Apple Health's export.xml?

It depends entirely on how long you have been recording and whether you wear a Watch. Phone-only users with step data measure in tens of megabytes; multi-year Watch users routinely see hundreds. Run wc -c export.xml on your own file rather than relying on a typical figure — the variance between two people is larger than any average is useful for.

Can I open export.xml in Excel or Numbers?

No. It is a nested XML event log, not a table, so there is no sheet for it to become. Convert the records you want to CSV first — Fix 1 above does exactly that.

What is export_cda.xml?

A Clinical Document Architecture version of a subset of your data, intended for exchange with healthcare systems. It is not a smaller copy of export.xml and is usually not what you want for analysis.

Does Apple offer JSON or an incremental export?

No. The built-in export is XML only, all-or-nothing, and manual. Getting JSON or incremental updates means reading HealthKit through an app on the device.

Is it safe to upload my export to an AI service?

That is your call, but it is worth being deliberate: the file contains your complete health history, not just the part relevant to your question. Extracting only the metric and date range you need — Fix 1 and 2 — is a meaningful reduction in what you share. Running the analysis locally shares nothing at all.

Health Export AI · local-first, read-only. · Home · Privacy · Terms · Support · Security