Skip to main content

FIT Analysis Extractor

A command-line Python application that receives a .fit file and creates a folder named from the activity date/time and FIT filename:

YYYY-MM-DD_HH-MM-SS_<FIT filename stem>/

Example:

2026-07-19_08-17-35_Morning_Run/
├── full.json
└── analysis.json

The output deliberately contains only two JSON files:

  • full.json preserves every decoded FIT message for archival and future reprocessing.
  • analysis.json contains a compact, normalized structure for workout analysis.

The .fit (Flexible and Interoperable Data Transfer) file format was developed by Garmin and is primarily used to store and share health, fitness, and sports data—such as heart rate, GPS tracks, power, and cadence—recorded by smartwatches, cycling computers, and fitness applications. Garmin maintains the format and provides the official FIT SDK so developers can integrate decoding and encoding of .fit files into their own software. Because many other workout applications (such as Strava) also support the format, workout data downloaded from those services can be fed directly into this tool to extract data.

Requirements

  • Python 3.10 or newer
  • garmin-fit-sdk

Install the dependency:

python -m pip install -r requirements.txt

Basic usage

python fit_extractor.py Morning_Run.fit

By default, the output folder is created beside the FIT file.

Specify an output parent folder:

python fit_extractor.py Morning_Run.fit --output-root ./extracted

Specify the local timezone:

python fit_extractor.py Morning_Run.fit --timezone Europe/Budapest

Create a ZIP archive as well:

python fit_extractor.py Morning_Run.fit --zip

Replace an existing output folder:

python fit_extractor.py Morning_Run.fit --overwrite

Fail when the Garmin decoder reports any errors:

python fit_extractor.py Morning_Run.fit --strict

Disable CRC validation while decoding:

python fit_extractor.py Morning_Run.fit --no-crc

Install the project as a command:

python -m pip install .
fit-extract Morning_Run.fit

analysis.json

The top-level structure is always:

{
  "activity": {},
  "splits": [],
  "samples": [],
  "events": [],
  "context": {}
}

Activity

Contains normalized activity-level values:

  • source file name and sport
  • local start and end timestamps
  • distance, elapsed time, moving time, and explicit pause time
  • average pace
  • average and maximum heart rate
  • average and maximum power
  • minimum and maximum raw altitude
  • calculated elevation gain and loss, plus calculation metadata
  • calories and running strides

Elevation gain/loss is calculated from record altitude after:

  1. filling missing altitude values by interpolation;
  2. applying a centered 5-point median filter;
  3. applying a centered moving average.

The centered moving-average window defaults to 15 seconds and can be changed:

fit-extract Morning_Run.fit --elevation-smoothing-window 21

The activity object records the calculation settings, for example:

"elevation_calculation": {
  "source": "enhanced_altitude",
  "smoothing": "moving_average",
  "window_s": 15.0,
  "pre_filter": "median_5_samples"
}

For running activities, the FIT total_strides value is exposed as strides. It is not relabeled as steps.

Splits

Splits are generated from cumulative record distance, not from manual FIT laps. The default split length is 1,000 metres. Boundary times and values are interpolated at the exact distance crossing.

Each split contains:

  • start, end, and covered distance
  • duration and pace
  • average/maximum heart rate
  • average/maximum power
  • smoothed start/end altitude
  • ascent, descent, and net elevation change

The final split may be shorter than one kilometre.

Change split length:

fit-extract Morning_Run.fit --split-distance 500

Samples

The extractor merges FIT record messages that share a timestamp and interpolates sparse cumulative distance. analysis.json then contains regular time-based samples every 5 seconds by default. The precise activity endpoint is always appended, even when it does not fall on the sampling interval. It uses the final cumulative distance and the latest available value for any measurement omitted by a partial final FIT record.

Fields:

elapsed_time_s
distance_m
speed_m_s
heart_rate_bpm
power_w
altitude_m
latitude
longitude

Change the interval:

fit-extract Morning_Run.fit --sample-interval 10

Optionally include GPS accuracy:

fit-extract Morning_Run.fit --include-gps-accuracy

Events

FIT event and lap messages are normalized to:

start
stop
pause
resume
lap

Duplicate events are removed, manual markers are converted to lap, and a final stop is stored at the precise activity duration.

Adding context

Context does not normally exist in a FIT file. Supply it using a JSON file:

fit-extract Morning_Run.fit --context context.example.json

The file may contain the context object directly, as shown in context.example.json, or an object with a top-level context key.

The extractor derives hydration metrics as the required inputs become available:

  • body_mass_loss_pct needs weight_before_kg and weight_after_kg.
  • estimated_sweat_loss_l additionally needs fluid_during_ml.
  • sweat_rate_l_per_hour additionally needs a positive moving time.

Calculations:

body mass loss % = (weight before - weight after) / weight before × 100
estimated sweat loss L = weight loss kg + fluid during L - urine during L
sweat rate L/h = estimated sweat loss L / moving time hours

A missing urine value is treated as zero only when the other required hydration values are available.

Unknown context fields are rejected so misspellings do not silently enter the analysis schema.

full.json

full.json contains:

  • source filename, path, size, and SHA-256
  • extraction time, timezone resolution, CRC setting, and decoder errors
  • message counts
  • every decoded Garmin FIT SDK message under its original message-type key

No CSV aliases or duplicate singular/plural exports are generated.

Complete command help

fit-extract --help

Metadata

Release files for fit-analysis-extractor 2.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fit-analysis-extractor 2.1.0
File Size Uploaded Provenance Actions
fit_analysis_extractor-2.1.0.tar.gz 15.9 kB Without provenance Details for fit_analysis_extractor-2.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for fit-analysis-extractor 2.1.0
File Interpreter ABI Platform Actions
fit_analysis_extractor-2.1.0-py3-none-any.whl Python 3 none any Details for fit_analysis_extractor-2.1.0-py3-none-any.whl

Total release size: 32.2 kB

Release files / fit_analysis_extractor-2.1.0.tar.gz

Download URL fit_analysis_extractor-2.1.0.tar.gz
Size 15.9 kB
Tags Source
SHA-256 checksum
How to use checksums
b9e7a6c5db5dae7da88ec2c25dccdd551871d19f79605a2d3b3a8812c3e83c19
BLAKE2b-256 checksum
How to use checksums
1df8c061fca368f75d2cf23e79fee02e0aa6cc45f4f18ba03b01f09c57c080d1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.5

Release files / fit_analysis_extractor-2.1.0-py3-none-any.whl

Download URL fit_analysis_extractor-2.1.0-py3-none-any.whl
Size 16.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1ee70fc6a69a9381e6acc71f72e3d3a1728584c9aab78d04f69c045f44a6f6d6
BLAKE2b-256 checksum
How to use checksums
c88ace222ac0201ccb8466471a74853fcc4b53e793ac8df92c3ef832710b043a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.5

Security for fit-analysis-extractor 2.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

2.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page