Catalog PyPI
PACKAGE EXPLORERView in registry

activity-parser

PyPI

Parser for loading FIT, TCX and GPX files into Pandas DataFrames.

fitfitnessgpsgpxpandasparsertcx
Versions collected1
Direct dependencies3From release 0.12.1
Last observed20 Oct, 18:37 UTC

README

Version 0.12.1 documentation

activity-parser

CI PyPI Python versions License

Parser for loading FIT, TCX and GPX activity files into Pandas DataFrames.

Provides a parser object for reading (optionally gzipped) FIT, TCX, and GPX activity files and converting them into Pandas DataFrames. During import, field names extracted from activity files are normalized into a canonical set of output column names with consistent units to allow for standardized downstream data processing.

Installation

pip install activity-parser

Usage

Create a new instance of the ActivityParser class to be reused for subsequent parsing of activity files:

import activity_parser

parser = activity_parser.ActivityParser()

Parse FIT, TCX and GPX files into normalized DataFrames:

from activity_parser import ParseError

try:
    records, laps, activity = parser.parse("path/to/fit_file.fit")
    records, laps, activity = parser.parse("path/to/gpx_file.gpx")
    records, laps, activity = parser.parse("path/to/tcx_file.tcx")
except ParseError as e:
    ...

Each file is assumed to contain a single activity. Multiple activities/tracks (chained FIT files, multi-activity TCX, multi-track GPX) have their records/laps merged into one set of results. In those cases, the returned Activity summary reflects only the first activity/session in the file.

parse() raises ParseError (FitError for FIT files, XmlError for TCX/GPX) when a file fails to parse. It raises ValueError for an unrecognized or ambiguous file type.

Output data

records and laps are each a DataFrame of normalized data, e.g.:

                           distance  speed  cadence  heart_rate
time
2026-01-05 08:00:00+00:00      0.00   36.0       80         100
2026-01-05 08:00:01+00:00      0.01   36.0       81         101

A few notes on column handling:

  • Column names and units are standardized across source formats for known field types.
  • Unknown fields are omitted by default; customize columns via record_columns, lap_columns, and include_all_columns on ActivityParser — see its docstring for details.
  • Not every column appears in every file: parse() only includes columns actually present.

Records

Not all fields are available in all source formats. Fields marked with (*) are exporter-dependent.

ColumnUnitFITTCXGPX
latitude, longitudedegreesYesYesYes
altitudemetersYesYesYes
distancekmYesYes(*)
speedkm/hYes(*)(*)
cadencerpmYesYes(*)
heart_ratebpmYesYes(*)
powerwattsYes(*)(*)
left_balance, right_balancepercentYes——
accumulated_powerwattsYes——
temperature°CYes—(*)
water_temperature°C——(*)
depthmeters——(*)
course, bearingdegrees——(*)

Laps

GPX files have no lap data, so laps is always an empty DataFrame for GPX. Fields marked with (*) are exporter-dependent.

ColumnUnitFITTCX
start_timetimestampYesYes
total_elapsed_timesecondsYesYes
total_timer_timesecondsYes—
start_position_lat, start_position_longdegreesYes—
end_position_lat, end_position_longdegreesYes—
total_distancekmYesYes
total_ascent, total_descentmetersYes—
avg_vamm/sYes—
avg_speedkm/hYes(*)
max_speedkm/hYesYes
avg_cadencerpmYesYes
max_cadencerpmYes(*)
total_strokescountYes—
stepscount—(*)
avg_heart_rate, max_heart_ratebpmYesYes
time_in_hr_zonesecondsYes—
avg_power, max_powerwattsYes(*)
normalized_powerwattsYes—
left_balance, right_balancepercentYes—
time_in_power_zonesecondsYes—
total_workjoulesYes—
avg_temperature, max_temperature°CYes—
total_calorieskcalYesYes
total_fat_calorieskcalYes—

Activity

activity is an Activity dataclass instance: a small file-level summary.

FieldUnitFITTCXGPX
sport—YesYes [1]Yes [1]
start_time—YesYesYes [2]
total_elapsed_timesecondsYesYesYes
total_timer_timesecondsYes——
total_distancekmYesYesYes
total_ascent, total_descentmYes——
total_calorieskcalYesYes—
avg_heart_rate, max_heart_ratebpmYesYesYes
avg_power, max_powerWYesYesYes
avg_cadence, max_cadencerpmYesYesYes
avg_speed, max_speedkm/hYesYes [3]Yes [3]
creator—YesYesYes
notes——YesYes

Fields are None when the source format/file doesn't record them. Many TCX/GPX fields are computed from record and lap data since they are not provided as activity-level summary fields by the file format.

Notes:

  1. TCX/GPX sport is normalized onto FIT's sport vocabulary; an unrecognized value is passed through unchanged.
  2. GPX start_time comes from metadata/time, which is technically the file's export time rather than the activity's start.
  3. TCX/GPX avg_speed divides by elapsed time, whereas FIT divides by timer time.

Examples

examples/ has runnable scripts for processing a directory of activity files, built on a shared parse_directory() helper:

  • check_archive.py <directory> [--all-columns] — a health check, broken down by file type: parsing failures, record column coverage, and file creators.
  • summarize_archive.py <directory> — a per-sport summary rollup, displaying key metrics across the archive.

Parser notes

FIT files

FIT parsing wraps garmin-fit-sdk, Garmin's official SDK, which decodes against the public FIT SDK profile.

parse() transforms certain FIT fields beyond decoding:

  • Positions are converted to degrees, distances to km, and speeds to km/h. Vertical rates (avg_vam, vertical_speed, and similar) stay in m/s.
  • For fields with lower- and higher-precision versions, only the higher-precision value is returned, under the base field's name.
  • For fields with sub-integer precision in a separate field, the precision is added into the base field.
  • left_right_balance (a bit-packed field) is decoded into left_balance/right_balance.
  • heart_rate is merged with a higher-rate hr stream when the file has one. Records outside its coverage keep their own device value.

Messages/fields that can't be resolved against the FIT profile (e.g. proprietary extensions) are kept as raw values under unknown_<n> names. Developer fields are resolved to their file-embedded names and flattened into ordinary columns alongside built-in fields.

parse_fit and parse_fit_raw are the lower-level functions ActivityParser.parse() wraps for FIT files. parse_fit returns the same canonical (records, laps, activity) shape, but without column curation. parse_fit_raw returns every message type in the file as its own uncurated DataFrame, in FIT-native units (semicircles, meters, m/s).

TCX & GPX files

TCX and GPX files are parsed natively in this package using lxml. Recognized elements and attributes are mapped onto the same canonical column names as FIT, with the same unit conventions.

The parser supports the following schema versions and extensions:

FormatSchema versionExtensions
TCXv2Garmin ActivityExtension v2
GPX1.0 / 1.1Garmin TrackPointExtension v1/v2, Cluetrust gpxdata

Unrecognized elements and attributes are exported as string columns named with their XML namespace in Clark notation.

parse_gpx and parse_tcx are the lower-level functions ActivityParser.parse() wraps for these formats. They return the same canonical (records, laps, activity) shape, but without column curation.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
0.12.13 Oct 20263

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

PENDING
tabishm52/activity_parser

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 18:37 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:f3fc0aae66ec44e0f6348a319cef3bebd6cc0b01baee28a3aab48deb784cbaa4