Price comparison sounds straightforward: find the same product on two marketplaces and show both prices. For most products, that's a solved problem — match on UPC, ISBN, or manufacturer SKU. Trading cards don't have any of that.
There is no universal product identifier for trading cards. No barcode on individual cards, no industry-wide SKU system, no standard naming convention. Every marketplace invents its own product catalog from scratch, and they all do it differently.
The Same Card, Many Identities
Consider a single card: Charizard ex from the Pokémon set "Obsidian Flames." Here's how it might appear across different sources:
eBay listing 1: "Charizard EX 125/197 Pokemon Obsidian Flames NM"
eBay listing 2: "CHARIZARD ex Obsidian Flames 125 / 197 Mint"
eBay listing 3: "Pokemon SV03 Charizard-ex Ultra Rare" (SV03 = platform-specific set code)
Collector database: "Charizard ex (OBF 125)"
That's five representations of the same card — and the third one is actually a Japanese variant using the Japanese set code SV03. Language is another critical delineator: the English and Japanese printings have different market values, different collector numbers, and different set names. A matching system that ignores language risks conflating two entirely different products.
Now multiply by finishes — this card exists as a regular version and an illustration rare with entirely different artwork. Each finish has different pricing. Each finish can be in multiple conditions (Near Mint through Damaged) and graded variants (PSA 10, BGS 9.5, etc.), each with its own market value.
One Charizard. Easily 30+ distinct priceable items once you account for language, finish, condition, grade, and listing variation.
Scale of the Problem
English Pokémon TCG alone has over 50,000 distinct products when you factor in every set, every card, every finish, and every language variant. Add conditions (Near Mint through Damaged) and graded variants (PSA 1–10, BGS, CGC, and more), and the number of individually priceable items grows by an order of magnitude. That's one game.
We're expanding to cover Magic: The Gathering (which has been printing since 1993 and has hundreds of thousands of unique cards), Yu-Gi-Oh!, One Piece, and eventually other TCGs. Across all games, languages, conditions, and grades, the total addressable catalog is in the millions.
Every one of those needs to be matched across every marketplace we aggregate.
Why String Matching Fails
The naive approach is fuzzy string matching — take a product title from TCGplayer, find the closest match in eBay listings. This breaks immediately:
- Abbreviations — "ex" vs "EX" vs "Ex" (these can refer to different card mechanics in different eras)
- Set naming — "Obsidian Flames" vs "OBF" vs "SV03" (platform-specific code) vs "Scarlet & Violet 3" — and these identifiers can cross language boundaries, where the same code may reference different product catalogs depending on the marketplace
- Seller additions — listings include condition, shipping info, lot descriptions, and promotional text that pollutes the title
- Multi-card listings — eBay sellers frequently list lots, bundles, or "pick your card" listings that don't map to a single product
- Language mixing — Japanese card names transliterated into English, or English names used for Japanese printings
Fuzzy matching on raw listing titles produces false positives that are worse than no match at all. Showing the wrong card's price is more damaging than showing no price.
Our Approach
Instead of matching listing-to-listing, we match everything to a canonical product identity. Each card in our system has a normalized representation that captures:
- Card name (standardized spelling and casing)
- Set (resolved from any valid identifier — full name, abbreviation, set code, product code)
- Collector number (the X/Y number printed on the card)
- Finish type (holofoil, reverse holo, normal, etc.)
- Print run (1st Edition, Unlimited, Shadowless for older sets)
Marketplace listings are parsed and mapped to this canonical form. A TCGplayer product and an eBay listing that resolve to the same canonical identity are considered the same card, regardless of how differently they're titled.
Data Normalization Pipeline
Raw marketplace data is messy. Prices arrive in different currencies, conditions use different grading scales, and product catalogs update constantly as new sets release. Our normalization pipeline handles:
- Price standardization — converting everything to a common currency, separating shipping costs from card prices, handling auction vs. buy-it-now pricing models
- Condition mapping — TCGplayer uses Near Mint/Lightly Played/Moderately Played/Heavily Played/Damaged. eBay sellers use whatever they want. We map free-text condition descriptions to a standard scale.
- Variant resolution — determining whether a listing is for a regular, holofoil, reverse holofoil, full art, or other variant. Sellers are inconsistent about specifying this, so we use a combination of title parsing, price context (a $0.25 listing is probably not the holofoil), and when available, image analysis.
- Freshness — pricing data has a shelf life. A sale from two hours ago is useful; a sale from two months ago can be misleading for volatile cards. We weight recent data more heavily and surface the timestamp so users can judge for themselves.
The Data Acquisition Challenge
None of this works without data. Aggregating reliable, fresh pricing data from multiple marketplaces is its own engineering discipline. Each source has different data formats, update frequencies, and terms of service. We work within each platform's guidelines and pursue official data partnerships as we grow.
Maintaining consistent data flow across multiple sources that evolve independently — with changing schemas, access policies, and catalog structures — is an ongoing operational investment that rivals the matching system itself in complexity.
Accuracy and Edge Cases
For well-structured modern sets (Scarlet & Violet era Pokémon, recent Magic sets), matching accuracy is very high. The collector number + set approach works reliably when both pieces of data are present and correctly formatted.
The hard cases are:
- Older sets — Japanese printings of early Pokémon sets (Base Set, Jungle, Fossil era) didn't include collector numbers. Their English counterparts did, but cross-language matching for these older sets relies more heavily on card name + set, which is less precise.
- Promo cards — promotional cards often have non-standard numbering or appear in multiple promo sets, making canonical identification ambiguous.
- Regional variants — the same card printed in different regions may have different artwork, different numbering, or different available finishes. A Japanese Pikachu promo and its English equivalent are the same card conceptually but different products.
- Error cards and misprints — these are unique, valuable, and essentially impossible to catalog systematically.
We handle edge cases through a combination of automated heuristics and manual curation for high-value cards where accuracy matters most.
We want to be transparent: as a new platform, our matching system is not perfect. There will be cases where fuzzy matching is the last resort, where false positives slip through, or where data corrections take time to propagate. Building a comprehensive, accurate product catalog is an iterative process — one that takes sustained investment in data quality. Many platforms with years of head start still struggle with these same challenges. We are committed to getting it right, and we will improve continuously as our coverage and validation systems mature.
What We're Building Toward
The canonical product identity system is designed to scale to any card game and any language. Adding a new TCG means building a new set of parsing rules and a new product catalog, but the matching infrastructure, normalization pipeline, and presentation layer are game-agnostic.
The long-term goal is comprehensive coverage: every card, every variant, every marketplace, every language. For a collector trying to figure out what their card is worth, one search should surface every data point that exists.
Questions or feedback? Reach out at [email protected].