Article

July 28, 2026 | 5 min read

ZwiftPower Profile Check with Python

Use a ZwiftPower profile check script to check Zwift IDs, categories, race counts, zFTP, and Zwift Racing Score from a CSV file.

ZwiftPower Profile Check with Python

I built a small ZwiftPower profile check script because I wanted a practical way to check multiple Zwift riders without opening every ZwiftPower profile manually.

The idea is simple: put a list of Zwift IDs in a CSV file, run the Python script, and get a new CSV file back with the rider category, number of races, zFTP, and Zwift Racing Score.

This is not a replacement for ZwiftPower. It is just a helper script for personal analysis when you already have a list of Zwift IDs you want to check.

You can find the script on GitHub here: erwinbierens/ZwiftPower-Profile-Check.

Why this matters

If you manage events, teams, club rides, or race checks, you sometimes need to validate a list of riders.

Doing that manually works for a few riders. It becomes annoying when the list gets longer.

The script helps with that by automating the boring part:

  • log in to ZwiftPower
  • open each profile by Zwift ID
  • read the useful profile fields
  • write the results back to a CSV file

That gives you a simple file you can filter, sort, or compare in Excel.

How the ZwiftPower profile check works

The script is written in Python and uses a few common libraries:

  • requests for the web requests
  • BeautifulSoup for reading the HTML
  • python-dotenv for loading credentials from a .env file
  • csv for reading and writing the rider list

The input file is called zwift_ids.csv.

It expects this structure:

Email,FirstName,LastName,Country,ZwiftID
piet@example.com,Piet,Jansen,NL,123456
klaas@example.com,Klaas,Visser,BE,654321

The script then creates an output file called zwiftpower_check.csv.

The output contains the original columns plus:

  • Category
  • Races
  • zFTP
  • ZwiftRacingScore

That makes the result easy to use in Excel, Power BI, or any other reporting tool.

Step-by-step setup

Start by placing the script files in a local folder.

You can download or clone the project from GitHub:

git clone https://github.com/erwinbierens/ZwiftPower-Profile-Check.git
cd ZwiftPower-Profile-Check

Create a Python virtual environment:

python3 -m venv venv
source venv/bin/activate

Install the requirements:

python3 -m pip install -r requirements.txt

Create a .env file in the same folder as the script:

ZWIFT_USER=your_email@example.com
ZWIFT_PASS=your_password

Then create the input file:

Email,FirstName,LastName,Country,ZwiftID
piet@example.com,Piet,Jansen,NL,123456
klaas@example.com,Klaas,Visser,BE,654321

Run the script:

python3 ZwiftPower.py

When it finishes, open zwiftpower_check.csv and review the results.

Practical example

For me, the useful part is not just checking one rider. It is checking a batch.

For example, if you have a list of riders from an event registration, you can add their Zwift IDs to the input CSV and let the script enrich the file with ZwiftPower data.

The result could look like this:

Email,FirstName,LastName,Country,ZwiftID,Category,Races,zFTP,ZwiftRacingScore
piet@example.com,Piet,Jansen,NL,123456,B,45,3.6,482
klaas@example.com,Klaas,Visser,BE,654321,C,12,2.9,321

From there, you can quickly spot missing profiles, unexpected categories, or riders with very little race history.

One useful part of the script is the cookie cache.

After a successful login, the script stores session cookies in cookies.pkl. On the next run, it tries to reuse that session instead of logging in again immediately.

The cache expires after four hours.

That keeps the script a bit more practical when you need to run it multiple times while cleaning up a CSV file.

Tips and common mistakes

Keep your .env file private. It contains your Zwift login details, so do not commit it to GitHub.

Use the script carefully. ZwiftPower is not an API in this case. The script reads HTML from profile pages, which means it can break if the ZwiftPower page layout changes.

Do not remove the delay between requests unless you know exactly what you are doing. The script waits two seconds between profile checks to avoid hammering the site.

Check the output manually before you rely on it. This is especially important when a profile is private, missing, or when ZwiftPower changes something in the login flow.

Also, this should be used for personal analysis only. Respect the Zwift and ZwiftPower terms and do not use this for commercial scraping.

Practical notes

There are a few things to keep in mind when you use this script more often:

  • keep the input CSV clean and make sure every row has a Zwift ID
  • review failed or empty results manually before making decisions
  • keep the request delay in place so you do not overload the website
  • keep your .env file private and never publish your credentials
  • rerun the script if your ZwiftPower session expires during testing

That keeps the workflow simple and avoids most issues you normally run into with this kind of automation.

End note

This ZwiftPower profile check script is a good example of a practical automation: small, focused, and useful when you need to repeat the same manual check many times.

It is not perfect, and it depends on the ZwiftPower website structure staying the same. But for personal batch checks, it saves time and gives you a clean CSV file to work with.

Suggested internal links to add before publishing:

  • a Python automation article
  • a CSV or Excel reporting article
  • a practical automation or scripting article

Try it in your own lab, and always validate the results before using them for decisions.

Ads appear here only after advertising consent.