A wrong match is worse than a missing one. An unmatched photo is simply absent from a rider's gallery; a mismatched photo is filed under someone else's name, which is what generates the complaint, the refund, and the lost client. For sportive and gran fondo photographers selling to participants, roster accuracy is the difference between a searchable archive and one nobody trusts.
Understanding the problem
Start list integration is the step that converts a detected number into a named rider. You upload the event's participant list, and each number read from a photo is checked against it in turn — so the roster acts as both a lookup table and a validity check. In cycling this matters more than in most sports, because the number is frequently read at distance, at an angle, or from a partly obscured back bib, and a single misread digit produces a plausible-looking number that may well belong to someone else in the same race.
Cycling galleries are searched by number or by name, and the buyer is often the rider. That means the match is the product. It also means errors are visible to exactly the person most likely to notice: a rider who finds a photo of someone else under their own number. Matching against a real roster is what lets us treat a read as a claim to be verified rather than a fact to be written.
In this sport specifically
Cycling gives the matcher an unusually rich second channel: team kit. In a professional or club field, jersey design, team name, and sponsor text are visible even when the back bib is hidden behind a saddle bag or turned away from the camera — so a photo with no readable number is not necessarily a dead end. The flip side is that this channel is noisy. Series-wide sponsors appear on every rider in the race, and a matcher that leans on sponsor text alone can confidently attach the wrong rider. Field size compounds all of it: in a packed sportive, numbers that differ by one digit are common, so a plausible misread often lands on a real, wrong entry.
Where it shows up
Late entries and DNS riders — the list you were sent a week earlier no longer matches the field on the road · very common
A number read correctly from the photo has no counterpart in your CSV, so it can't be matched to a name. The read itself was fine; the roster was stale. Conversely, riders who never started still occupy numbers in the list, leaving room for a misread to land on them.
Back bib obscured by a saddle bag or rain jacket, but the team kit is fully visible · very common
There is no number to read at all. If matching depends strictly on a number, the frame is unmatchable — even though a human looking at the jersey could name the team immediately and narrow it to a handful of riders.
A digit misread at distance produces a number that exists in the start list but belongs to a different rider · occasional
This is the dangerous case. The read is wrong but internally consistent — it corresponds to a genuine entry, so a roster check alone cannot catch it. The photo gets filed under a real rider who wasn't in the frame.
Series sponsor text on every jersey in the race being treated as identifying information · occasional
A sponsor that appears across the whole field carries no discriminating power, but it looks like evidence. Leaning on it can push a weak candidate over the line and produce a confident match on a rider identified by nothing more than a logo everyone is wearing.
Traditional approaches, and why they fall short
Manual lookup — reading the number off the photo, then finding it in a printed list or spreadsheet
Two context switches per photo: read the frame, search the sheet, type the name. It stays workable for a hand-picked selection and collapses across a full event folder. · Accurate while attention holds, then drifts. Transcription slips and off-by-one row errors are the usual failure, and they are invisible once the file is written.
The lookup cost is paid per photo, so it scales linearly with the shoot. It is also the step most often skipped under deadline, which is precisely when errors are most likely.
Basic OCR over the image, with the output pasted against the roster afterwards
Quick to run, but the verification pass is manual, because wrong reads have to be spotted rather than reported. · Workable on a flat, well-lit, front-facing number; unreliable on a curved jersey at distance, which describes most cycling frames.
Plain OCR transcribes any text it finds — sponsor names, bike brands, road signage — with no notion of which string is a bib number. It returns confident answers without distinguishing a valid entry from a hallucinated one, so the roster check has to happen entirely by hand afterwards.
Position and timing correlation — inferring identity from where a rider was on the road and when
Requires timing data from the organizer plus careful clock synchronization between your camera and their system. · Reasonable when riders pass a timing point strung out; ambiguous in a group, where many riders share a crossing window.
Only works near timing points, and a peloton crossing together leaves a long candidate list for every frame. Most of the best cycling photography happens away from the mats.
How RaceTagger handles it
You import the event's start list once as a CSV, and set the sport to cycling. A vision model reads what is visible in each photo — bib numbers on the back or hip, frame numbers, team name, and sponsor text — and each read is scored against the roster rather than trusted outright. The number carries the most weight; team and sponsor act as corroboration, and a candidate supported by more than one kind of evidence scores higher than one resting on a single read. When a detected number doesn't correspond to any entry in your list, that absence is treated as a signal: rather than accepting a number that isn't in the race, the matcher tests whether a near-miss reading would land on a rider who actually started.
Key advantage
The start list turns matching into a checked operation instead of an open-ended guess. A read that corresponds to no registered rider is treated as suspect, and a frame with no readable number can still be narrowed using team and sponsor evidence — which in cycling is often visible when the bib is not. Where the evidence is strong but not conclusive, the photo is set aside with its closest candidates attached, so a human decides rather than the tool guessing.
- Good conditions
- A clean back bib, shot square, on a rider whose number is in the start list — reads and matches cleanly, with team kit agreeing as a second signal
- Challenging
- Numbers at distance in a pack, partly hidden bibs, or a rider identified mainly by kit — often still matchable, but more of these frames land in the review queue with candidates attached rather than being resolved outright
- Worst case
- A misread that happens to correspond to another rider genuinely entered in the race. The roster check cannot catch this one, because the result is a valid entry — it is the failure mode we are most explicit about, and the reason we treat a review pass as part of the workflow rather than an optional extra
Import the start list once per event, from the Participants screen, where it becomes a preset for that event. The number column is the only hard requirement, and that importer answers to the header names your file is likely to already have — Number, Bib, race_number, numero — with rider name, team, and category picked up under their usual headers and carried through. You don't add a column for the tag text; it's composed from the fields you supplied. Check the rows rather than the headers before importing: a row with a different field count than the header line gets skipped, which is what an unquoted comma inside a team name will do to it. RaceTagger then processes the folder in batch, reading JPEG and RAW files via the embedded preview, and separates confident matches from frames that need a decision. Matches are written as EXIF/XMP/IPTC metadata — embedded in the file for JPEGs, but written to an XMP sidecar alongside RAW files rather than into the RAW itself, so forward a .NEF or .CR3 on its own and the names stay behind. Where the metadata does travel with the file, it lands in Photo Mechanic, Lightroom, or whichever gallery platform indexes standard fields. Frames carrying a review marker are written too — the marker is there so you can find them, not to hold the file back — which is why the review pass belongs before delivery, not after.
Manual vs OCR vs AI vision
| Metric | Manual | Basic OCR | RaceTagger |
|---|---|---|---|
| How a read becomes a named rider | You look the number up in a spreadsheet and type the name | Text is extracted, then reconciled against the roster by hand afterwards | Each read is scored against the imported start list as part of the same pass |
| A number that isn't in the start list | You notice it's missing, and stop to work out why | Written out as-is; nothing checks it against the field | Treated as suspect — a near-miss reading is tested against riders who actually started |
| Bib hidden, team kit visible | You recognize the kit and narrow it down yourself | No number, no output | Team and sponsor evidence can still narrow the candidates |
| Ambiguous or contested reads | Resolved on the spot, or guessed under deadline | Returned with the same confidence as a clean read | Held back with the closest candidates attached, for a person to decide |
| Cost model | Your hours, or a paid tagging assistant | Compute is cheap; the manual reconciliation after it is not | Credits — 1 credit per photo analyzed |
Practical tips
- 1
Ask the organizer for the start list on race morning, not the entry export from the week before
Late entries, transfers, and withdrawals all move numbers. A number read perfectly from a photo still can't be matched if it isn't in your file, and stale entries leave empty numbers for a misread to land on. The freshest export the organizer can give you does more for match quality than anything else you control.
- 2
Include a team column in your CSV even when you only care about numbers
Team is the evidence that survives when the bib doesn't. With a team column present, a rider photographed from the front or with a saddle bag across the number can still be narrowed, and a number read correctly gets a second signal agreeing with it. Without the column, that channel simply isn't available to the match.
- 3
Shoot where the field is strung out rather than where it is densest
Climbs, exits from technical corners, and the closing kilometers of a sportive separate riders. Separation does two things at once: it makes each bib physically readable, and it removes the near-identical neighbors that make a misread plausible. A pack shot is the hardest frame to match and often the least saleable per rider.
- 4
Treat the review queue as the place where a wrong match gets caught, and clear it before delivery
Frames with candidates attached are the ones the matcher deliberately declined to resolve. That queue is short by design and concentrated on exactly the ambiguous cases, so working it is a focused pass rather than a re-check of the whole shoot. Skipping it doesn't remove the uncertainty — it just ships it.
- 5
Spot-check a handful of matched photos against riders you can identify yourself before publishing the gallery
The failure mode a roster can't catch is a misread that lands on a real entry, and it will look completely normal in the output. A short sample check — a few riders you recognize, or numbers you noted on the day — is the cheapest way to detect a systematic problem, such as one digit being consistently misread across a whole session.
The takeaway
In cycling, the start list is not a convenience feature — it is what separates a detected number from an identified rider, and what lets a read that corresponds to nobody in the race be treated as suspect rather than written into your files. It is not a guarantee: a misread that lands on another genuine entry will pass the check, which is exactly why the review queue and a quick spot-check belong in the workflow before the gallery goes live.
Match your next cycling gallery against the real start list
You get free credits when you sign up — 1 credit per photo after that. Import a start list, run a folder from your last race, and see which frames match cleanly and which ones we hand back to you.
Try it free →Questions photographers ask
What format does the cycling start list need to be in?
A plain CSV, and the only column it truly requires is the rider's number. Import it from the Participants screen, where the start list becomes a preset for the event: that importer recognizes the names the number column usually already has — Number, Bib, race_number, bib_number, numero — ignoring case and treating a space like an underscore, so most organizer exports go in as they stand. Rider name, team, and category are picked up the same way, under headers like Driver, Name, Team, Category, or Class, and carry through into the photo metadata. There is no separate column to write for the tag text: when you don't supply one, it's assembled from the name, category, and team you did. The one thing worth a glance before importing is row shape rather than headers — a row that carries a different number of fields than the header row, which is what an unquoted comma inside a team name produces, is skipped without complaint. If nothing at all maps to a number, the import stops and tells you which headers it found. (There is a second, older CSV slot on the analysis screen, and it behaves differently: that one does insist on columns named numero and metatag. For a start list, use the Participants import.)
What happens when a rider's number isn't in the start list?
There is nobody to match it to, so no name is attached and there are no candidates to review — that outcome is recorded distinctly from an ambiguous read. It usually means the roster is out of date rather than that the read was wrong, which is why a race-morning export matters more than it sounds.
Can a photo be matched when the bib number can't be read at all?
Sometimes. Team and sponsor text are treated as real evidence in cycling, so a rider photographed with the number hidden can still be narrowed — and if the evidence is strong enough, matched. It works best when your CSV includes a team column and the field contains several distinguishable teams; in a single-club event, kit stops discriminating between riders.
Can it tag a wrong rider, and how would I know?
Yes, in one specific way: if a digit is misread and the resulting number belongs to another rider who genuinely entered, the result is a valid roster entry and the check passes. We'd rather state that plainly than promise it can't happen. The practical defense is the review queue plus a short spot-check of recognizable riders before you publish.
Does the sponsor text on every jersey confuse the matching?
It can, and that's a known weakness of leaning on kit. Text shared by the whole field — a series title sponsor, an event partner — carries no discriminating power even though it looks like evidence. Team-specific identifiers are the useful signal; race-wide branding is the noise.
Do I need a separate list for each stage or each event?
One list per event is the normal case, imported once and used across the whole folder. In series where numbers stay with the rider from stage to stage, a single list can carry the whole event — but check with the organizer rather than assuming, because some series reissue numbers between stages, and a roster that has quietly gone stale is the failure mode worth avoiding.
Keep reading