KnownPace

Explainer

A Garmin export is 1,258 files. Fifty-four of them are your workouts.

I unpacked my own Garmin account export and read every file. Where each number lives, why the .fit filenames are useless, and the ten lines that fix that.

Every time Garmin Connect refuses to show you something — the decimal on your VO2 max, what your race prediction said three weeks ago, which factor dragged today’s training readiness down — the number usually exists. Garmin computed it, stored it, and decided not to print it.

The account export is where it lives. It is also badly documented, and most of the guides describing it are copying each other rather than opening one. So I opened mine and read all 73 entries.

Three ways out, only one of them complete

RouteWhat you getGood for
Single activity → gear icon → Export OriginalOne .fit file — every recorded data pointOne run you want to analyse or re-upload
Single activity → gear icon → TCX / GPX / KMLTrack plus some or no sensor dataMoving a route somewhere else
Activities list → export controlA CSV, one row per activityA quick spreadsheet of distances and times
Account Settings → Export Your DataThe whole archive described belowAnything Connect will not show you
All four live on the Connect website, under Account Settings or on the activity itself.

The account export is not instant — mine arrived by email as a download link, not while I waited. Request it before you need it.

What actually arrives

A 6.2 MB zip that unpacks to 7.9 MB. Seventy-three entries: 40 files and 33 empty folders.

The empty ones are AVIATIONCLOUD, NAVIONICS, DI_TACX, INREACH, DI_BASEBALL_IMPACT, FLY_GARMIN and twenty-seven more. Garmin ships every customer the shape of its entire product catalogue and fills in the two or three folders that apply. It looks alarming and means nothing.

Everything that matters to a runner sits under DI_CONNECT/.

The map

This is the part no guide gives you: which file holds which number. Row counts are from my own export — two months, one watch.

File under DI_CONNECT/What is in itRows in minemeasured
DI-Connect-Metrics/RunRacePredictions_*.jsonDaily 5K, 10K, half and marathon predictions, in seconds187
DI-Connect-Metrics/TrainingReadinessDTO_*.jsonReadiness score plus each factor's own percentage178
DI-Connect-Metrics/MetricsAcuteTrainingLoad_*.jsonAcute and chronic load per day, plus ACWR status131
DI-Connect-Metrics/TrainingHistory_*.jsonDaily training status and the phrase behind it131
DI-Connect-Metrics/MetricsMaxMetData_*.jsonVO2 max — rounded, and the raw value it came from26
DI-Connect-Fitness/*_summarizedActivities.jsonEvery activity, 97 fields each54
DI-Connect-Aggregator/UDSFile_*.jsonDaily rollup: body battery, stress, resting HR, steps68
DI-Connect-Wellness/*_sleepData.jsonNightly sleep stages and scores69
DI-Connect-Wellness/*_fitnessAgeData.jsonFitness age and the inputs behind it63
DI-Connect-Wellness/*_AbnormalHrEvents.jsonEvery high-heart-rate alert, with its threshold49
DI-Connect-Wellness/*_healthStatusData.jsonOvernight metric outliers42
DI-Connect-Wellness/*_bioMetrics_latest.jsonLactate threshold heart rate and pace, FTP1
DI-Connect-Uploaded-Files/UploadedFiles_0-_Part1.zipA nested zip of .fit files — see below1258
The `*` stands for a date range and your numeric user ID, which Garmin puts in most file names.

Two things to know about the naming. The date range in a file name is the range that file covers, so you can tell at a glance how far back each metric goes. And DI-Connect-Fitness files carry your email address in the name — including in the 1,258 file names inside the nested zip.

The .fit archive is a trap

UploadedFiles_0-_Part1.zip unpacks to 1,258 .fit files and 13.3 MB. I had recorded 54 activities in that period. So what are the other 1,204?

Every FIT file states its own type in its first record. Sorted by that:

Type in the fileFilesmeasuredWhat it is
activity54An actual workout
monitoring_b712All-day step, heart rate and intensity monitoring
44316Unnamed in the public FIT profile
4974Unnamed in the public FIT profile
6847Unnamed in the public FIT profile
7942Unnamed in the public FIT profile
4113Unnamed in the public FIT profile
All 1,258 files in my export, grouped by the type each one declares. Only the first row contains workouts.

The median file is 1.5 kB. Ninety-six per cent of the files are your watch quietly filing housekeeping records.

Now the part that costs people an afternoon. The file names look like this:

your.email@example.com_471118721667.fit

No date. No sport. No distance. And that number is not the activity ID. Activity IDs in summarizedActivities.json are eleven digits (24063976426); the file names carry a twelve-digit upload ID. I checked all 1,258 against all 54: not one matched. Guides that tell you to pair them up by ID are describing something that does not work.

The only reliable way in is to open each file and ask it what it is:

import fitdecode, glob, os, shutil

os.makedirs("workouts", exist_ok=True)

for path in glob.glob("*.fit"):
    with fitdecode.FitReader(path) as fit:
        for frame in fit:
            if frame.frame_type == fitdecode.FIT_FRAME_DATA and frame.name == "file_id":
                head = {f.name: f.value for f in frame.fields}
                break
    if head.get("type") != "activity":
        continue
    stamp = head["time_created"].strftime("%Y-%m-%d_%H%M")
    shutil.copy(path, f"workouts/{stamp}.fit")

pip install fitdecode, run it inside the unpacked folder, and you get 54 files named by the moment the watch started recording. From there the sport, the distance and everything else is one lookup away in summarizedActivities.json, matched on the start time.

What is in here that Connect will not show you

Four things I have actually used:

  • Training readiness, taken apart. The watch shows one score. TrainingReadinessDTO shows the six inputs separately — sleep score, sleep history, recovery time, HRV, stress history and acute load — each with its own percentage, every day. That turns “why is it 42 today” from a guess into a lookup.
  • VO2 max with decimals. The rounded number is in the same file as the raw value it came from, and the conversion is exact. I wrote that one up separately: Garmin says your VO2 max has no decimals.
  • Every race prediction you have ever had. Connect shows today’s. RunRacePredictions has all of them, one row per day, which is what let me plot what a new watch’s predictor does in its first two months.
  • Per-activity fields Connect hides. Each of the 97 fields per activity includes time in each of the seven heart rate zones, time in each of the six power zones, ground contact time, vertical ratio, grade-adjusted speed, normalised power, and your own RPE and feel entries. That is where the numbers behind my running power analysis came from.

What was empty in mine, and why that proves nothing

gear.json and trainingPlan.json both contained an empty list. I own no registered gear and follow no Garmin plan, so I cannot tell you whether Garmin exports those properly or not — only that an empty file is not automatically Garmin withholding something. The same caution applies to anything you expect and do not find: check whether you ever created it before concluding it was left out.

Before you upload this anywhere

There is a whole genre of posts telling you to drop this zip into a chatbot and ask it about your training. Look at what you would be handing over first.

customer_data/customer.json holds your full name, date of birth and email address. DI_CONNECT/DI-Connect-User/user_contact.json holds your phone number. Neither has anything to do with running.

Every training number worth analysing is in DI-Connect-Metrics/, DI-Connect-Fitness/ and DI-Connect-Wellness/. Send those folders and leave the rest on your own disk. It costs you one drag and a delete.

Sources

  • Garmin Connect web, Account Settings → Export Your Data — the request route
  • My own Garmin account export, requested 23 August 2026, covering 17 June to 23 August 2026: 40 files, 33 empty folders, 1,258 .fit files, 54 activities
  • The FIT file type of all 1,258 files read with fitdecode 0.11.0