Unofficial Python client for the Hevy workout API (api.hevyapp.com)
Project description
hevy-unofficial
Unofficial Python client for the Hevy workout API (api.hevyapp.com).
Disclaimer: Not affiliated with Hevy. The API is undocumented and may change. Use at your own risk and respect Hevy's terms of service.
Install
pip install hevy-unofficial
playwright install chromium
Without browser automation (lighter install):
pip install 'hevy-unofficial[core]'
Development install from source:
pip install -e "packages/hevy[dev]"
# CI / headless dev without Playwright:
pip install -e "packages/hevy[dev,core]"
Quick start
Use tokens from a browser session or from POST /login (login requires reCAPTCHA on web):
from hevy_unofficial import HevyClient
with HevyClient(
access_token="YOUR_ACCESS_TOKEN",
refresh_token="YOUR_REFRESH_TOKEN",
) as client:
account = client.users.get_account()
print(account["username"])
routines = client.routines.list()
workouts = client.workouts.list_paged(username=account["username"], limit=10)
Environment variables (optional):
HEVY_BASE_URL— defaulthttps://api.hevyapp.comHEVY_API_KEY— defaultshelobs_hevy_web(web client key)HEVY_PLATFORM— defaultweb
Browser login
Opens hevy.com and reads the auth2.0-token cookie (login if needed):
from hevy_unofficial import CredentialStore, login_via_browser, prompt_client
store = CredentialStore()
tokens, email = login_via_browser(email="you@example.com", store=store)
# prompt_client tries browser login when Playwright + display are available
with prompt_client(store=store) as client:
...
On headless servers (CI, no DISPLAY), browser login is skipped automatically.
Set HEVY_FORCE_BROWSER=1 to override, or use_browser=False for manual tokens.
Credential cache
Tokens can be cached by email and updated automatically after refresh:
from hevy_unofficial import CredentialStore, prompt_client
store = CredentialStore() # ~/.config/hevy-unofficial/credentials.json
with prompt_client(store=store) as client:
...
On first run, browser login is attempted when available; otherwise you enter tokens. Later runs reuse the cache.
API surface
The client mirrors the web app's HTTP API:
| Attribute | Domain |
|---|---|
client.auth |
Login, signup, refresh, logout, passwords |
client.users |
Account, profile, preferences, API keys |
client.routines |
Routines, folders, sync batch, reorder |
client.workouts |
History, comments, likes, metrics, calendar |
client.exercises |
Built-in catalog (cached), custom templates, history |
client.social |
Feed, follow, followers |
client.coach |
Coach invites and trainer program |
client.billing |
Paddle / Stripe subscription helpers |
client.misc |
Webhooks, OAuth, uploads, feedback |
Exercise catalog
Built-in templates are extracted from hevy.com's _app-*.js bundle (not the REST API):
# Cached for 7 days in ~/.config/hevy-unofficial/exercise_catalog.json
exercises = client.exercises.list_catalog()
# Force ETag check / re-download if the bundle changed
exercises = client.exercises.list_catalog(refresh=True)
Offline extraction from a saved JS file:
client.exercises.parse_catalog_from_js("path/to/_app-xxx.js")
Routines example
# List all routines (sync)
data = client.routines.list()
# Create
created = client.routines.create({
"title": "Push Day",
"exercises": [],
"folder_id": None,
"index": 0,
"program_id": None,
"notes": None,
"coach_force_rpe_enabled": False,
})
routine_id = created["routineId"]
# Update
client.routines.update(routine_id, {
"title": "Push Day A",
"exercises": [...],
"folder_id": None,
"index": 0,
"program_id": None,
"notes": None,
"coach_force_rpe_enabled": False,
})
# Delete
client.routines.delete(routine_id)
Publishing to PyPI
Push a version tag (must match version in pyproject.toml):
git tag v0.1.0
git push origin v0.1.0
The pypi.yml workflow runs tests, publishes to PyPI, then deploys docs to
GitHub Pages (docs deploy only runs after PyPI succeeds). Configure PyPI trusted
publishing for workflow pypi.yml or set PYPI_API_TOKEN.
Manual upload:
cd packages/hevy
pip install build twine
python -m build
twine upload dist/*
Tests
cd packages/hevy
pytest
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hevy_unofficial-0.0.2a0.tar.gz.
File metadata
- Download URL: hevy_unofficial-0.0.2a0.tar.gz
- Upload date:
- Size: 17.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b60dc7fc1c69b282b36c2ef1c98392b8ddb1eccf77f9301f132d0af23a31112e
|
|
| MD5 |
e8abe3807aa7c21ffc4ec229b31e09c1
|
|
| BLAKE2b-256 |
9eb991a1d991c8a947f6f1cb79b8de6f12f6d3f1bcc99b7456117d058dee8128
|
Provenance
The following attestation bundles were made for hevy_unofficial-0.0.2a0.tar.gz:
Publisher:
pypi.yml on Sahil624/hevy-unofficial
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hevy_unofficial-0.0.2a0.tar.gz -
Subject digest:
b60dc7fc1c69b282b36c2ef1c98392b8ddb1eccf77f9301f132d0af23a31112e - Sigstore transparency entry: 1706499623
- Sigstore integration time:
-
Permalink:
Sahil624/hevy-unofficial@27192ee76738346710b9389e5047efcfb8720eca -
Branch / Tag:
refs/tags/v0.0.2-alpha - Owner: https://github.com/Sahil624
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@27192ee76738346710b9389e5047efcfb8720eca -
Trigger Event:
push
-
Statement type:
File details
Details for the file hevy_unofficial-0.0.2a0-py3-none-any.whl.
File metadata
- Download URL: hevy_unofficial-0.0.2a0-py3-none-any.whl
- Upload date:
- Size: 26.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ad74adf047afdf1d810fa45f4e48f847a8871e4f6fb123cab62215391b31c117
|
|
| MD5 |
7692e4db657e1eeb074376a38626a0cc
|
|
| BLAKE2b-256 |
a83e754991fd106209802bc69be351420b948e7ae56366a4b96809de31fae8a0
|
Provenance
The following attestation bundles were made for hevy_unofficial-0.0.2a0-py3-none-any.whl:
Publisher:
pypi.yml on Sahil624/hevy-unofficial
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hevy_unofficial-0.0.2a0-py3-none-any.whl -
Subject digest:
ad74adf047afdf1d810fa45f4e48f847a8871e4f6fb123cab62215391b31c117 - Sigstore transparency entry: 1706499664
- Sigstore integration time:
-
Permalink:
Sahil624/hevy-unofficial@27192ee76738346710b9389e5047efcfb8720eca -
Branch / Tag:
refs/tags/v0.0.2-alpha - Owner: https://github.com/Sahil624
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@27192ee76738346710b9389e5047efcfb8720eca -
Trigger Event:
push
-
Statement type: