Introduction
This book explains why OpenStreetlifting exists, and what you need to know to use the archive or to contribute to it.
OpenStreetlifting is an open, collaborative project building a permanent and traceable archive of all Streetlifting data, freely accessible to everyone.
Important concepts in this project:
- open: the data and the code are both open source.
- collaborative: open source means working together, so do not hesitate to reach out if you want to help.
- permanent: the archive is meant to be downloaded and kept for as long as possible, as common knowledge.
- traceable: data that is displayed or exported keeps its original source wherever it can.
- freely: the project costs nothing to use and carries no advertising
I will refuse any advertising or partnership that would harm the very nature of the project.
Page references
- Contributing Data: adding a competition, correcting one that is already published.
- Data Reference: how do we store competition results.
- Data Access: public API and bulk download.
- Licensing
How to help
If you have results from a competition that is not in the archive yet, you can open a pull request on Github, see: Contributing Data. You can also contact me, see: contact page
Acknowledgments
This project is heavily inspired by the OpenPowerlifting project.
Contributing Data
If you know Git, you can add or correct the archive’s files and open a pull request on GitHub. Otherwise, send me the results through the contact page.
Before you start
What counts as a source
A federation PDF, a scoresheet photo, a competition livestream or a public Instagram post can all be useful. The source should identify the competition and let us check the results. Prefer official results from the organizer when available.
Check the competition is not already there
Search the competition archive by name, federation or year. Check the date and location too, as the name may differ. If you find the competition, you can help by correcting mistakes or adding missing results.
Adding a competition
Each competition has a folder under
backend/data/competitions/{federation}/{year}/{slug}/. A slug is a short name
used to identify the competition, such as worlds-2023.
The folder contains two files:
competition.toml: the competition’s name, dates, location and source links.entries.csv: the athletes and their results.
For example, the FinalRep Worlds 2023 folder on GitHub contains both files. Open them to see how a competition is stored.
Use an existing competition as an example, replacing its details and results with your own. Check the project files for an existing entry before creating a new folder. The Data Reference explains how to fill in each file.
Validate it locally
If you have downloaded the repository and have Rust and Cargo installed, open a
terminal in the backend folder and run:
SQLX_OFFLINE=true cargo run -p osl_importer --bin import -- prepare data/competitions/<federation>/<year>/<slug>
SQLX_OFFLINE=true cargo run -p osl_importer --bin import -- competitions --dry-run
Replace the preparation path with your competition. Preparation fills totals from complete lift results and formats its files; the dry run checks the archive without writing to the database. The summary should show zero failures. Review any warnings and compare your entries with the source as well. If you cannot run this check, mention it in your pull request so we can help.
Open a pull request
Open a pull request in the project repository.
Give your pull request a clear title, such as Add FinalRep Worlds 2023 results.
Include the source link, a short description of your changes and anything you
are unsure about. Mention whether you ran the validation check.
Correcting results that are already published
You can report a mistake through the contact page. Include a link to the competition or athlete, explain what should change and share a supporting source.
To make the correction yourself, edit the competition’s existing files and open a pull request as described above.
Review checklist
Before submitting files, check that:
- You are adding a new competition or updating the existing entry.
- The results match your sources, and
competition.tomlincludes their references. - You have pointed out missing details, athletes who share a name, or unusual weight classes.
- Separate divisions remain separate if a weight class was contested more than once.
- Mixed contests use
CategorySex=MX, each athlete hasSex=MorSex=F, andcompetition.scoringmatches the source’s ranking method. - RIS contests with fewer than four lifts declare their actual event, have no
weight classes anywhere in the competition, and use the source’s
ReportedRis. Follow the shorter-event RIS rules. - You have explained any validation errors or warnings you need help with.
Getting help
If you get stuck, email [email protected] or open a GitHub issue with your question and source. You do not need to prepare the files before asking for help. Sharing results is already a contribution.
Data Reference
OpenStreetlifting stores each competition in two files: competition.toml for
its details and entries.csv for its results. This page explains what to put in
each file. For the steps to submit them, see Contributing Data.
You can browse a real example in the FinalRep Worlds 2023 folder on GitHub.
Competition Location
backend/data/competitions/{federation}/{year}/{slug}/
├── competition.toml
└── entries.csv
Use the federation name in lowercase with hyphens, the year the competition
started and a unique competition name such as worlds-2023. This last part, the
slug, also identifies the competition on the website. Keep it unchanged when
correcting results.
competition.toml
This file describes the competition metadata
For example:
event = "MPDS"
sources = ["https://final-rep.com/world-championship/"]
[competition]
name = "Worlds"
start_date = "2023-09-30"
end_date = "2023-10-01"
city = "Cologne"
country = "DE"
status = "completed"
[federation]
name = "FinalRep"
Competition and federation details
| Field | What to enter |
|---|---|
competition.name | The competition’s name. |
competition.start_date | The first day, as YYYY-MM-DD. |
competition.end_date | The last day; defaults to start_date when omitted. |
competition.venue | The venue name, if known; omit it when unknown. |
competition.city | The city, if known. |
competition.region | The region or state, if known. |
competition.country | An ISO 3166-1 alpha-2 country code, such as FR or DE. |
competition.scoring | total or ris; required for mixed contests. |
competition.status | See Status below. |
federation.name | The federation’s name, written consistently across competitions. |
federation.abbreviation | Its abbreviation, if used. |
federation.country | Its ISO 3166-1 alpha-2 country code, if applicable. |
The names, start date and competition country are required. Omit end_date for
a one-day competition. prepare removes an end date equal to the start date;
it preserves a later end date. Optional fields can be left out.
Event
OpenStreetLifting covers streetlifting competitions combining muscle-up,
pull-up, dips and squat. The main formats are MPDS, sometimes called All4,
and PD, sometimes called Classic. event lists the contested movements
using these letters in this order:
| Letter | Movement |
|---|---|
M | Muscle-up |
P | Pull-up |
D | Dips |
S | Squat |
Use MPDS for all four movements or PD for pull-up and dips. Other
combinations of these four lifts, such as PDS, use the same letter order.
Include event whenever you add results.
Status
upcoming: a planned competition without results. Add onlycompetition.toml.live: a competition in progress with partial results. Includeentries.csvandevent, and add only published results. Change tocompletedwhen final results are available. The API useslive; the website displays “In Progress”.completed: a competition with final results. Includeentries.csvand setevent.
Sources
Include at least one source link, archived file path, or description in sources,
above [competition], for both announcements and results. Identify the original
publication or document so someone else can check it. Empty lists and blank
references are rejected. Include every source used to compile the results.
entries.csv
Each row records one athlete’s results in one contest. Keep the column names
exactly as shown below. Use kilograms for weights and a decimal point for
fractions, such as 72.5.
Use this standard base header when starting a file:
Sex,FirstName,LastName,Disambiguation,Country,BodyweightKg,ReportedRis,TotalKg,Status,StatusReason,MuscleUp1Kg,MuscleUp2Kg,MuscleUp3Kg,BestMuscleUpKg,PullUp1Kg,PullUp2Kg,PullUp3Kg,BestPullUpKg,Dips1Kg,Dips2Kg,Dips3Kg,BestDipsKg,Squat1Kg,Squat2Kg,Squat3Kg,BestSquatKg
Add WeightClassKg after Sex for competitions with weight classes, and
Division first when separate divisions are needed. NativeName,
CategorySex, BodyweightSource and ReportedRisEdition are optional
additional columns.
The parser also accepts files without FirstName, Disambiguation or
StatusReason: an omitted column means an empty value for every entry. prepare
always restores these three columns in the standard base header, so formatted
files provide a consistent starting point for contributors. It preserves any
values already supplied. It fills an empty TotalKg only when every event
movement has a successful best lift.
All other base headers, including TotalKg, are required even when their cells
may be empty. Keep
the columns for all four movements, leaving cells empty for movements outside
the event. Unknown or misspelled headers are rejected.
Athlete and result columns
| Column | What to enter |
|---|---|
Sex | The athlete’s sex: M or F. MX is not an athlete sex. |
WeightClassKg | The weight class, such as 80 or 101+. Leave it out for a meet with none. |
FirstName | The athlete’s first name. Leave empty for a single name. |
LastName | The surname, or the full name for an athlete known by a single name. Required. |
Disambiguation | Leave empty unless different athletes share a name; see Names. |
Country | The athlete’s ISO 3166-1 alpha-2 country code, if the source gives it. |
BodyweightKg | The athlete’s bodyweight, if known. |
ReportedRis | The source’s published RIS score, whether or not bodyweight is known. |
TotalKg | Overall total from the source, or filled by prepare from a complete breakdown. |
Status | competed, disqualified or no_show. Empty means competed. |
StatusReason | A short explanation for disqualified or no_show. Leave empty for competed. |
Athlete sex and mixed contests
Sex identifies the athlete and selects their RIS formula. Add the optional
CategorySex column only when needed: MX places that row in a mixed contest.
An empty cell or omitted column uses the athlete’s Sex. An explicit M or F
must match Sex. Moving between mixed and single-sex contests keeps the same
athlete profile.
For mixed contests, set the ranking metric under [competition]:
scoring = "ris"
total: rank byTotalKg.ris: rank by RIS. All4 uses each athlete’s own formula when its inputs are available. Shorter events use published scores and require a competition without weight classes; see RIS for fewer than four lifts.
This setting applies to every contest in the competition. Without it, existing single-sex contests rank by total when they have weight classes, or by RIS when they have none. Other scoring methods are rejected. If divisions use different scoring rules, resolve that format before importing it.
A missing ranking metric leaves the result unplaced. RIS ties use total, then lighter known bodyweight; total ties use lighter known bodyweight. These are OSL placings from the stored results, not a transcription of federation placings. Computed All4 RIS uses OSL’s current edition. Published scores remain marked as reported when the event is shorter or the inputs needed to recompute them are missing.
A competition can contain mixed and single-sex contests together. Keep each
athlete’s Sex on every row, and set CategorySex=MX only on mixed entries.
prepare retains that column whenever a mixed contest needs it.
Names
Use the athlete’s usual spelling and capitalization, including accents and
hyphens. Write Anne-Sophie, for example, rather than ANNE-SOPHIE. The importer
checks names but does not fix them for you.
Use a Latin spelling in FirstName and LastName. The optional NativeName
column preserves a name written in another script.
Identity uses the normalized name, sex, and Disambiguation. Correcting or
clearing Country preserves the athlete’s profile and URL.
When different athletes share a name and sex, use Disambiguation numbers
starting at 1, even if their countries differ. Keep each person’s number
consistent across competitions; check existing entries before assigning one.
Country
Keep the Country header. Leave its cell empty when the source omits the
athlete’s country; the host country is not evidence of nationality.
The profile uses the known country from that athlete’s entries. Empty cells leave that evidence intact. If all entries have empty cells, the profile shows “Country not recorded” and retains global rankings, records, and competition history. National rankings require a known country.
Conflicting known countries stop preparation and import. Correct the affected
entries together and import them in one batch. Use Disambiguation only when
the entries belong to different people. A genuine change of sporting nationality
needs a separate reporting policy; do not split one person to bypass this check.
Division
Add Division when a competition runs separate contests for the same weight
class, such as Open and Elite. Use the source’s division names, with consistent
spelling. If you use this column, fill it for every athlete. Otherwise, leave it
out.
WeightClassKg
Write 80 for a class up to 80 kg and 101+ for a class above 101 kg. Put the
number first, without kg or a leading sign.
The standard classes are:
- Men:
66,73,80,87,94,101,101+. - Women:
52,57,63,70,70+.
Other positive limits are accepted. Record the class used by the competition, using the same notation.
Some competitions rank on RIS alone and run no weight classes. Leave the column out for those rather than working a class back from bodyweight. When a meet combines weight-classed and unclassed contests, keep the column and leave it empty for athletes in the unclassed contests.
Attempts
Each movement has three attempt columns and one best-lift column:
| Movement | Attempt columns | Best-lift column |
|---|---|---|
| Muscle-up | MuscleUp1Kg, MuscleUp2Kg, MuscleUp3Kg | BestMuscleUpKg |
| Pull-up | PullUp1Kg, PullUp2Kg, PullUp3Kg | BestPullUpKg |
| Dips | Dips1Kg, Dips2Kg, Dips3Kg | BestDipsKg |
| Squat | Squat1Kg, Squat2Kg, Squat3Kg | BestSquatKg |
Write 100 for a successful attempt at 100 kg and 100x for a missed attempt.
Leave the cell empty if the attempt was not taken or is unknown. A zero is a
recorded attempt, not a missing value.
When attempts are provided, the best lift is the heaviest successful one. You may leave the best-lift cell empty; if you fill it, it must agree with the attempts. If only the best lift is known, fill that column alone.
Mark an athlete who missed every attempt at a movement as disqualified, with a
reason such as Bombed the squat. A no_show must have no attempts, best lifts, total, or positive RIS. A published
zero RIS may be kept as source evidence. Disqualified rows may keep their lifts
and published RIS, but receive no total, calculated RIS, or ranking. Their lift
values must still be consistent.
Totals and preparation
Use TotalKg for the overall result. Keep the total and any available lift
results together. The former ReportedTotalKg header is rejected.
Run osl-import prepare <directory> before importing. It fills a missing total
from successful best lifts only when every movement in the event is present,
validates the result, and formats the files. Existing totals must equal the sum
of a complete breakdown, or be at least the known subtotal when the breakdown
is incomplete. Negative totals and totals on disqualified or no-show rows are
rejected. A successful zero-weight lift counts as a recorded result.
When both the total and part of the breakdown are unknown, leave them empty. The validator warns that the result has no total or calculated RIS. Missing lifts are never treated as zero. Preserve a published total when available; it supports total rankings and, for All4 with bodyweight, RIS calculation even without a full breakdown.
prepare validates every selected competition before writing any files.
prepare --check leaves files unchanged and fails if preparation is needed.
Import requires a stored total whenever the breakdown is complete; it never
fills one. Rankings, pages and RIS calculations use that stored value.
Bodyweight and reported RIS
Enter each value the source provides: BodyweightKg, ReportedRis, or both.
Leave unknown values empty. Use ReportedRisEdition for the source’s formula
year when established; the competition year alone does not establish it.
For a complete, competed All4 result with bodyweight and a known M or F formula,
the validator checks the published score against its stated edition, rounded to
two decimal places. A disagreement blocks import. When the edition or required
results are unknown, both values are preserved and a warning explains why the
score could not be checked. Calculated ranking scores are stored separately;
they never replace ReportedRis in the CSV. A published RIS can still be used
when bodyweight is known but the total is missing. Scores published for shorter
events remain source evidence; eligible shorter competitions can use those
published scores for ranking, as described below. OSL does not recompute them
with the All4 formula.
For All4, missing bodyweights can be recovered from a published score and a complete
total. The recovery tool writes the estimate to BodyweightKg, marks it
BodyweightSource=recovered, and preserves ReportedRis and
ReportedRisEdition. All four fields are required for a recovered bodyweight;
the estimate must reproduce the original score. A reported weigh-in uses
BodyweightSource=reported, which is the default when bodyweight is supplied.
The former Ris header is rejected. Rename it to ReportedRis, preserving its
values. Existing archive files already use the new name.
RIS for fewer than four lifts
Some competitions, such as FinalRep Underground 3L, rank athletes by a published
RIS score across pull-up, dips and squat. Record the actual event as PDS.
Muscle-ups were not contested, so their cells stay empty.
For any supported event with one, two or three movements, RIS ranking requires:
scoring = "ris"under[competition], supported by the organizer’s rules.- No weight classes anywhere in the competition. Omit
WeightClassKg; a meet containing even one weight-classed contest is ineligible for shorter-event RIS. - The organizer’s published score in
ReportedRisfor each athlete who receives a RIS placing.
Men’s, women’s, mixed and division contests may remain separate. Here, “no
weight classes” means no weight limits; it does not mean combining those groups.
For a mixed contest, retain each athlete’s Sex and set CategorySex=MX.
For example, the metadata for a three-lift RIS competition includes:
event = "PDS"
sources = ["<organizer's results URL or document reference>"]
[competition]
name = "Example Underground"
start_date = "2026-06-28"
country = "VN"
status = "completed"
scoring = "ris"
[federation]
name = "FinalRep"
Keep the usual lift, total and bodyweight evidence. A known bodyweight does not
replace a published shorter-event score with a calculated All4 score. OSL
preserves ReportedRisEdition when established by the source, but does not
verify a shorter-event score against the All4 formula or recover bodyweight from
it. A missing score produces a warning and leaves that athlete without a RIS
placing, even when total and bodyweight are known. Disqualified and no-show
athletes remain unranked under the usual status rules.
Shorter-event scores appear as reported on competition and athlete pages.
Updating OSL’s All4 formula leaves them intact. RIS rankings and athlete progress
compare scores within one event: PDS scores do not enter the default MPDS
global ranking or All4 profile standings. API consumers can request a shorter
event with the rankings event filter; a competition’s own leaderboard already
uses that competition’s event. RIS ties still use total, then known bodyweight.
The four-lift rules remain unchanged: All4 may use weight classes and OSL may calculate its RIS from bodyweight and total. A shorter competition ranked by total may retain published RIS as evidence, but those scores do not determine placings or enter RIS rankings.
Validation
The importer rejects unknown fields, missing required columns and inconsistent results. Errors must be fixed before import. Warnings flag details to review, such as a missing city, missing bodyweight and RIS, or a name appearing in several contests.
Follow Validate it locally to check your files. A successful check confirms that the format is accepted; compare the results with the source too.
Data Access
You can browse the archive on the website or use the public API to access the data in your own projects. The data is dedicated to the public domain under CC0, so you can freely use, modify and share it. See Licensing for details.
You do not have to give credit, but a mention of OpenStreetlifting would make me happy.
Public API
The API provides competition results, athlete profiles and rankings as JSON. It is read-only and requires no account or API key.
The base URL is:
https://api.openstreetlifting.org/api/v1
For example, this request returns a page of competitions:
curl 'https://api.openstreetlifting.org/api/v1/competitions?page=1&page_size=20'
Lists are split into pages. Use page to choose a page, starting at 1, and
page_size to request between 1 and 100 results. The response includes
pagination details so you can request the remaining pages.
For available requests, filters and response fields, see the API reference. You can also find the OpenAPI specification and Bruno request examples on GitHub.
Bulk download
A download of the full archive is coming soon. It is not available yet; this page will be updated when it is ready.
Getting help
If you need help accessing the data, contact me and describe what you would like to use it for.
Licensing
OpenStreetlifting’s data is public domain. The code has a separate open-source licence.
Data
The archive is dedicated to the public domain under CC0 1.0 Universal. You can use, copy, modify and share the data, including commercially, without asking permission. Credit is optional, but a mention of OpenStreetlifting would make me happy.
This covers the files in backend/data/ and the data returned by the API,
including calculated totals, placings and RIS scores. The full terms are in
LICENSE-DATA.
Credit
If you would like to credit the project, you can use:
Data from OpenStreetlifting.
Contributing data
When you open a pull request that adds or corrects data in backend/data/, you
agree to share your contribution under CC0 too, so everyone can reuse it.
CC0 and personal data
CC0 waives copyright and the database right. It cannot waive data protection rights, and says so itself: the dedication does not affect the privacy or publicity rights of anyone whose data the work describes.
The files name living people. Taking a copy makes you responsible for what you then do with it, on your own account and under your own law, whatever the licence allows. That responsibility is yours, not this project’s, and CC0 does not transfer it.
It also runs one way in time. An athlete who asks to be taken off the archive is redacted here, but a snapshot somebody downloaded last year still carries their name and nothing can reach into it. If you redistribute the data, take it fresh rather than serving an old copy. See Personal Data.
Code
The code is licensed under the GNU Affero General Public License v3 (AGPLv3). You can use, modify and share it under that licence’s terms.
AGPLv3 covers the repository outside backend/data/, except for third-party
material with its own licence. The full terms are in
LICENSE.
Sources and third-party material
CC0 applies to OpenStreetlifting’s data, not to the original scoresheets, photos or videos linked as sources. Those materials keep their own rights and licences.
The country flags in frontend/static/flags/ are
Twemoji graphics, copyright Twitter, Inc and
other contributors, licensed under
CC BY 4.0.
Other dependencies, including fonts, keep the licences included in their packages.
Personal Data
OpenStreetlifting brings competition results together on searchable athlete pages. An athlete can appear here without having visited the site or submitted data. The privacy notice identifies the controller, explains the purposes of processing, and sets out your GDPR rights.
What the archive holds
Results come from federations, organisers, competition platforms, public posts, and contributors. They can include names in Latin and original scripts, sex category, country, competition details, bodyweight, attempts, scores, placings, and participation status. The archive also calculates rankings and performance comparisons. Some bodyweights are recovered from published scores rather than reported at a weigh-in; their origin is recorded in the data.
An Instagram handle may be added when a public account has been matched to an athlete. You can ask for the link to be corrected or removed separately from competition results.
The proposed basis for publishing results is legitimate interests under GDPR Article 6(1)(f): preserving and comparing the sport’s record. That basis requires necessity and a balance with athletes’ rights. Public sources, a CC0 licence, and the word “archive” do not settle that balance. Linking results across years and to social accounts increases the effect on a person’s privacy.
Bodyweight and performance information require care. Whether information reveals health depends on its context, combinations, and use; being a sports result does not automatically exclude it from the rules for health data. See the CNIL’s explanation of health data.
Request a correction or removal
Email [email protected] with your athlete-page link or enough competition details to identify the record. Say whether you want a correction, removal of a social link, removal of your name, restriction, or erasure. You do not need to give a reason to use the voluntary name-removal procedure.
Use email to keep the request private. A public issue, pull request, or Discord message can expose the information you want removed. A request received through another channel still needs to be handled; email is the preferred private route.
Requests are normally free and receive a response within one month. A complex request may require up to two additional months, with an explanation within the first month. Identity evidence is requested only when reasonably needed. The privacy notice explains access, correction, objection, erasure, restriction, portability, consent, automated decisions, and complaint rights, including their conditions.
What the removal tool does
The importer replaces matching names in current result files with a numbered
label such as Redacted Athlete #7. It clears the original-script name and
removes matching Instagram entries. Importing the changed files and pruning the
old database records updates the website, API, and new downloads and removes
the old named profile.
The tool preserves competition details, sex category, country, bodyweight, attempts, scores, and placings. Those details can still identify someone when compared with source results or earlier copies. This is pseudonymisation, not guaranteed anonymity or complete erasure. A successful command does not by itself resolve an objection or erasure request.
A public removal record holds a keyed fingerprint of the name, matching fields, and the replacement number. The secret key is kept outside the repository. This record remains personal data and helps detect later imports of matching names; changed spellings or identity fields may need additional checks. The check needs the secret key to work.
For commands and file formats, see the athlete-data README.
Earlier copies and continued retention
The archive currently has no scheduled expiry for results. Continued retention of identifiable records still needs justification and remains subject to your rights. The removal record serves a separate purpose: preventing republication while future imports remain possible.
The tool does not rewrite Git history, remove source result sheets, recall copies, or submit search-engine removal requests. Copies under the project’s control, including history, require their own assessment. Where erasure is required, GDPR Article 17(2) also requires reasonable steps to inform other controllers using the published data. Article 19 governs notification of corrections, erasure, and restrictions to recipients, with its stated exceptions. See the GDPR.
CC0 does not waive data protection rights. See Licensing. Requests to the original publisher or a search engine can help with copies they control; they do not replace this project’s obligations.
You can complain to the CNIL or another competent EU data protection authority. The privacy notice also explains your right to seek a judicial remedy.