Query syntax
The search language: tokens, colour operators, boolean logic, and the places it differs from Scryfall.
Search follows Scryfall's conventions closely enough that most Scryfall queries work unchanged. This page lists what our parser and executor actually support. Differences from Scryfall are called out where they exist.
Terms are ANDed by default. t:creature ci<=wu means both, not either.
Tokens
| Token | Aliases | Matches |
|---|---|---|
| bare word | Card name contains the word | |
name: | Card name contains the value | |
t: | type: | Type line contains the value |
o: | oracle: | Oracle text contains the value |
kw: | keyword: | Has that keyword ability |
c: | color: | Card colours (see below) |
ci: | id:, identity: | Colour identity (see below) |
cmc: | mv: | Mana value, with = < > <= >= |
m: | mana: | Mana cost, exact string |
r: | rarity: | common, uncommon, rare, mythic, special |
f: | format: | Legal in that format |
set: | e:, edition: | Printed in that set, by set code |
tag: | Carries that semantic tag | |
price: | Cheapest USD price, with = < > <= >= | |
- | Negates the term or group that follows | |
OR | Either side; AND is accepted and is a no-op | |
( ) | Grouping |
OR and AND are case-insensitive and are never treated as name text. To
search for a name containing one of them, quote it: name:"fire and ice".
Values with spaces must be quoted: o:"draw a card".
Details worth knowing
o: searches both faces. It matches against a generated column that
concatenates every face, so a transform, modal DFC, split, adventure, flip or
meld card matches on text printed on its back half or second half. Searching the
front face alone is not currently expressible.
t: also matches the subtype list. A positive t: matches the type line as
a substring or the parsed subtype array, so t:wolf still finds Werewolf
cards. A negated -t: checks the type line only.
m: is exact, not a substring. m:{G}{G} finds cards whose mana cost is
exactly that. m:{G} does not find {1}{G} cards.
set: matches any printing. Cards carry the full list of sets they appear
in, so set:cmm finds every card printed in that set, including reprints.
price: is the cheapest current USD retail price across a card's
normal-finish printings, in dollars. It is TCGplayer-sourced and refreshed
daily. See card prices.
tag: values are a fixed vocabulary. Unknown tags are rejected with
suggestions. The full list is searchable in the app at
/search/tags, and
taxonomy and tagging explains how a card gets one.
Colours
The part most often gotten wrong. Colour (c:) is what is printed on the card.
Colour identity (ci:) is what determines Commander legality, and includes
symbols in rules text.
| Query | Means |
|---|---|
c>=u | Contains blue. May have other colours too |
c>u | Contains blue and at least one other colour |
c=u | Exactly blue, nothing else |
c<=u | A subset of blue: mono-blue or colourless |
c<u | A strict subset of blue: colourless only |
ci>=u | Identity contains blue |
ci>u | Identity contains blue and at least one other colour |
ci=u | Identity is exactly blue |
ci<=u | Identity fits inside blue: legal in a mono-blue deck |
ci<u | A strict subset of blue: colourless identity |
Colour letters are W U B R G. Combine them without separators: ci<=wu.
c:u and ci:u are accepted for Scryfall compatibility, and they mean
different operators: bare c: means >= and bare ci: means <=. That
asymmetry is Scryfall's and we match it. Write the operator you mean.
Two things cannot be expressed inside an OR group: exact mana costs (m:) and
strict colour subsets (c<, ci<, and the negated forms -c>, -ci>). A
query using them inside an OR fails with an error telling you to split it into
separate searches. All of them work outside an OR.
Boolean logic
t:creature t:legendary both (AND is the default)
t:instant OR t:sorcery either
-t:creature not a creature
-(t:creature OR t:artifact) neither creature nor artifact
(t:creature ci<=u) OR (t:artifact ci<=r) nested groupsNegating a group distributes as you would expect: -(A OR B) is "not A and
not B".
Parentheses are required around an OR whenever it sits beside other terms.
t:creature (r:rare OR r:mythic) and t:creature r:rare OR r:mythic are
different queries.
field:(group) does not exist
t:(instant OR sorcery) is invalid here, and also invalid on Scryfall. Every
term carries its own prefix:
(t:instant OR t:sorcery)The validator rejects the grouped form with a hint.
Examples
| Query | Finds |
|---|---|
t:legendary t:creature ci=u | Mono-blue commanders |
t:legendary t:creature ci<=wu | Commanders for an Azorius deck |
ci<=u cmc<=3 | Cheap cards legal in a mono-blue deck |
o:"counter target spell" t:instant | Counterspells |
(kw:Flying OR kw:Menace) t:creature | Evasive creatures, by keyword |
tag:removal ci<=b cmc<=2 | Cheap black removal, by semantic tag |
set:one r:mythic | Mythics from Phyrexia: All Will Be One |
-(t:creature OR t:land) cmc>=6 | Expensive non-creature, non-land spells |
t:creature price<=1 | Creatures under a dollar |
Where this sits
Queries are parsed into an intermediate representation, then compiled to SQL.
The IR and its serializer live in packages/core/src/query/, and the compiler
in apps/web/lib/search/executor.ts.
Anatomy of a search walks through both.
Magic's own terms are defined in the app, with rule citations, at
/search/concepts. These pages link to those definitions
instead of restating them.