Skip to content

Instantly share code, notes, and snippets.

@Luca-Pozzi
Created February 12, 2026 14:24
Show Gist options
  • Select an option

  • Save Luca-Pozzi/889b0ba890b328cb81be4b8650a8536e to your computer and use it in GitHub Desktop.

Select an option

Save Luca-Pozzi/889b0ba890b328cb81be4b8650a8536e to your computer and use it in GitHub Desktop.
Utility file to extract data from Garmin FIT files
import os
import csv
import tkinter.filedialog
import garmin_fit_sdk
import matplotlib.pyplot as plt
# Import one .fit file from filedialog
fpath = tkinter.filedialog.askopenfile(
mode='r',
filetypes=[('Garmin FIT files', '*.fit;*.FIT')]
).name
# Read data from .fit file
stream = garmin_fit_sdk.Stream.from_file(fpath)
decoder = garmin_fit_sdk.Decoder(stream)
messages, errors = decoder.read(
apply_scale_and_offset=True,
convert_datetimes_to_dates=True,
convert_types_to_strings=True,
enable_crc_check=True,
expand_sub_fields=True,
expand_components=True,
merge_heart_rates=True,
mesg_listener=None
)
# Extract HR and timestamp data
hr_list = []
t_list = []
for msg in messages['record_mesgs']:
if not 'heart_rate' in msg:
continue
hr_list.append(msg['heart_rate'])
t_list.append(msg['timestamp'].timestamp())
# Extract laps
lap_list = []
for msg in messages['lap_mesgs']:
lap_list.append(msg['start_time'].timestamp())
# Plot the data
plt.plot()
plt.plot(t_list, hr_list)
# Draw vertical lines corresponding to laps
y_min, y_max = plt.gca().get_ylim() # get current Y-axis limits
plt.vlines(lap_list, y_min, y_max, colors='r', linestyles='dashed')
# Set the axis labels
plt.xlabel("Time [s]")
plt.ylabel("HR [bpm]")
plt.title("Heart rate")
plt.show()
# Save HR data and laps to (separate) CSV files
fdir = os.path.dirname(fpath) # get name of directory where files are
fname = os.path.basename(fpath).split('.')[0] # get fname w/o extension
with open(os.path.join(fdir, f"{fname}_hr.csv"), 'w', newline='') as f:
csv_writer = csv.writer(f)
csv_writer.writerow(['HR [bpm]', 't [s]'])
csv_writer.writerows([[hr, t] for hr, t in zip(hr_list, t_list)])
with open(os.path.join(fdir, f"{fname}_lap.csv"), 'w', newline='') as f:
csv_writer = csv.writer(f)
csv_writer.writerow(['t [s]'])
csv_writer.writerows([[t] for t in lap_list])
@Luca-Pozzi
Copy link
Author

fit_reader.py

Extract data from Garmin FIT file, and save to CSV file.

In the current implementation, the script:

  1. loads a FIT file, selected via filedialog
  2. parses it to get HR data (if any) and laps (if any)
  3. plots the data for inspection
  4. saves data to CSV files (separately for HR and laps)

Tip

All data included in the FIT file can be extracted by tweaking the parsing stage (i.e., lines 27-39). Some knowledge about the structure of the FIT file format can be found in the Garmin FIT SDK documentation.

Requirements

Before running the script, install the required dependencies with

pip install garmin-fit-sdk
pip install matplotlib

Note

The matplotlib dependency can be omitted if the plotting stage is commented out from the code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment