DEV Community

lulzasaur
lulzasaur

Posted on

Compare TCGPlayer, Reverb, and OfferUp Prices in One API Call

Compare TCGPlayer, Reverb, and OfferUp Prices in One API Call

If you flip trading cards, musical gear, or general merchandise, you're probably checking multiple marketplaces manually to find the best price. TCGPlayer for Magic/Pokemon cards, Reverb for guitars and pedals, OfferUp for local deals.

I built a unified API that searches across 20+ marketplaces and returns normalized results. Here's how to build a price comparison tool in ~30 lines.

Quick Start: Cross-Marketplace Search

const API_URL = 'https://marketplace-price-api-production.up.railway.app';
const API_KEY = 'your-key';

// Search for a Fender Stratocaster across marketplaces
const markets = ['reverb', 'offerup', 'craigslist'];
const query = 'Fender Stratocaster American Professional';

const results = await Promise.all(
  markets.map(async (market) => {
    const resp = await fetch(
      `${API_URL}/${market}/search?` +
      new URLSearchParams({ q: query, limit: '5' }),
      { headers: { 'X-Api-Key': API_KEY } }
    );
    const data = await resp.json();
    return { market, listings: data.results || [] };
  })
);

// Find the cheapest listing across all marketplaces
const allListings = results.flatMap(r =>
  r.listings.map(l => ({ ...l, source: r.market }))
);

allListings
  .filter(l => l.price > 0)
  .sort((a, b) => a.price - b.price)
  .slice(0, 10)
  .forEach(l => {
    console.log(
      `$${l.price.toFixed(2)}${l.title.slice(0, 60)} [${l.source}]`
    );
  });
Enter fullscreen mode Exit fullscreen mode

Output:

$850.00 — Fender American Professional II Stratocaster [offerup]
$899.00 — Fender Am Pro II Strat Mystic Surf Green [reverb]
$925.00 — Fender American Professional II Stratocaster HSS [craigslist]
$949.99 — Fender American Pro II Strat Dark Night [reverb]
$975.00 — Fender American Professional II Strat w/ Case [reverb]
Enter fullscreen mode Exit fullscreen mode

One search query, three marketplaces, sorted by price.

Trading Card Price Comparison

For TCGPlayer, the API returns market pricing data:

const tcgResp = await fetch(
  `${API_URL}/tcg/search?` +
  new URLSearchParams({
    q: 'Charizard ex 223',
    game: 'pokemon'
  }),
  { headers: { 'X-Api-Key': API_KEY } }
);

const cards = await tcgResp.json();

for (const card of cards.results.slice(0, 5)) {
  console.log(`${card.name} — Market: $${card.marketPrice}`);
  console.log(`  Low: $${card.lowPrice} | Mid: $${card.midPrice}`);
}
Enter fullscreen mode Exit fullscreen mode

Building an Arbitrage Finder

The real power is finding price gaps between marketplaces. Here's a script that checks if something is cheaper on one platform vs. another:

async function findArbitrage(query, buyFrom, sellOn) {
  const [buyResults, sellResults] = await Promise.all([
    fetch(
      `${API_URL}/${buyFrom}/search?q=${encodeURIComponent(query)}&limit=10`,
      { headers: { 'X-Api-Key': API_KEY } }
    ).then(r => r.json()),
    fetch(
      `${API_URL}/${sellOn}/search?q=${encodeURIComponent(query)}&limit=10`,
      { headers: { 'X-Api-Key': API_KEY } }
    ).then(r => r.json()),
  ]);

  const buyMin = Math.min(
    ...buyResults.results.filter(r => r.price > 0).map(r => r.price)
  );
  const sellMax = Math.max(
    ...sellResults.results.filter(r => r.price > 0).map(r => r.price)
  );

  const margin = ((sellMax - buyMin) / buyMin * 100).toFixed(1);

  if (sellMax > buyMin) {
    console.log(`💰 ${query}`);
    console.log(`   Buy on ${buyFrom}: $${buyMin.toFixed(2)}`);
    console.log(`   Sell on ${sellOn}: $${sellMax.toFixed(2)}`);
    console.log(`   Margin: ${margin}%`);
  }

  return { query, buyMin, sellMax, margin: parseFloat(margin) };
}

// Check a list of items
const items = [
  'Boss Katana 50',
  'Shure SM7B',
  'Roland TD-17',
  'Fender Jazz Bass',
];

for (const item of items) {
  await findArbitrage(item, 'offerup', 'reverb');
  await new Promise(r => setTimeout(r, 300));
}
Enter fullscreen mode Exit fullscreen mode

Supported Marketplaces

The API covers 20+ marketplaces across categories:

Musical Instruments: Reverb
Trading Cards: TCGPlayer
General: OfferUp, Craigslist, Facebook Marketplace, Poshmark
Real Estate: Redfin, Realtor.com, Zillow
Cars: AutoTrader, Cars.com, CarGurus
Home Services: Thumbtack, Houzz, Angi

Each marketplace endpoint follows the same pattern: /{marketplace}/search?q=your+query. The response schema is normalized — title, price, url, image, location — so you don't need separate parsing logic per marketplace.

Price Tracking Over Time

Set up a daily cron to track prices on specific items:

import { appendFileSync } from 'fs';

const TRACK = [
  { query: 'Pokemon Charizard ex 223', market: 'tcg' },
  { query: 'Gibson Les Paul Standard', market: 'reverb' },
];

for (const item of TRACK) {
  const resp = await fetch(
    `${API_URL}/${item.market}/search?q=${encodeURIComponent(item.query)}&limit=5`,
    { headers: { 'X-Api-Key': API_KEY } }
  );
  const data = await resp.json();

  const prices = data.results
    ?.filter(r => r.price > 0)
    .map(r => r.price) || [];

  if (prices.length > 0) {
    const avg = (prices.reduce((a, b) => a + b, 0) / prices.length).toFixed(2);
    const line = `${new Date().toISOString()},${item.market},${item.query},${avg},${Math.min(...prices)},${Math.max(...prices)}`;
    appendFileSync('price-history.csv', line + '\n');
  }
}
Enter fullscreen mode Exit fullscreen mode

After a few weeks, you'll have enough data points to spot trends and time your buys.

I built this because I got tired of writing scrapers every time I needed marketplace data for a project. It's on RapidAPI — free tier for evaluation, paid tiers when you're running it in production.

Top comments (0)