Skip to content
Prepaid, no subscription trap. Top up a balance and we draw the monthly fee from it.
tcggraph

Scryfall LLC · Magic: The Gathering only

Scryfall alternative — beyond Magic

Scryfall is the best Magic API there is, and it is free. TCGGraph is what you reach for when your app also needs Pokémon, One Piece or Lorcana behind one key.

What Scryfall does well

  • Free, generous and genuinely excellent for Magic. No key required.
  • The best full-text search syntax in the hobby, and a huge community around it.
  • Complete Oracle text, every printing, every language, plus bulk data dumps.
  • Run by people who care deeply about Magic data quality.

Where TCGGraph differs

  • Scryfall covers Magic and only Magic, by design. If your product is Magic-only, that is not a limitation.
  • TCGGraph carries nine games behind one schema, so adding a second game costs you an enum value rather than a second integration.
  • TCGGraph normalises prices across Cardmarket, TCGplayer, Card Kingdom and Manapool with daily history; Scryfall surfaces marketplace links and current prices.
  • TCGGraph offers signed webhooks for set releases, spoilers and legality changes, so you do not have to poll.

Side by side

Feature comparison

FeatureScryfallTCGGraph
Games coveredMagic only9 games
Consistent schema across games
Price historyCurrent pricesDaily, accumulating
European prices (Cardmarket)Magic only8 games
US prices (TCGplayer)Magic onlyAll 9 games
Normalised multi-marketplace prices4 sources
GraphQL
Webhooks
Bulk data filesPaged, 2 credits per 100 cards
Image CDN
PriceFreeFrom $29/mo

When to use Scryfall instead

If you are building a Magic-only product, use Scryfall. It is free, the data is excellent and the search syntax is unmatched. Come back when you add a second game, a second currency, or a price you need to put in front of a paying customer.

Migration

What the change looks like

Concepts map closely. Most migrations are a single afternoon of find-and-replace plus a test pass.

Scryfall
# Scryfall
curl "https://api.scryfall.com/cards/search?q=c:red+cmc<=2"
TCGGraph
# TCGGraph — same query, and the shape survives adding a second game
curl "https://api.tcggraph.com/v1/cards?game=magic-the-gathering&colors=R&manaValue=2" \
  -H "Authorization: Bearer $TCGGRAPH_KEY"

Signals

When it is worth switching

None of these are reasons on their own. Two or three together usually are.

  • You are adding a second game and do not want to write a second ingestion layer, a second cache and a second price model.
  • You need price history rather than a spot price — for a portfolio chart, a repricing job or a trend alert.
  • You want to be told when a set publishes or a card's legality changes, instead of diffing bulk files on a cron.
  • You need an uptime commitment and a support contact, because something you sell depends on the data being there.

Migration

Moving off Scryfall, step by step

The honest version, including the parts that are not one-to-one.

  1. Step 1

    Map the search syntax

    Scryfall's query language is more expressive than any parameter-based API, and that is the part you will miss. Common ones translate directly: c:u becomes colors=U, id:u becomes colorIdentity=U, cmc<=3 becomes maxManaValue=3, kw:flash becomes keywords=Flash, and filters combine with AND. What does not translate is OR, negation, text search and format legality. t:dragon has no equivalent either, because typeLine matches the whole line. Read legalities on the cards you fetch, and run one request per alternative where Scryfall would take an OR.

  2. Step 2

    Switch the identifier you key on

    A card record here is one printing, like a Scryfall card object, and its id is ours, not Scryfall's. To map your stored rows, join on tcgplayerId or cardmarketId, which Scryfall also publishes and every record carries in externalIds. There is no oracle_id equivalent: group printings by name, which Magic keeps unique per rules object.

  3. Step 3

    Move price reads off the card object

    Scryfall attaches a small price object to each card. Every card here carries prices[], one quote per marketplace, finish and list type, and the daily history is one call away at /v1/prices/{id}/history. There is nothing to opt into and no blended number.

  4. Step 4

    Keep Scryfall where it is better

    Plenty of teams run both: Scryfall for its search syntax on a Magic-only screen, us for everything cross-game. They are not mutually exclusive, and we would rather tell you that than pretend otherwise.

Field mapping

What each field becomes

The part that takes the longest is discovering that Scryfall spells the same concept differently. Here it is, written down.

ScryfallTCGGraphNotes
oracle_id— (not carried)Group printings by name instead.
tcgplayer_idexternalIds.tcgplayerIdThe join key for a migration, with cardmarket_id.
cmcgameData.manaValueRenamed by Wizards in 2021; we follow the current term.
type_linegameData.typeLineSame string, em dash included.
color_identitygameData.colorIdentityArray of single-letter codes in both.
card_facesname, text, gameData.typeLineOne record; the faces joined with " // ", layout says how.
legalities.commanderlegalities.commanderSame keys, same four values.
prices.usdprices[].marketOurs is an array by source and finish, not one field.
image_uris.normalimages.normalUnmetered on both. No credit cost here either.

FAQ

Common questions

Anything else, email hello@tcggraph.com. We will tell you if the answer is that you should stay where you are.