Skip to main content

ha-garmin

Python client for Garmin Connect API, designed for Home Assistant integration.

Features

  • Native Garmin Connect API integration
  • Robust authentication with multiple login strategies and automatic fallbacks
  • MFA support with automatic endpoint fallback
  • Token persistence - save and restore sessions to avoid re-login
  • Automatic token refresh - proactively refreshes before expiry
  • Retry with backoff for rate limits (429) and server errors (5xx)
  • Midnight fallback - automatically uses yesterday's data when today isn't ready yet
  • Coordinator-based fetch - optimized data fetching for Home Assistant multi-coordinator pattern
  • Data transformations - automatic unit conversions (seconds→minutes, grams→kg)

Installation

pip install ha-garmin

Optional: install with improved browser UA generation:

pip install ha-garmin[ua]

Usage

Standalone script

Authentication is synchronous; data fetches run in a thread pool and are awaited.

import asyncio
from datetime import date
from ha_garmin import GarminAuth, GarminClient, GarminMFARequired

# Auth is synchronous
auth = GarminAuth()

if not auth.load_session(".garmin_tokens.json"):
    try:
        auth.login("email@example.com", "password")
    except GarminMFARequired:
        mfa_code = input("Enter MFA code: ")
        auth.complete_mfa(mfa_code)
    auth.save_session(".garmin_tokens.json")

# timezone: fallback zone for "today" until the Garmin account's own UTC
# offset is learned from the first daily summary (defaults to the system zone).
client = GarminClient(auth, timezone="Europe/Amsterdam")


async def fetch_all():
    today = client.today()  # Garmin calendar date, independent of the process zone
    core_data     = await client.fetch_core_data(today)      # Steps, HR, sleep, stress
    body_data     = await client.fetch_body_data(today)      # Weight, body composition, fitness age
    activity_data = await client.fetch_activity_data(today)  # Activities, workouts, training calendar
    training_data = await client.fetch_training_data(today)  # HRV, training status
    goals_data    = await client.fetch_goals_data()          # Goals, badges
    gear_data     = await client.fetch_gear_data()           # Gear, alarms, solar, devices


asyncio.run(fetch_all())

Home Assistant integration

Set up auth during async_setup_entry and pass the client to your coordinators.

from datetime import date, timedelta
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from ha_garmin import GarminAuth, GarminClient

async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    auth = GarminAuth()

    token_path = hass.config.path(".storage/garmin_tokens.json")
    if not auth.load_session(token_path):
        # Initial login must have been completed via the config flow
        raise ConfigEntryAuthFailed("No valid Garmin session")

    client = GarminClient(auth)

    coordinator = GarminCoreCoordinator(hass, client)
    await coordinator.async_config_entry_first_refresh()

    hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator
    return True


class GarminCoreCoordinator(DataUpdateCoordinator):
    def __init__(self, hass: HomeAssistant, client: GarminClient) -> None:
        super().__init__(hass, logger=_LOGGER, name="Garmin core", update_interval=timedelta(minutes=15))
        self._client = client

    async def _async_update_data(self) -> dict:
        return await self._client.fetch_core_data(date.today())

Coordinator Fetch Methods

Optimized methods that group related API calls for Home Assistant coordinators:

Method API Calls Data Returned
fetch_core_data() 3 Steps, distance, calories, HR, stress, sleep, skin temperature change, body battery, SPO2
fetch_body_data() 3 Weight, BMI, body fat, hydration, fitness age
fetch_activity_data() 6+ Activities, workouts, HR zones, polylines, training calendar (scheduled workouts, plan goal event or calendar race)
fetch_training_data() 8+ Training readiness, status, VO2 Max, HRV, lactate, endurance/hill scores, power-to-weight
fetch_goals_data() 4 Goals (active/future/history), badges, user level
fetch_gear_data() 6+ Gear items, stats, device alarms, solar intensity (daily avg + gain), devices, last sync, paired sensors
fetch_blood_pressure_data() 1 Blood pressure measurements
fetch_menstrual_data() 2 Menstrual cycle data
fetch_nutrition_data() 1 Nutrition log: consumed macros, goals, per-meal breakdown

Write / Action Methods

Methods for logging data back to Garmin Connect, suitable for Home Assistant services:

Method Description
add_nutrition_log(calories, carbs, protein, fat, name) Log a Quick Add nutrition entry (requires Connect+)
set_hydration(value_in_ml) Log hydration intake
set_blood_pressure(systolic, diastolic, pulse) Log a blood pressure measurement
add_body_composition(weight, percent_fat, ...) Log weight / body composition via FIT upload
create_activity(name, type, start, duration_min) Create a manual activity
upload_activity(file_path) Upload a FIT / GPX / TCX file
set_active_gear(activity_type, setting, gear_uuid) Set default gear for an activity type
add_gear_to_activity(gear_uuid, activity_id) Associate gear with an activity

Nutrition logging

Requires a Garmin Connect+ subscription and initial setup through the Garmin Connect app (the app creates the meal slots that the API needs).

await client.add_nutrition_log(
    calories=500,
    carbs=60,       # optional, grams
    protein=30,     # optional, grams
    fat=15,         # optional, grams
    name="Lunch",   # optional label
)

The method automatically fetches the correct meal slot ID and time for the day. If no meal slots are configured yet, open the Garmin Connect app and set up your nutrition plan first.

Individual API Methods

Method Description
get_user_profile() User profile info
get_user_settings() Profile settings (userData, incl. VO2 Max running/cycling)
get_daily_steps() Steps for date range
get_body_composition() Weight, BMI, body fat
get_fitness_age() Fitness age metrics
get_hydration_data() Daily hydration
get_activities() Most recent activities (newest first, no date filter)
get_activity(activity_id) Single activity summary (includes e-bike fields)
get_activity_details() Detailed activity with polyline
get_activity_connect_iq_display_info() Field definitions of the Connect IQ apps used in an activity; values are in get_activity()['connectIQMeasurements'], joined by fetch_activity_data() into lastActivity['connectIQFields']
get_activity_hr_in_timezones() HR time in zones
download_activity(activity_id, file_format) Download activity file (fit/original/tcx/gpx/kml/csv)
get_workouts() Workout library (created/saved workouts, not when scheduled)
get_scheduled_workouts(year, month) Training calendar for a month: self-scheduled + Garmin Coach / adaptive-plan workouts
get_training_readiness() Training readiness score
get_training_status() Training status
get_morning_training_readiness() Morning readiness
get_endurance_score() Endurance score
get_hill_score() Hill score
get_lactate_threshold() Lactate threshold
get_power_to_weight(target_date) FTP / power-to-weight data
get_goals() User goals by status
get_earned_badges() Earned badges
get_gear() User gear items
get_gear_stats() Gear statistics
get_gear_defaults() Default gear settings
get_devices() Connected devices
get_sensors() Paired ANT+/BLE sensors and battery status
get_device_alarms() Device alarms
get_device_solar_data() Solar intensity data per device
get_device_last_used() Last used device and last sync time
get_device_settings() Device settings
get_blood_pressure() Blood pressure data
get_menstrual_data() Menstrual cycle data
get_menstrual_calendar() Menstrual calendar
get_nutrition_log() Daily nutrition log (Connect+)

Data Transformations

The library automatically adds computed fields for convenience:

  • Time conversions: sleepTimeSeconds → sleepTimeMinutes
  • Activity time: highlyActiveSeconds → highlyActiveMinutes
  • Weight: weight (grams) → weightKg
  • Stress: stressQualifier → stressQualifierText (capitalized)
  • Nested flattening: HRV status, training readiness, scores
  • VO2 Max: training status (running, else cycling), then profile settings, then recent activities
  • Training plan goal: the plan's goal event, else the upcoming (primary) race on your calendar
  • Skin temperature: avgSkinTempDeviationC is the nightly change from your baseline, not an absolute temperature
  • Sanity checks: a metabolicAge that can't be an age in years is returned as None

License

MIT

Metadata

Release files for ha-garmin 0.1.50

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

Source distribution (sdist)

Source distribution for ha-garmin 0.1.50
File Size Uploaded Provenance
ha_garmin-0.1.50.tar.gz 89.8 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for ha-garmin 0.1.50
File Interpreter ABI Platform
ha_garmin-0.1.50-py3-none-any.whl Python 3 none any Details

Total release size: 150.1 kB

Release files / ha_garmin-0.1.50.tar.gz

Download URL ha_garmin-0.1.50.tar.gz
Size 89.8 kB
Tags Source
SHA-256 checksum
How to use checksums
6ff66a0f0e534160d58bb1aa9bb221dffa4b7c46496555c2d051af4bc08c472d
BLAKE2b-256 checksum
How to use checksums
8de44699eda17dca3632689379a3648d6a738f96fa51c216ae7e0e60f6921ced
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.5

Release files / ha_garmin-0.1.50-py3-none-any.whl

Download URL ha_garmin-0.1.50-py3-none-any.whl
Size 60.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
711050a7635a650bc30863c213ce1d15e782ea19243726fcabd3a677989c63f8
BLAKE2b-256 checksum
How to use checksums
788ded5a068cb06c073e98ba8ddc19997ab3e208cd6be9431e583178d30915ae
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.5

Security for ha-garmin 0.1.50

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.

Release history Release notifications | RSS feed

This release

0.1.50 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