JavaScript interface for the Gatherer card database
CoffeeScript Shell Makefile JavaScript
Latest commit c0ed519 Aug 4, 2016 @davidchambers xyz@1.0.x
Failed to load latest commit information.
lib 0.8.0 Mar 31, 2016
scripts makefile: integrate xyz Jul 18, 2014
src recognize colorless mana symbol Mar 24, 2016
test tests: update failing test and disable nondeterministic tests Aug 4, 2016
.gitignore provide a JavaScript API rather than a REST API Jan 14, 2013
.npmignore add .npmignore Jul 18, 2014
.travis.yml respond with "no results" given non-existent card name Dec 31, 2015
LICENSE add LICENSE (closes #58) Jun 15, 2013
Makefile respond with "no results" given non-existent card name Dec 31, 2015 readme: use SVG version of Travis badge Nov 21, 2015


Build Status

Gatherer is the canonical source for Magic: The Gathering card details. While useful, it lacks an interface for retrieving this data programmatically. The lack of an API makes creating Magic-related applications unnecessarily difficult.

Tutor is a simple JavaScript interface for Gatherer.



tutor.card(id, callback(err, card))
tutor.card(name, callback(err, card))
tutor.card(details, callback(err, card))

The first and second forms are shorthand for tutor.card({id: id}, ...) and tutor.card({name: name}, ...) respectively. The callback is passed an object representing the specified card. Version-specific metadata such as flavor text and rarity are included for cards specified by id. Attributes not applicable to the card type (e.g. lands have no mana cost) or not present (e.g. certain creatures have no rules text) are omitted.

tutor.card 'Demonic Tutor', (err, card) ->
  # => "Demonic Tutor"
  console.log card.mana_cost
  # => "{1}{B}"
  console.log card.text
  # => "Search your library for a card and put that card into your hand. Then shuffle your library."

Split cards

Because the two sides of a split card share a Gatherer id, it's necessary to provide the name of the desired side:

tutor.card id: 27165, name: 'Fire', (err, card) ->
  # => "Fire"

tutor.card id: 27165, name: 'Ice', (err, card) ->
  # => "Ice"

Retrieving either side of a split card by name is straightforward:

tutor.card 'Fire', (err, card) ->
  # => "Fire"

tutor.card 'Ice', (err, card) ->
  # => "Ice"

Flip cards

Retrieving the top half of a flip card by id is straightforward:

tutor.card 247175, (err, card) ->
  # => "Nezumi Graverobber"

Either half of a flip card can be retrieved explicitly by setting which to "a" (for the upper half) or "b" (for the lower half):

tutor.card id: 247175, which: 'b', (err, card) ->
  # => "Nighteyes the Desecrator"

When retrieving a flip card by name rather than id, one may simply provide the name of the desired half:

tutor.card 'Nighteyes the Desecrator', (err, card) ->
  # => "Nighteyes the Desecrator"

Double-faced cards

Either face of a double-faced card can be retrieved by id:

tutor.card 262675, (err, card) ->
  # => "Afflicted Deserter"

tutor.card 262698, (err, card) ->
  # => "Werewolf Ransacker"

Or by name:

tutor.card 'Afflicted Deserter', (err, card) ->
  # => "Afflicted Deserter"

tutor.card 'Werewolf Ransacker', (err, card) ->
  # => "Werewolf Ransacker"


tutor.set(name, callback(err, set))

Scrape cards from the set specified by name. For example:

tutor.set 'Homelands', (err, cards) ->
  console.log cards.length
  # => 115
  console.log Object.keys(cards[0]).sort()
  # => [
  #   "converted_mana_cost",
  #   "expansion",
  #   "gatherer_url",
  #   "image_url",
  #   "mana_cost",
  #   "name",
  #   "power",
  #   "rarity",
  #   "subtypes",
  #   "supertypes",
  #   "text",
  #   "toughness",
  #   "types",
  #   "versions"
  # ]


tutor.formats(callback(err, formatNames))

Provides the names of all the game's formats:

tutor.formats (err, formatNames) ->
  console.log formatNames
  # => [
  #   "Classic",
  #   "Commander",
  #   ...
  #   "Vintage",
  #   "Zendikar Block"
  # ]


tutor.sets(callback(err, setNames))

Provides the names of all the game's sets:

tutor.sets (err, setNames) ->
  console.log setNames
  # => [
  #   "Alara Reborn",
  #   "Alliances",
  #   ...
  #   "Worldwake",
  #   "Zendikar"
  # ]


tutor.types(callback(err, types))

Provides the names of all the game's types:

tutor.types (err, types) ->
  console.log types
  # => [
  #   "Artifact",
  #   "Basic",
  #   ...
  #   "Vanguard",
  #   "World"
  # ]


npm install tutor --global will make the tutor command available globally.

$ tutor card 'Demonic Tutor'
Demonic Tutor {1}{B} Search your library for a card and put that card into your hand. Then shuffle your library.

$ tutor card 'Demonic Tutor' --format json | python -mjson.tool | head -n 10
    "community_rating": {
        "rating": 4.714,
        "votes": 229
    "converted_mana_cost": 2,
    "languages": {},
    "legality": {
        "Commander": "Legal",
        "Legacy": "Banned",

$ tutor card 60 --format json | python -mjson.tool | head -n 10
    "artist": "Douglas Schuler",
    "community_rating": {
        "rating": 4.917,
        "votes": 109
    "converted_mana_cost": 2,
    "expansion": "Limited Edition Alpha",
    "languages": {},
    "legality": {

$ tutor set Alliances | head -n 2
Aesthir Glider {3} 2/1 Flying Aesthir Glider can't block.
Agent of Stromgald {R} 1/1 {R}: Add {B} to your mana pool.

Example of using the CLI from other applications:

Link to Wiki

Running the tests

make fixtures
make test
make testcli