API guide

Every card on this site is available as JSON from https://api.rifthunt.com. No key, no signup, no quota: all requests are GET, all responses are application/json, and CORS is open so you can call it straight from a browser app.

Fair use

There is no hard rate limit, which is a request rather than a promise. Keep bursts under roughly 10 requests per second and put a short delay between calls in a loop.

If you want more than a few hundred cards, do not crawl: download the bulk export once and work locally. It is one request instead of a thousand and it is faster for you.

Send a User-Agent that identifies your project. If something misbehaves, that is the difference between getting an email and getting blocked.

Endpoints

RequestReturns
GET /cards/search?q=…Search. Same syntax as the site (see the syntax guide). Takes unique=, order= and dir=, below.
GET /cards/named?exact=…One card by exact name.
GET /cards/:idOne card by its UUID.
GET /setsEvery set, with printing counts.
GET /sets/:codeOne set by code, e.g. ogn.
GET /bulk-dataIndex of the bulk exports.
GET /bulk/cardsThe whole catalogue: 1725 printings, ~1.2 MB.
GET /bulk/pricesTCGplayer prices for 1664 printings. Refreshed daily.
GET /prices/:riftboundIdPrices for one printing.
GET /tags?kind=&q=Community tags, most-used first. kind is function or art; q filters by name.
GET /tags/:kind/:slugOne tag: description, count, creator, and the search that lists its cards.
GET /cards/:id/tagsEvery community tag on one printing: function tags from its card, art tags of its own.
GET /bulk/tagsEvery tagging, one row per (tag, printing). What the site builds from.
GET /cards/:id/rulingsRulings for the card, from Riftbound FAQ. The same list for every printing.
GET /bulk/rulingsEvery ruling, one entry per card. What the site builds from.
GET /healthLiveness check.

Searching

/cards/search takes the same query syntax as the site's search box, documented in full on the syntax guide.

ExampleFinds
/cards/search?q=t:unit d:fury e<=3Cheap Fury units.
/cards/search?q=t:gear p:1Gear costing one rune.
/cards/search?q=s:ogn r:epicEpics in Origins.

Results are one printing per card by default: reprints and variants collapse into a single entry, and the rest are on that card's page. A query matching nothing returns 404, not an empty list.

Response shape

Lists are wrapped in an envelope:

{
  "object": "list",
  "total_cards": 41,
  "has_more": false,
  "next_page": null,
  "data": [ /* card objects */ ]
}

Errors use the same convention, with the HTTP status repeated in the body:

{
  "object": "error",
  "status": 404,
  "code": "not_found",
  "details": "Your query didn't match any cards. Adjust your search terms."
}

The card object

FieldMeaning
objectAlways "card".
idPermanent UUID for this printing.
printing_idThe same value as id, under the name /bulk/cards and /bulk/prices use. Join on this.
oracle_idPermanent UUID shared by every printing of the same card. Also in /bulk/cards.
langLanguage of the text fields. Only "en" today.
namePrinted name, including any variant suffix, e.g. "Annie, Dark Child (Metal)".
oracle_nameThe base name shared by every printing, e.g. "Annie, Dark Child".
typeUnit, Spell, Gear, Legend, Battlefield or Rune.
domainsLowercased array. Also which runes may pay the rune cost.
energyEnergy cost. null when there is none.
powerRune cost: how many runes are recycled to play it. null when there is none.
mightCombat stat on units. null otherwise.
keywordsLowercased array.
tagsLowercased array. Searchable with tag:.
rules_textPlain text. Keeps :rb_*: symbol shortcodes.
flavor_textPlain text, or null.
setSet code, lowercased, e.g. "ogn".
set_nameFull set name.
collector_numberAs printed, zero-padded, e.g. "017". Letter-prefixed (t, r, s) for tokens, runes and special promos.
raritycommon, uncommon, rare, epic, showcase or promo.
artistIllustrator, or null.
variantalternate, overnumbered, signature or null. Metal promos carry it in the name instead.
riftbound_idRiot's own id, e.g. ogn-025-298. Not unique: 52 promos share one.
rifthunt_uriCanonical path for this printing on rifthunt.com.
rulings_uriPath to the card's rulings, /cards/:id/rulings. An empty list when there are none.
imagesObject with small (200 wide), normal (480 wide) and large (744x1039) WebP URLs on images.rifthunt.com, plus back for the five double-sided tokens. Immutable: the ?v= changes when the image does.
tcg_idTCGplayer product id, or null. Build your own link with it if you prefer.
finishesThe finishes this printing is made in: ["normal", "foil"], ["foil"] or ["normal"], the same names as the keys of prices. null when unknown (no TCGplayer product).
purchase_urisObject with tcgplayer (an affiliate link, see below) and cardmarket.
pricesTCGplayer prices per finish, or null if we have none. See below.

One printing or all of them

By default search returns one printing per card: the plain one, without a variant suffix. Add unique=prints to get every printing, which is what you want for prices: a card and its Metal promo are separate products fifty times apart in value.

curl -s "https://api.rifthunt.com/cards/search?q=annie&unique=prints"

/cards/named?exact= accepts either form. The base name returns the plain printing; a printed name such as Annie, Dark Child (Metal) returns that printing.

Sorting

unique= is cards (default), prints, or art for one printing per illustration. order= is one of name (default), released, set, number, usd, rarity, energy, power, might or artist. dir= is asc, desc, or auto (default): newest and priciest first, everything else A to Z. Cards with no value for the sort key come last either way. next_page carries all three.

curl -s "https://api.rifthunt.com/cards/search?q=t:legend&unique=prints&order=usd"

Bulk data

/bulk/cards returns all 1725 printings in one response, about 1.2 MB. It is the same file the site itself builds from, so it will never disagree with what you see here. Fetch it once a day at most, since card data only changes when a set does.

curl -s https://api.rifthunt.com/bulk/cards > cards.json

Each printing there carries the same ids as the card object, under the same names: printing_id (the card object's id) and oracle_id, so you can group printings into cards, or match one to an API result, without a second request. It also carries finishes, as on the card object. The other fields are camelCase, in the shape the site builds from.

Two fields there are deprecated and will be removed soon. id is our ingest's source record id (like ogn-001-298), not the card object's id; use printing_id. oracleId is the same value as oracle_id, kept for now for backwards compatibility; use oracle_id.

Community tags

Cards carry two kinds of community tag: function tags on the card (what it does, searchable as otag:removal) and art tags on a printing (what the picture shows, art:dragon). Reading them needs no account. Adding them does: sign in on the tagger, which uses the same API with a bearer token. Tags can change at any time, so cache them for minutes, not days.

curl -s "https://api.rifthunt.com/cards/search?q=otag:removal"

Rulings

Rulings come from Riftbound FAQ, Christian “Near” Ivicevic's unofficial rulings site, under CC BY-SA 4.0: 167 rulings on 71 cards right now. Every response names the source, the upstream commit and the licence; if you republish them, keep the attribution. Each ruling is a question and an answer, the answer as plain text (comment) and as HTML that uses the same :rb_*: shortcodes and [Keyword] tokens as rules_text. Rulings belong to the card, so every printing returns the same list. A wrong ruling is reported on the FAQ's GitHub, not to us.

curl -s https://api.rifthunt.com/bulk/rulings > rulings.json

Prices

Prices are a separate export, because they change on a completely different schedule to the catalogue. /bulk/prices returns 1688 rows, one per printing with a TCGplayer product, of which 1664 have a current market price. The rest are listed products with nothing for sale right now, so every field is null. Refreshed daily.

curl -s https://api.rifthunt.com/bulk/prices > prices.json

Normal and foil are reported separately, under finishes, because TCGplayer lists them as separate products and they diverge by orders of magnitude: the same card can be seven cents normal and $185 foil.

Every row reports both finishes, including ones the card is never made in. Check a printing's finishes to tell them apart: a finish listed there with null prices exists but has no listings, and a finish missing from it does not exist (most rares and up are foil only).

Each row also carries a purchaseUri, an affiliate deep link to that exact printing on TCGplayer. See affiliate links.

Each row carries the printing's printing_id, the same value as in /bulk/cards and on the card object, so that is the simplest way to join a price to its card.

Rows are also keyed by riftboundId, collector and slug together, never by riftboundId alone. The 52 “(Metal)” promos share an id with their base printing and are separate products at very different prices, so keying on the id by itself will silently give you the wrong one.

Affiliate links

The purchase_uris.tcgplayer value on every card, and the purchaseUri on every price row, are affiliate links. RiftHunt earns a commission when someone buys through one. They are how this API stays free and keyless, and you are welcome to use them in your own app.

Caching

Responses are cached at Cloudflare's edge, so most requests never reach the origin. Respect these and you will rarely notice a limit exists.

EndpointBrowserEdge
/cards/search60s browser1h edge, 24h stale-while-revalidate
/cards/:id, /cards/named1h browser24h edge
/sets, /sets/:code1h browser24h edge
/bulk/cards1h browser24h edge, 7d stale-while-revalidate
/bulk/rulings, /cards/:id/rulings1h browser24h edge, 7d stale-while-revalidate
/bulk/prices, /prices/:id5–10m browser15–30m edge, 24h stale-while-revalidate
/tags, /cards/:id/tags, and any search using otag: or art:30s browser1m edge, 5m stale-while-revalidate

Examples

# shell
curl -s "https://api.rifthunt.com/cards/search?q=t:gear%20p:1"

# PowerShell: note curl is an alias for Invoke-WebRequest, so use the native cmdlet
Invoke-RestMethod "https://api.rifthunt.com/sets" | Select-Object -ExpandProperty data

# browser / Node
const res = await fetch("https://api.rifthunt.com/cards/named?exact=Blind Fury");
const card = await res.json();
console.log(card.energy, card.power, card.domains);

Terms

Free for any use, commercial included. RiftHunt is unofficial Fan Content under Riot Games' Legal Jibber Jabber policy: card names, text and images are Riot's, and your project inherits the same terms. A link back is appreciated but not required.