</>TCG Price Lookup
CatalogAPIPricingFAQDocsBlog
CatalogAPIPricingFAQDocsBlog
</>TCG Price Lookup

Real-time trading card price data and developer API. Live prices from TCGPlayer and eBay for Pokemon, Pokemon Japan, Magic: The Gathering, Yu-Gi-Oh!, One Piece, Disney Lorcana, Star Wars: Unlimited, and Flesh and Blood.

Product

  • Card Price Checker
  • Value Checker
  • Price Guide
  • API for Developers
  • Pricing

Games

  • Pokemon
  • Pokemon Japan
  • Magic: The Gathering
  • Yu-Gi-Oh!
  • One Piece
  • Disney Lorcana
  • Star Wars: Unlimited
  • Flesh and Blood

Resources

  • Blog
  • FAQ
  • Documentation
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 TCG Price Lookup. All rights reserved.

TCG Price Lookup is not affiliated with or endorsed by TCGPlayer, eBay, or any trading card game publisher.

All trading card game names, logos, and card imagery are trademarks and © of their respective owners. Pokemon is © Nintendo / Creatures Inc. / GAME FREAK Inc. Magic: The Gathering is © Wizards of the Coast LLC. Yu-Gi-Oh! is © Konami Digital Entertainment. One Piece Card Game is © Bandai / Shueisha / Toei Animation. Disney Lorcana is © Disney / Ravensburger. TCG Price Lookup is an independent card price tracking service and is not affiliated with, endorsed by, or sponsored by any of the above companies, PSA, BGS, CGC, or any grading service. All card names and imagery are used solely for identification and price tracking purposes.

Realtime integration patterns

Build responsive pricing UIs today with efficient polling and caching — structured so you can swap in a streaming transport later without touching your UI.

No WebSocket or SSE endpoint today. The API is HTTP request/response. Prices update on a schedule rather than tick-by-tick, so well-tuned polling gives you up-to-date data without a persistent connection. The patterns below keep your client ready for a streaming transport if one ships.

Efficient polling

Batch your watchlist into a single ids request (up to 100 cards), poll only while the tab is visible, and re-render just the rows whose prices changed.

"js-comment">// Refresh a watchlist with the batch endpoint — one request, many cards.
async function refresh(ids, key) {
  const res = await fetch(
    "https:">//api.tcgpricelookup.com/v1/cards/search?ids=" + ids.join(","),
    { headers: { "X-API-Key": key } }
  );
  if (!res.ok) return; "js-comment">// see backoff section for 429 / 5xx handling
  const { data } = await res.json();
  for (const card of data) updateIfChanged(card);
}

"js-comment">// Poll only while the tab is visible to save quota.
let timer;
function start(ids, key, intervalMs = 30_000) {
  stop();
  timer = setInterval(() => {
    if (document.visibilityState === "visible") refresh(ids, key);
  }, intervalMs);
}
function stop() { clearInterval(timer); }

Suggested intervals

Match cadence to how visible the data is. Polling faster than prices actually move just burns your daily quota.

Use caseRefresh interval
Active watchlist / open card page15–30s
Background pages / dashboards60–120s
Bulk valuation / nightly syncOnce per scheduled run

Stability rules

  • •Apply exponential backoff on 429 and 5xx, honoring Retry-After when present.
  • •Stagger timers across cards so they don't all fire on the same tick and trip the burst limit.
  • •Pause polling when the tab is hidden; resume (and refresh once) when it becomes visible.
  • •Only re-render rows whose price fields actually changed.
  • •Debounce user-facing notifications so micro-moves don't spam alerts.

Stay transport-agnostic

Keep one reducer that applies price updates and one adapter that decides how they arrive. Polling is your adapter today; if a stream ships, you swap the adapter and the rest of your app is unchanged.

"js-comment">// Keep update handling separate from how updates arrive.
"js-comment">// Today the adapter polls; a future one could read a stream —
"js-comment">// your UI never has to change.
function applyPriceUpdate(state, card) {
  const prev = state[card.id];
  const next = card.prices?.raw?.near_mint?.tcgplayer?.market ?? null;
  if (prev?.market === next) return state;          "js-comment">// no-op, skip re-render
  return { ...state, [card.id]: { ...card, market: next } };
}

const pollingAdapter = { subscribe: (ids, key, cb) => start(ids, key, 30_000) };
"js-comment">// const streamAdapter = { subscribe: ... }  // drop-in later