Photos tagged only with numbers are effectively unfindable by the people most likely to buy them. Runners search their own name, clubs search their club, and press desks need a name in the caption — so an archive keyed to bare numbers pushes the lookup work back onto you, one query at a time, in the days right after the race when interest in the gallery is at its highest.
Understanding the problem
Start-list integration is the step that joins two datasets: the bib numbers detected in your photos, and the participant list supplied by the event. The join key is the number, and everything you actually want to deliver — the runner's name, their category, their club or team — is carried by the list rather than by the photo. Done once per event, it converts the whole take from number-tagged to name-tagged.
For mass-participation road running, the archive is the product. Photo sales, gallery search, club deliveries, and press captions all resolve through a name or a club, not through a bare integer. And because the list is a single import, the difference between a properly matched event and an unmatched one is not a per-photo cost — it is the difference between a gallery that people can search and one they can't.
In this sport specifically
Road running start lists come from timing and registration platforms, and they arrive in whatever shape that platform exports: names split into two columns or joined into one, categories written as age bands or as codes, club fields left empty for unaffiliated runners, accented characters mangled by the export encoding. Fields are usually finalized late, because race-week registration, bib reassignments, and no-shows are normal in a field of tens of thousands. And unlike a motorsport entry list, a marathon list is a list of private individuals — the names in it are personal data you are choosing to write into files you distribute.
Where it shows up
One event day, several distances — marathon, half, and 10K — sharing a numbering scheme · very common
Bib number 412 exists in more than one race. The photo shows the digits and nothing else that reliably says which distance the runner is in, so a single flat list keyed on the number alone can resolve to the wrong person entirely.
The start list you were sent on Wednesday, used on the photos you shot on Sunday · very common
Race-week entries, bib reassignments, and transfers land after the export. Numbers that changed hands now point at the previous holder — and that is worse than no name at all, because it looks correct and gets delivered.
An export where the runner's name is spread across separate first-name and last-name columns · common
The importer needs to know which text belongs on the photo. Left unresolved, you get half a name in the metadata, or a column of surnames with no first names attached.
A charity or corporate wave where the bib carries a name instead of a number · occasional
There is no number to read, so there is nothing to join on. These runners fall out of the automated pass entirely and need to be handled as their own set.
Traditional approaches, and why they fall short
Keeping the start list open in a spreadsheet and looking up numbers by hand as you caption
Scales linearly with the take — every distinct runner in the gallery is one more manual lookup · Accurate while you are fresh; transposition errors creep in as the session runs long
It puts the join at the slowest possible point — after the shoot, at one photo at a time, on the night when the gallery is most valuable. The runners who never get looked up are simply never findable by name.
Delivering the gallery keyed on bib numbers only, and letting buyers search by number
No tagging cost, but a permanent support cost · Exactly as accurate as the numbers you read — no name-level errors, because there are no names
It works only for the buyer who remembers their number and knows to search by it. Everyone searching a name, a club, or a category — which is most people, and every press desk — finds nothing, and the questions come back to you.
Matching after the fact against published results by finish time
Low per photo once set up, but depends on synchronized clocks and reliable position notes · Reasonable at a sparse finish line; unreliable mid-course and in crowded frames
It infers identity from where a runner should have been rather than reading who is in the frame. In a mass field, several runners share any given second at any given point on the course, so the inference is confidently wrong rather than blank — and there is nothing in the output that tells you which is which.
How RaceTagger handles it
RaceTagger reads the bib numbers visible in each photo with a vision model that is looking for a race bib rather than transcribing any text it finds, then matches each read against the participant list you imported for the event. The list is a CSV: a number column plus the tag text to attach, with optional name, category, and team columns — and if you supply name, category, and team without a tag column, it composes the tag from them. Extra columns you include are carried through as additional fields rather than dropped. A number that matches no row in your list doesn't resolve to a participant, and a read that doesn't resolve cleanly is marked as needing review — with the closest candidates from your list surfaced for you to confirm — rather than being accepted as a settled match.
Key advantage
Identity comes from the number that is actually in the frame, checked against a real list — not inferred from timestamps or finish position. That means an uncertain read arrives marked as uncertain, with candidates you can choose between, rather than as a plausible name silently attached to the wrong runner.
- Good conditions
- A flat, unobstructed bib facing the camera, with a number that exists in the imported list — reads and matches cleanly, and the name, category, and club from your list carry into the metadata
- Challenging
- Bibs folded at the edge, partly covered by a hydration belt or a jacket, or angled away — often still readable, but more of these come back marked for review, and a partial read that matches no row in the list doesn't resolve to a participant
- Worst case
- The bib is not visible in the frame at all, or the event uses name-only bibs — there is no number to join on, so the photo isn't matched to anyone rather than being given a guessed identity
Import the event's list once, then batch-process the folder. RaceTagger handles JPEG and RAW — reading RAW via the embedded preview — so you don't convert a day's shooting first, and matches are written as EXIF/XMP/IPTC metadata — embedded in the file for JPEGs, and written to an XMP sidecar alongside RAW files rather than into the RAW itself — with uncertain reads carrying a review marker rather than being delivered as a settled identity. That means the names and clubs travel with the photos into Photo Mechanic, Lightroom, or Capture One and into whatever gallery platform you deliver through, instead of living in a spreadsheet alongside them. Running is a dedicated sport profile in the app; identification there is bib-driven, not face-driven, so a runner is only identified when their number is in the frame.
Manual vs OCR vs AI vision
| Metric | Manual | Basic OCR | RaceTagger |
|---|---|---|---|
| How the number becomes a name | You look it up in the spreadsheet, one runner at a time | It doesn't — OCR returns digits and stops there | Read numbers are matched against the imported list in the same pass |
| A number that isn't in the list | You notice it, and decide what to do | Written as-is, with no way to know it was never a valid bib | No name written — a number with no match in your list produces nothing; an ambiguous read is marked for review with candidates to confirm |
| Sponsor text and course signage in the frame | Ignored — you know what a bib looks like | Frequently returned as though it were the bib number | Looks for a race bib, and a read matching no list entry doesn't get accepted |
| Where the names end up | In your captions, or in a sidecar spreadsheet | Wherever you paste them afterward | Written into the files as EXIF/XMP/IPTC, so they travel into Photo Mechanic, Lightroom, or Capture One |
| Cost model | Your hours, on the night the gallery matters most | Compute only, plus the manual pass to find wrong and missing reads | Credits — 1 credit per photo analyzed |
Practical tips
- 1
Ask for the start list after the race-week cutoff, not the one that's already in your inbox
Late entries, transfers, and bib reassignments are settled close to the start. Every match you make inherits the trust of the list, so the freshest export the organizer can send — ideally the same file the timing system ran on — is worth more than any amount of care later.
- 2
Import one list per race, and keep folders per race, when the day has several distances
If the marathon, the half, and the 10K reuse numbers, no tool can tell them apart from the digits on the bib alone. Splitting the day by race — separate folders, separate lists — removes the ambiguity structurally instead of hoping the match resolves it.
- 3
Normalize the name column before you import, not after you deliver
Exports split names across columns, use inconsistent capitalization, or mangle accented characters. Five minutes in a spreadsheet fixing the column you actually want written into the metadata is cheaper than correcting the name on every file that carries it.
- 4
Decide deliberately what personal data goes into the files you hand out
A start list is a list of private individuals, and metadata written into a JPEG travels with that file anywhere it is forwarded. Import the columns your delivery genuinely needs — a name and a club for a searchable gallery — rather than the whole registration export with contact details and age in it.
- 5
Spot-check the match on a handful of runners you can identify yourself before processing the whole take
Run a small folder first and confirm that number, name, and club line up on runners you recognize. A column mapped to the wrong field is invisible in the abstract and obvious on five photos — and catching it there saves rewriting metadata across the entire event.
The takeaway
The number in the photo and the name in the start list are two halves of the same record, and the join between them is a one-time import rather than a per-photo chore. What makes it work is the discipline around the list: get the version that was actually used on race day, keep separate distances separate, and import only the personal data your delivery needs. What makes it trustworthy is what happens when the join fails — a number that matches nothing gets no name at all, and an uncertain read comes back marked for your eye — instead of either one quietly becoming somebody else's name.
Turn a folder of bib numbers into a gallery people can search by name
500 free credits when you sign up — 1 credit per photo. Import your event's start list, run a folder, and see the names land in the metadata.
Try it free →Questions photographers ask
What does the start-list CSV need to contain?
At minimum a column with the bib number and a column with the tag text to attach to it. If you supply name, category, and team columns instead of a prepared tag, RaceTagger composes the tag from those, and any extra columns you include are carried through as additional fields rather than discarded.
The organizer sent me the list in their timing platform's own format. Is that a problem?
Usually not — it is a spreadsheet export, and the work is renaming and tidying columns rather than converting formats. The part worth doing carefully is deciding which column becomes the text written into your photos, especially when the export splits names across separate first-name and last-name fields.
What happens when a bib number isn't in the list I imported?
There are two different outcomes worth separating. If the number simply isn't in your list, the photo isn't matched to anyone — no name, and nothing to choose between. If the read itself is ambiguous or uncertain, that's the other case: it's marked for review with the nearest candidates from your list for you to confirm. Either way, nothing is delivered as a settled identity on a guess, and a number that corresponds to no entry is exactly the signal you want — it means either a misread digit or a runner who registered after your export.
My event runs a marathon, a half, and a 10K with overlapping numbers. Can it tell them apart?
Not from the photo alone — the digits on the bib are the same digits, and nothing else in the frame reliably resolves which race a runner is in. Handle it structurally: keep the races in separate folders and match each against its own list, rather than one merged list for the day.
Can it identify runners by face when the bib is hidden?
No. Running is set up as a bib-driven profile with face recognition off — identification comes from the number in the frame, so a runner whose bib is covered by a jacket, turned away, or out of shot isn't matched to anyone. We would rather leave that photo unidentified than attach a name we inferred.
Do the runner names actually end up inside the image files?
For JPEGs, yes: matches are written into the file as EXIF/XMP/IPTC metadata, so the name, category, and club from your list travel with the photo into your editor and your delivery platform, while uncertain reads carry a review marker rather than being recorded as settled. RAW files work differently — nothing is written inside the RAW itself. The metadata goes into an XMP sidecar file next to it, which Photo Mechanic, Lightroom, and Capture One read, but which has to travel with the RAW: forward a .NEF or .CR3 on its own and the names stay behind. For the JPEGs you deliver, the data does travel to anyone the file is forwarded to, which is worth keeping in mind when you decide which columns to import.
Keep reading