Google Health API wrapper (formerly a Fitbit Web API wrapper)
⚠️ Breaking change in v2.0.0 Google is sunsetting the legacy Fitbit Web API in September 2026 and replacing it with the Google Health API. Starting from v2.0.0, this library talks only to the Google Health API. There is no backward compatibility with the old Fitbit Web API. If you still need the legacy implementation, pin your dependency tofitbitApp<2.0.0.
- Go to the Google Cloud Console and create a new project.
- Enable the Google Health API for that project.
- Configure the OAuth consent screen:
- Audience:
External(unless you have a Google Workspace organization) - Add yourself under Test users first to verify everything works.
- Once verified, click Publish app to switch the publishing status to In production.
This step matters: while a project is in
Testingstatus, issued refresh tokens expire after 7 days, which breaks any long-running / unattended setup. Apps for personal use (not shared, or used by fewer than 100 people you know) are exempt from Google's verification review, so you can safely publish without going through the full review process.
- Audience:
- Create an OAuth 2.0 Client ID (Application type: Web application). Add a redirect URI such as
http://localhost:8000. - Note down the Client ID and Client Secret.
{
"CLIENT_ID": "Your OAuth 2.0 Client ID",
"CLIENT_SECRET": "Your Client Secret"
}Save this as Config.json.
A helper script is provided at tools/get_google_token.py. Run it from a
machine that has a web browser available (the device running your long-lived script does not need to
have a browser itself):
python3 tools/get_google_token.pyThis opens the Google consent screen in your browser, and on completion writes the result to
Token.json next to the script. Copy Config.json and Token.json to wherever your script using this
library will run.
Make sure the OAuth consent screen is in production status (see 1.1) before running this script, otherwise the refresh token you obtain will expire in 7 days.
import json
import fitbitApp
import os
curdir = os.path.dirname(__file__) + "/"
with open(f"{curdir}Config.json") as f:
CONFIG = json.load(f)
with open(f"{curdir}Token.json") as f:
TOKEN = json.load(f)
app = fitbitApp.app(TOKEN["access_token"], TOKEN["refresh_token"], CONFIG["CLIENT_ID"], curdir)
# Identity: legacy Fitbit user ID + new Google Health user ID
print(app.get_identity())
# Profile / settings
print(app.get_profile())
print(app.get_settings())
# Convenience wrappers for the most common data types
print(app.Steps()) # today's steps (daily rollup)
print(app.HeartRateIntradayByDate()) # today's intraday heart rate
print(app.SleepLogByDate(date="2026-06-27")) # sleep ending on the given date
print(app.WeightLog()) # today's weight log (empty dict if no entry)
# Generic access to any of the 31 supported data types
print(app.list_data_points(
"steps",
filter_expr='steps.interval.civil_start_time >= "2026-06-01T00:00:00"',
))
print(app.daily_roll_up(
"weight",
start_date={"date": {"year": 2026, "month": 6, "day": 1}, "time": {}},
end_date={"date": {"year": 2026, "month": 6, "day": 1}, "time": {"hours": 23, "minutes": 59, "seconds": 59}},
))See the Google Health API data types reference for
the full list of supported data_type identifiers and which methods (list / reconcile / rollUp /
dailyRollUp) each one supports.
- Nutrition data is not available in the Google Health API at this time. If your application relied
on
FoodLog()/WaterLog()from the legacy v1.x implementation, there is currently no replacement. - Access tokens expire after 1 hour (down from Fitbit's 8 hours). The
oauth2class transparently refreshes on a401response, so this should not require any action on your part.
Integration tests live under tests/ and call the live Google Health API using your own credentials.
pip install -r requirements-dev.txt
cp Config.json Token.json tests/
pytest tests/ -vtests/Config.json and tests/Token.json are excluded via .gitignore and should never be committed.
- v2.1.1: Verified the convenience methods added in v2.1.0 against live data. 27 of 27
reachable methods worked correctly on the first try with zero filter-syntax bugs; 21 of
those returned real data, 6 returned an empty result (no data recorded for that type on the test
account). The remaining 6 methods (
HydrationLogByDate,NutritionLogByDate,ElectrocardiogramByDate,FoodList,FoodMeasurementUnitList,IrregularRhythmNotificationList) require thenutrition/ecg/irnOAuth scopes, which are optional and were not requested during testing — these scopes gate data types that most consumer fitness trackers (e.g. Fitbit Inspire 3) don't support hardware-wise, so they remain unverified by design rather than by bug. All other methods listed under v2.1.0 below are confirmed working. - v2.1.0: Added convenience wrapper methods for nearly all remaining Google Health API data
types (read-only: list/reconcile/rollUp/dailyRollUp — no create/update/delete). Methods for
steps,heart-rate,sleep,weight,body-fat,daily-heart-rate-variability,daily-resting-heart-rate,active-zone-minutes,calories-in-heart-rate-zone,height, andexercisehave been tested against real data. - v2.0.0: Full migration from the legacy Fitbit Web API to the Google Health API. Breaking change — no backward compatibility with v1.x.
- v1.1.0: Updated to support Fitbit Sleep API v1.2 and improved authentication logic.
- v1.0.0: Initial release with support for activity, heart rate, sleep, SpO2, weight, and other endpoints.
- Google Health API: https://developers.google.com/health
- Migration guide (Fitbit Web API → Google Health API): https://developers.google.com/health/migration
- Legacy Fitbit Web API reference (sunsetting Sept 2026): https://dev.fitbit.com/build/reference/web-api/