Skip to content

tracijo32/withings-export

Repository files navigation

withings-export

Exports Withings measurements into monthly JSON partitions:

<out_dir>/year=YYYY/month=MM.json

The CLI entrypoint is withings_export.py.

Requirements

  • Python 3.10+ (recommended: 3.12)
  • A Withings developer application and OAuth tokens (provided via environment variables)

Configuration (environment variables)

The code is agnostic to how env vars are injected (dotenv file, CI secrets, Secret Manager, etc). It reads these environment variables:

  • WITHINGS_APP_CLIENT_ID
  • WITHINGS_APP_CLIENT_SECRET
  • WITHINGS_APP_REFRESH_TOKEN

Optional (will be refreshed/updated automatically if python-dotenv is installed, which it is by default here):

  • WITHINGS_APP_ACCESS_TOKEN
  • WITHINGS_APP_ACCESS_TOKEN_EXPIRES_AT (ISO8601)

Optional: load env vars (dotenv or Secret Manager)

By default, the app does not require .env and will just use whatever env vars are already present.

If you want the app to load env vars itself, set:

  • WITHINGS_ENV_SOURCE:
    • dotenv (load a dotenv file)
    • secret_manager (load a JSON mapping from Google Secret Manager)
  • WITHINGS_ENV_OVERRIDE: set to true to override existing env vars (default: false)

Dotenv loader:

  • WITHINGS_ENV_PATH: path to .env (defaults to ./.env if it exists)

Secret Manager loader (expects secret payload JSON object of {"ENV_NAME": "value", ...}):

  • WITHINGS_ENV_SECRET_RESOURCE: e.g. projects/<project>/secrets/<secret>

Persisting refreshed tokens (optional)

Withings refresh can rotate tokens. Persistence is configurable via:

  • WITHINGS_TOKEN_PERSIST:
    • auto (default): persist to dotenv if WITHINGS_ENV_PATH/env_path is set, otherwise no-op
    • dotenv: update the dotenv file
    • secret_manager: add a new Secret Manager version with updated tokens
    • noop: never persist

For Secret Manager persistence:

  • WITHINGS_TOKEN_SECRET_RESOURCE: e.g. projects/<project>/secrets/<secret>

Local run

Install deps:

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Run:

python withings_export.py --lookback-days 30 --out-dir withings_measurements

See all options:

python withings_export.py --help

Docker

Build

On macOS/Linux, building with your host UID/GID helps bind-mounted directories and .env stay writable:

docker build \
  --build-arg UID="$(id -u)" \
  --build-arg GID="$(id -g)" \
  -t withings-export .

Run (recommended)

This mounts:

  • ./.env/app/.env (so refreshed tokens can be persisted)
  • ./withings_measurements/data/withings_measurements (so exports persist)
mkdir -p withings_measurements
docker run --rm -it \
  -v "$PWD/.env:/app/.env" \
  -v "$PWD/withings_measurements:/data/withings_measurements" \
  -e WITHINGS_ENV_PATH=/app/.env \
  withings-export \
  --out-dir /data/withings_measurements \
  --lookback-days 30

Docker Compose

Default compose service mounts the same volumes and prints --help by default.

Run an export:

UID="$(id -u)" GID="$(id -g)" docker compose run --rm withings-export \
  --out-dir /data/withings_measurements \
  --lookback-days 30

Notes

  • Allowed date range: --start cannot be earlier than 2025-08-01 (enforced in withings_export.py).
  • Timezone handling: if you pass a naive datetime, --tz controls which timezone it’s interpreted in.
  • GCS output: --out-dir can be a gs://bucket/prefix URI. You must provide Google credentials (Application Default Credentials) in the container and have google-cloud-storage installed (it is included in requirements.txt).

Google Compute Engine + Secret Manager (container)

One workable pattern is:

  • Put your Withings env vars in Secret Manager as a JSON object mapping env var names to values.
  • Run the container with a service account that can access the secret.
  • Optionally, allow the container to persist rotated tokens by granting permission to add secret versions and setting WITHINGS_TOKEN_PERSIST=secret_manager.

Example secret payload

Store something like:

{
  "WITHINGS_APP_CLIENT_ID": "",
  "WITHINGS_APP_CLIENT_SECRET": "",
  "WITHINGS_APP_REFRESH_TOKEN": "",
  "WITHINGS_APP_ACCESS_TOKEN": "",
  "WITHINGS_APP_ACCESS_TOKEN_EXPIRES_AT": "2026-03-06T12:34:56+00:00"
}

Container env vars (load + persist)

Set these when running on GCE:

  • WITHINGS_ENV_SOURCE=secret_manager
  • WITHINGS_ENV_SECRET_RESOURCE=projects/<project>/secrets/<secret>
  • WITHINGS_TOKEN_PERSIST=secret_manager
  • WITHINGS_TOKEN_SECRET_RESOURCE=projects/<project>/secrets/<secret>

IAM permissions needed

If you only load from Secret Manager:

  • roles/secretmanager.secretAccessor

If you also persist rotated tokens back to Secret Manager:

  • roles/secretmanager.secretAccessor
  • roles/secretmanager.secretVersionAdder (or a broader Secret Manager role that can add versions)

About

Export weight data from my Withings smart scale using their API. Docker container available to run on Google Cloud as a daily task.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors