Extract your own MyStrengthBook training data into a portable, offline spreadsheet. Free. Open source. Runs entirely on your machine.
I built this because after a year of powerlifting with every set, RPE, and coach comment logged into MyStrengthBook, the platform briefly went down and I realized I had no way to get my own data out. No export button. No download. If the servers disappeared, a year of training history would disappear with them.
So this is the fix. Not for MSB, for me, and for anyone else whose coach uses the same platform or one of the reskinned "Training App" variants built on top of it. It reads the pages your already-logged-in browser can already see, packages the full training log into a single local JSON file, and turns it into a spreadsheet that is yours to keep, analyze, back up, or walk away with.
It is free, open-source, runs entirely on your machine, and will never send your data anywhere.
— Matthias
- What it does
- Quick start
- What gets extracted
- Output sheets
- CLI reference
- Configuration
- Privacy
- Terms of service
- Installation
- Publishing your own fork
- Development
- Contributing
- License
+---------------------+ +----------------------+ +------------------------+
| Your browser tab, | | | | |
| logged in at | | msb_capture.json | | training_log.xlsx |
| app.mystrengthbook |----->| (one JSON blob: |----->| (Raw Log, weeks, |
| .com | | every set, every | | progress, charts) |
| | | full comment) | | |
+---------------------+ +----------------------+ +------------------------+
^ ^ ^
| | |
Paste scraper JS Python CLI parses it Open in Excel /
into DevTools (msb-extractor parse) Numbers / Sheets
- Capture. Paste
scraper/msb-scraper.jsinto your browser's DevTools console while logged in to MyStrengthBook. It fires a handful of parallel calls to MSB's own JSON API, grabs every training day in a 24-month window (sets, loads, RPEs, complete per-set comments) and saves onemsb_capture.jsonfile to your Downloads folder. End-to-end runtime: under one minute. - Parse. Run
python -m msb_extractor parse captures/msb_capture.json -o captures/training_log.xlsx. - Open. That's it. Open the xlsx in any spreadsheet app.
The spreadsheet includes a flat Raw Log you can pivot on, one Week YYYY-MM-DD sheet per training week in the format coaches and lifters actually use, a per-exercise Progress sheet, and line charts of your estimated 1RM over time for every major lift.
Total time: ~5 minutes, most of it in the browser. You only do this once.
This tool needs Python 3.11 or newer. Open a terminal and type:
python --version # Windows / most setups
python3 --version # macOS, Linux, or Windows Store PythonIf neither command prints a version ≥ 3.11, follow the OS-specific
install notes below. On Windows, the Microsoft Store install of Python
often only responds to python3; try both.
If you see Python 3.11.x or higher, you're good. If you see anything
else — "command not found", "Python was not found", or a version below
3.11 — install Python first:
- Windows: download from python.org/downloads. Tick the checkbox that says "Add Python to PATH" during install. (Alternative: install "Python 3.11" from the Microsoft Store.) Close and reopen your terminal afterwards, then re-check the version.
- macOS: the easiest path is Homebrew —
brew install python@3.11. Or download from python.org. - Linux:
sudo apt install python3.11 python3.11-venvon Debian/Ubuntu, or use your distro's package manager.
If python --version works but pip --version doesn't, your Python
install is broken — reinstall from python.org (make sure pip is
selected during install).
git clone https://github.com/m6bernha/msb-extractor.git
cd msb-extractorNo git? Download the repo as a ZIP from
the GitHub page (green
"Code" button → "Download ZIP"), unzip it, and cd into the unzipped
folder.
Install the package (creates a local Python environment and drops the CLI into it):
# create an isolated Python environment
python -m venv .venv
# Activate it. Pick the line that matches your shell; delete the '#':
source .venv/bin/activate # macOS / Linux
# .venv\Scripts\activate # Windows PowerShell / cmd
# source .venv/Scripts/activate # Windows Git Bash
# install the package (drops the msb-extractor and merge-captures
# commands into the active venv)
pip install -e .The tool is not on PyPI yet — installing from source is the current
path. If .venv\Scripts\activate fails on Windows PowerShell with
running scripts is disabled, see
troubleshooting.md.
- Open app.mystrengthbook.com in a regular browser window (Chrome, Edge, or Firefox — not Incognito, which has a separate cookie jar). Log in as normal.
- Press
F12to open DevTools. On Mac, useCmd+Option+I. - Click the Console tab across the top of the DevTools panel.
- If the console shows a red self-XSS warning, type the phrase it asks for and press Enter. That unlocks pasting for the rest of the session — it's a one-time browser safety check, not an error.
- Open
scraper/msb-scraper.jsin any editor, select all (Ctrl+A/Cmd+A), copy. - Click once in the console input area at the bottom of DevTools, paste, press Enter.
- A small dark widget appears in the top-right corner of the MSB page
showing
phase: token. The scraper is listening for MSB's next API call so it can grab your auth token off it. - Within 15 seconds of pasting, click a day on MSB's calendar (or navigate to a month you haven't viewed this session). This forces MSB to issue a fresh API call, which the scraper then snatches the token from.
- The widget advances to
phase: apiand counts up to 25 months. Typical runtime is 30-60 seconds end-to-end. (The count is 25 for a 24-month window because it includes the current, partially-complete month.) - Your browser downloads
msb_capture.jsonto its default download folder. On Windows that is usuallyC:\Users\<you>\Downloads; on macOS,~/Downloads; on Linux, whatever your browser is configured to use. - Move
msb_capture.jsoninto thecaptures/folder at the root of this repo. This folder ships with the repo (its contents are gitignored, so your data is never committed). Every command and helper script below assumes the capture lives atcaptures/msb_capture.json.
If step 8 times out (token_capture_timeout), reload the MSB page (F5),
re-paste the scraper, and click a calendar day within 15 seconds of pasting.
Full troubleshooting lives in scraper/README.md.
If your browser does not download anything, run window._msbDownload()
in the same DevTools console — this re-saves the capture the scraper
already has. If you ran the scraper more than a few seconds ago, paste
it again (the capture is cleared from the page as soon as the file
reaches disk).
Option A (easiest): use the one-click helper.
- Windows: double-click
run.batin the repo root. - macOS / Linux: in a terminal,
bash run.sh.
The helper creates the Python environment on first run, installs the
package, parses captures/msb_capture.json, and offers to open the
resulting captures/training_log.xlsx. Subsequent runs reuse the
environment and complete in under a second.
Option B: run the Python commands yourself.
From the repo root, with your venv activated:
# quick sanity check — prints a summary without writing any file
python -m msb_extractor info captures/msb_capture.json
# produce the xlsx
python -m msb_extractor parse captures/msb_capture.json -o captures/training_log.xlsxThe info command prints date range, training-day count, set count, and
which probe endpoints the scraper captured. The parse command writes the
xlsx and prints a summary like Parsed 192 training days, 2,484 sets total, across 28 exercises.
Open captures/training_log.xlsx in Excel, Numbers, LibreOffice, or
upload it to Google Sheets.
New to the layout? Read docs/reading-your-spreadsheet.md — it walks through each sheet (Summary, Raw Log, weekly blocks, Exercise Progress, e1RM Charts, Exercise Index) and suggests what to do with each.
- docs/faq.md — non-technical questions ("is this safe?", "do I need to code?", "can I use this on my coach's account?").
- docs/troubleshooting.md — concrete fixes for common errors.
- scraper/README.md — full browser-side reference.
For every training day in your account the parser pulls out:
- Date and day of week
- Exercise order (A, B, C, ...)
- Exercise name as configured in your program
- Prescribed: target sets, reps, RPE or percentage of 1RM, and computed load where the coach used a percentage
- Actual: the reps you performed, the RPE you logged, the load you lifted, MSB's computed %1RM and estimated 1RM
- Your comments on each set, in full. MyStrengthBook's page HTML only shows a ~40-character preview (older v3 scrapers had to click through every one to recover the full text). v4 reads MSB's JSON API directly, so the complete note — whether 5 characters or 900 — arrives in one shot with zero truncation workaround.
- Completion status per set (completed, partial, missed, prescribed only)
- Video-attachment metadata when you uploaded a lift video
A sample output is checked into docs/examples/demo_training_log.xlsx (synthetic data). Open it to see exactly what each sheet looks like.
| Sheet | Purpose |
|---|---|
| Raw Log | One row per set. 14 columns covering date, exercise, prescription, status, actual reps / RPE / load, %1RM, e1RM, your comment, and the data-source level. Rows from days that had full detail are shaded green. Filterable via the built-in autofilter. |
| Week YYYY-MM-DD (one per ISO week) | The hero sheet, modelled on the classic Jeff Nippard / Peace Era / PPL spreadsheet layout. Each day in the week is a block: Exercise / Sets / Reps / RPE / Set 1 / Set 2 / Set 3 / Set 4 / Set 5 / LSRPE / Notes. Reps that fell short of the prescription are annotated on the load cell ("70 kg x 5"). Comments are concatenated into the Notes column. |
| Exercise Progress | One row per (exercise, training day): top load, top reps, top RPE, best e1RM of the day, and the set count. The e1RM column is stored as a number with a unit-aware display format so charts and pivot tables can reference it directly. |
| e1RM Charts | A line chart of estimated 1RM over time for every exercise with five or more days of e1RM data. Two charts per row, sized for legibility. |
| Exercise Index | Every exercise in your history, ranked by total volume. Total sets, training days performed, first and last date seen. |
| Summary | Cover page with the extraction's generated-at timestamp, captured-at timestamp, date range, counts, and a legend explaining the row shading. |
Run these with your venv activated (see Step 1) or prefix them with
python -m msb_extractor/python -m tools.merge_captures. Acommand not found: msb-extractorerror almost always means the venv isn't active in the current terminal session — reactivate it.
msb-extractor parse INPUT.json [OPTIONS]
-o, --output PATH Output xlsx path. Defaults to <input>.xlsx
-u, --units TEXT Display unit, "kg" or "lbs". Default: kg.
-r, --rename-map PATH Optional YAML file mapping source exercise names
to preferred display names.
msb-extractor info INPUT.json
Prints a summary of a capture JSON without writing any files.
Useful for confirming you've captured what you think you've captured.
msb-extractor -V # or --version
msb-extractor --help
For stitching an initial capture together with follow-up gap-fill runs:
merge-captures a.json b.json -o merged.json
# or: python -m tools.merge_captures a.json b.json -o merged.json
Full usage: tools/merge_captures.py.
Loads are stored natively (kilograms in-model) and displayed in either unit
based on the --units flag. The e1RM charts axis label follows the same
choice.
MSB coaches write their own exercise names. If you want the spreadsheet to
use familiar names instead of the coach's verbatim labels, point
--rename-map rename.yaml at a file like:
# rename.yaml -- maps source names to display names.
# Keys with parentheses, colons, or other YAML metacharacters must be
# quoted. Plain ASCII keys like "Bench Press" do not need quotes.
"Competition (bench)": "Flat Barbell Bench Press"
"Competition (squat)": "Back Squat"
"Competition (deadlift)": "Conventional Deadlift"
"T2K (deadlift)": "2-Count Pause Deadlift"
"Close Grip Bench (bench)": "Close Grip Bench Press"Names not in the file pass through unchanged.
The scraper covers the last 24 months by default. To change the window
or the pacing, edit the CONFIG block near the top of
scraper/msb-scraper.js before pasting:
var CONFIG = {
startMonth: null, // 'YYYY-MM'; null => current month - 24
endMonth: null, // 'YYYY-MM'; null => current month
monthConcurrency: 5, // parallel API month fetches
monthDelayMs: 40,
retryCount: 2,
retryBackoffMs: 800,
requestTimeoutMs: 20000,
authToken: null, // set a JWT here to bypass auto-capture
tokenCaptureTimeoutMs: 15000,
tokenPokeIntervalMs: 1500, // how often to nudge MSB for a fresh API call
heartbeatMs: 10000,
showWidget: true,
downloadFilename: 'msb_capture.json',
partialFilename: 'msb_capture_partial.json'
};Full scraper docs (auth model, probe endpoints, troubleshooting failure modes) live in scraper/README.md.
- Nothing leaves your machine. The scraper only talks to
app.mystrengthbook.com, using your existing logged-in session cookies. The Python CLI runs locally. - No analytics, no telemetry, no accounts. The authors never see your data.
- No credentials handled. The tool never asks for your MSB password and never stores it. All it uses is the session cookie your browser already has.
- The captured JSON is yours. It sits on your disk, in a folder of your choosing. Delete it whenever you want.
See docs/privacy.md for a longer write-up including a data-flow diagram.
This tool is for extracting your own training data from your own MyStrengthBook account. Please read this section before using it.
- Not affiliated. This project is not produced by, endorsed by, or connected to MyStrengthBook, their coaching partners, or any reskinned white-label "Training App" built on their platform. All trademarks belong to their respective owners.
- Fair use of your data. The scraper pulls pages your logged-in browser can already see. You are not circumventing authentication, reverse engineering an API, or exfiltrating anyone else's data. That said, please read MyStrengthBook's current Terms of Service and use this tool only in ways that are consistent with them.
- Do not use this on accounts you do not own. Running the capture script against a friend's, client's, or family member's MSB account without their clear permission is not a use case this project supports.
- Coaches with many athletes: if you have a coach account with access to multiple athletes, treat their data as theirs, not yours. Get permission before extracting, and do not publish captures or spreadsheets that name other people's training data.
- Platform drift. MSB can change their API schema, authentication flow, endpoint paths, or HTML layout at any time and the scraper or parser may stop working without notice. There is no stability guarantee.
- No warranty. This software is provided "as is", without warranty of any kind. See LICENSE.
If you are a representative of MyStrengthBook and would prefer this tool not exist, open an issue and we will talk.
See docs/terms-of-use.md for the full text.
git clone https://github.com/m6bernha/msb-extractor.git
cd msb-extractor
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .Requires Python 3.11 or newer.
pip install -e ".[dev]"A PyPI release is planned once the probe-endpoint parsers land. Until then, install from source.
If you want to publish your own fork of this tool under your GitHub account:
# 1. Fork on github.com, then:
git clone https://github.com/YOUR-USERNAME/msb-extractor.git
cd msb-extractor
# 2. Update the project metadata in pyproject.toml and README.md to your
# name and URLs.
# 3. Push your first commit. CI runs automatically on push.There is no server-side component to run, so hosting amounts to sharing a git repo and (optionally) publishing to PyPI under your own account.
# Setup
python -m venv .venv
source .venv/bin/activate # on Windows: .venv\Scripts\activate
pip install -e ".[dev]"
# Tests
pytest
# Lint / format
ruff check .
ruff format .
# Type check
mypy
# Regenerate the example spreadsheet
python docs/examples/generate_demo.pySee docs/troubleshooting.md for known issues.
Bug reports, patches, and new exporter formats are welcome. See CONTRIBUTING.md for the dev workflow, commit message style, and how to run the test suite.
MIT — see LICENSE. Do whatever you want with this, but I bear no responsibility for what happens when you do.