Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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

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.toml includes 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 has Sex=M or Sex=F, and competition.scoring matches 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

FieldWhat to enter
competition.nameThe competition’s name.
competition.start_dateThe first day, as YYYY-MM-DD.
competition.end_dateThe last day; defaults to start_date when omitted.
competition.venueThe venue name, if known; omit it when unknown.
competition.cityThe city, if known.
competition.regionThe region or state, if known.
competition.countryAn ISO 3166-1 alpha-2 country code, such as FR or DE.
competition.scoringtotal or ris; required for mixed contests.
competition.statusSee Status below.
federation.nameThe federation’s name, written consistently across competitions.
federation.abbreviationIts abbreviation, if used.
federation.countryIts 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:

LetterMovement
MMuscle-up
PPull-up
DDips
SSquat

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 only competition.toml.
  • live: a competition in progress with partial results. Include entries.csv and event, and add only published results. Change to completed when final results are available. The API uses live; the website displays “In Progress”.
  • completed: a competition with final results. Include entries.csv and set event.

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

ColumnWhat to enter
SexThe athlete’s sex: M or F. MX is not an athlete sex.
WeightClassKgThe weight class, such as 80 or 101+. Leave it out for a meet with none.
FirstNameThe athlete’s first name. Leave empty for a single name.
LastNameThe surname, or the full name for an athlete known by a single name. Required.
DisambiguationLeave empty unless different athletes share a name; see Names.
CountryThe athlete’s ISO 3166-1 alpha-2 country code, if the source gives it.
BodyweightKgThe athlete’s bodyweight, if known.
ReportedRisThe source’s published RIS score, whether or not bodyweight is known.
TotalKgOverall total from the source, or filled by prepare from a complete breakdown.
Statuscompeted, disqualified or no_show. Empty means competed.
StatusReasonA 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 by TotalKg.
  • 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:

MovementAttempt columnsBest-lift column
Muscle-upMuscleUp1Kg, MuscleUp2Kg, MuscleUp3KgBestMuscleUpKg
Pull-upPullUp1Kg, PullUp2Kg, PullUp3KgBestPullUpKg
DipsDips1Kg, Dips2Kg, Dips3KgBestDipsKg
SquatSquat1Kg, Squat2Kg, Squat3KgBestSquatKg

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 ReportedRis for 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.