Fetching Free Player Faces for a Game Without Shipping the Wrong Human
I wanted real footballer photos on the cards in my draft game, free-licensed only. The fetch was easy. Not shipping the philosopher Socrates instead of the footballer was the hard part. Here is the pipeline and the disambiguation fix.
My draft game, World 11, puts real footballers on cards. About 1,234 of them, pulled from World Cup squads going back to 1966. I wanted the cards to show the actual player, because recognising the face is half the fun of a drafter. What I was not going to do was ship copyrighted press photos. So the rule was simple: free-licensed images only, properly attributed, or a clean fallback. Getting the images was a morning. Making sure each one was actually the right person took longer and taught me more.
The Easy Part
Wikipedia and Wikimedia Commons host a lot of player photos under licenses you can actually use: Creative Commons, public domain, and similar. The MediaWiki API will hand you a page's lead image and the image's license metadata. So the first pass is short:
- For each player name, hit the API for the page's thumbnail and the image's license.
- Keep the image only if the license is explicitly free. Anything fair-use or non-free gets skipped, never downloaded.
- Crop to a square, save it under a slug derived from the name, and write an attribution line crediting the photographer, because Creative Commons requires it.
Players with no free image get a clean initials badge instead. That is the whole happy path, and it covered a big chunk of the roster on the first run.
Then I looked at the cards.
The Hard Part, Names Are Ambiguous
The midfielder Socrates is one of the most famous Brazilians to ever play the game. Search Wikipedia for "Socrates" and you get the Greek philosopher. My fetch dutifully put a marble bust on the card.
It was not a one-off. "Hulk" gave me the comic-book character instead of the Brazil forward. A backup keeper named Luis resolved to an American businessman. A one-word name is a coin flip, and the exact-title lookup confidently grabbed whatever the most prominent article was.
The instinct is to fix it by searching "
The Fix, Verify Then Decide
What actually worked was a verification pass that does not trust either lookup blindly:
- For each face, check whether the source page is actually described as a footballer. The page's short description or its categories tell you this cheaply. A philosopher, a businessman, a comic character all fail the check immediately.
- If a face fails, try to re-resolve it through a football-specific search and re-verify the result is a footballer.
- If it still cannot be confirmed, or the name is so ambiguous that the search returns an obviously different person, revert to the initials badge.
That third step is the one that matters. A missing face is fine. A clean initials card reads as a deliberate design choice. A confidently wrong face, a philosopher or the wrong famous player, breaks the illusion and makes the whole roster feel untrustworthy. So when in doubt, ship nothing rather than ship wrong.
There was one more gotcha worth flagging for anyone batching this. The obvious way to check "is this a footballer" is to read the page's categories, and the obvious way to do that fast is to batch fifty pages per API call. The API caps how many categories it returns per request, so most pages in a big batch came back looking category-less and got flagged as not-footballers. My first audit flagged 849 of 1,034 faces, including Messi. The page short-description field returns one clean string per page with no such cap, and switching to that dropped the false positives to a handful of genuinely wrong ones.
Where It Landed
After the verification pass and the reverts, coverage sat around 84 percent of the roster with confirmed-footballer photos, and the rest on clean initials. Every photo is credited in an attribution file that ships with the game. No press photos, no wrong humans, no marble busts.
The general lesson travels beyond games. When you are pulling identity-bearing data from a public source by name alone, the fetch is never the hard part. Disambiguation is. Build the verification step first, and make "show nothing" the default whenever you cannot be sure.
You can see the faces, busts safely excluded, in World 11, free in the browser.
Like this? You'll like what I'm building too.
Two ways to support and get more of this work.
HEARTH
A privacy-first Life OS for your desktop. Journal, tasks, and notes that stay on your machine. Coming soon, direct download from this site.
Read moreMY TOOLKITS
Receipts-first toolkits for shipping after hours, building Claude agents, publishing on Amazon, and more. The exact methods I used, not theory.
Browse on WhopRelated Articles
Balancing a Roguelike to a One-in-Three Win Rate With a Headless Harness
My draft roguelike was too easy. A strong team won the cup two-thirds of the time, so winning meant nothing. Here is how I stopped guessing and tuned it to a real one-in-three with a few hundred simulated runs.
Solo Game Development: Trap or Actually Doable?
Everyone says solo game dev is impossible. Then you look at Stardew Valley. Here's the realistic breakdown of building games alone in 2025.
How I Built a Seeded Football Match Simulation for a Draft Game
Players draft the team but never play the match, so the simulation has to feel fair. Here is the possession-and-event model behind World 11, why it is deterministic from a single seed, and what that buys you for free.