Search Specification

Exactly what each search box does, and why a player you know exists can still be missing from a name search.

Tag search always hits the live API

Searching by tag does not touch the local index at all. The box normalises what you typed and sends you straight to the profile route, which asks the official Brawl Stars API for that account. Any tag that exists in the game resolves, whether or not this site has ever seen it before — and the profile is written into the local index as a side effect, which is how name search gets a corpus.

Normalisation, in order:

  • Surrounding whitespace is trimmed and the whole tag is upper-cased, so tag search is case-insensitive.
  • A leading # is stripped.
  • O becomes the digit 0 and I becomes the digit 1 — those letters do not exist in Supercell tags, so typing them is treated as the obvious mistake rather than as an error.
  • Anything that is not a digit or a letter is removed.

The result must then be 3 to 14 characters long and use only the tag alphabet 0289PYLQGRJCUV. Anything else is rejected in the form before a request is made. Club tag search works identically.

A tag the API answers with 404 shows a not-found page, and the background refresh queue drops that tag from the local index the next time it comes up — so a deleted account stops appearing in name search and stops consuming refresh budget.

Name search only covers the local index

The official API has no name lookup of any kind. Name search therefore runs entirely against this instance’s own SQLite index of players and clubs it has already seen. If nobody has ever opened a given player here and that player has never appeared on one of the leaderboards this instance bootstrapped from, a name search cannot find them.

Players who have never been viewed here are not indexed for name search. Search by tag once and they become searchable.

How a player search query is matched:

  • The query is trimmed and lower-cased, and compared against a lower-cased copy of the name. Matching is therefore case-insensitive; it is not accent- or width-insensitive, so é and e are different characters.
  • An empty query returns nothing — it is not treated as “list everyone”.
  • By default a query is matched two ways at once, and the results are merged:
    • From the start of the name. fang finds Fangirl, and toxicfang finds ToxicFang. This half searches every indexed player, however few trophies they have, and it reads at most 2,000 names.
    • Anywhere inside the name, but only across the 5,000 players with the most trophies. This is what finds a decorated name where the part you remember sits in the middle — a clan tag, a bracket or a run of symbols in front of the word you typed.
  • Those two numbers are the honest edge of this search, so here is where it bites. Below the top 5,000 — currently everyone under 170,378 trophies, which is 99.91% of the 5,595,083 players indexed — a player is found only if what you typed is the beginning of their name. Above that line, matching anywhere in the name still works exactly as it always did. The start-of-name half does search every one of those 5,595,083 rows — but only from the front.
  • Typing more characters does not fix a miss. Typing characters further left does. Extending a fragment to the right never helps, because the start-of-name half only ever compares against the front of the name. Measured on a real account called XxBladedFrostxX (20,045 trophies, below the line): bladedfrostxx — thirteen of its fifteen characters — finds nothing, while xxblade finds it. For 銀💙Kurihana迪熊🧸 you have to reproduce the and the emoji: kurihana and 💙kuriha both miss, 銀💙kuriha hits. 527,620 of the indexed names — 9.4% — begin with a symbol or an emoji like that.
  • How many results you get changed too, and an earlier version of this page was wrong about it. It said a query of one or two characters returned exactly what it used to. Re-measured across 29 queries — ASCII and non-ASCII, one character through eight, common, rare and one matching nothing at all — 25 of them filled the old 100-row page, and of those only a and ar come back unchanged. Those two were the entire evidence base for the sentence that has now been removed. Of the old 100 results, what survives is 100 for a and ar, 85 for q, 50 for 8, 10–26 for a single non-Latin character ( 10, 17, ж 22, 26), 24 for bra, 18 for brawl, 5 for zzq.
  • The places this frees up are filled with start-of-name matches the old ranking pushed off the page — every single replacement row, across all 29 queries, was one. But they only fill if enough names actually start with what you typed. A search returns at most the names starting with your query (up to 2,000) plus the top-5,000 players whose name contains it, so when fewer than about a hundred names share your beginning the page is simply shorter than it used to be: brawlers returns 55 rows where it used to return 100, 0o returns 56, and zzq returns 6 — there are 105 indexed players with zzq somewhere in their name, and this search reaches six of them. A term distinctive enough that every account carrying it already starts with it is unaffected: toxicfan and фанг return exactly what they always did.
  • What did not change is the top of the table. Across all 29 queries the highest-trophy result that was lost had 170,108 trophies — below the 170,378 floor of the match-anywhere window. Every dropped row without exception was a mid-name match on a player under that line.
  • %, _ and \ in your query are escaped before the query runs, so they match themselves instead of acting as wildcards. There is no wildcard syntax exposed to the user.
  • Results are ordered by current trophies, highest first, then cut to the result limit.

Club name search is trimmed, lower-cased, wildcard-escaped and ordered by club trophies descending in the same way, but it is a plain substring match over every club, with no cap and no split into two halves. It can afford to be: there are about 1,400 clubs indexed against more than five million players, so reading the whole club table costs well under a millisecond whatever you type. Clubs have no exact-match or previous-names option. If what you typed is itself a valid tag, both search pages also offer a direct link to that tag.

The two search options

The two checkboxes under the player name box refine how a name is matched. Both are available to everyone — no account is needed, and they work the same whether you tick them on the page or set exact=1 and prev=1 on the URL yourself.

Search only exact name matches

Replaces both halves of the default match with a single whole-name equality match. Still case-insensitive: toxicfang matches a player called ToxicFang, but fang no longer matches anything unless someone is named exactly that. Useful when a common word buries the account you want — and it is the one mode with no cap of any kind behind it, because an equality match is a single index seek however many players there are.

Include previous names

Also searches the name-history table — every name this instance has observed an account using — and adds any account whose old name matches and that is not already in the results. The list of current-name matches is built first, the history matches are appended after it, and the whole list is then cut to the limit, so a query with many current-name matches may leave no room for history matches. Where a hit came from an old name, the search results show that old name next to the account.

Old names are matched from the start of the name only. A player who used to be called ToxicFang is found by typing toxic, not fang. Current names get a match-anywhere pass as well, but only across the top 5,000 by trophies; name history gets no match-anywhere pass at all, at any trophy level. Combine this box with the exact-match box above and the history lookup becomes a whole-name match instead.

The reason is cost, not policy. There are over five million recorded names, a match-anywhere search cannot use the index on that table and has to read every row, and this option needs no account — so it has to stay something the server can answer without making everyone else wait. That is not an aspiration: the server is one process with one synchronous database connection, so a slow search is not slow for the person who typed it, it is slow for every other visitor being served at that moment.

A single search reads at most 2,000 history rows, taken in alphabetical order. That cap is reached more often than an earlier version of this page claimed: it said a query of three characters or more was normally well inside it, and that is simply not true of real names. Counted on this instance’s own index, every one of the 200 most common three-character beginnings has more than 2,000 names behind it, and the most common of them — bra — has 88,333, forty-four times the cap. What the cap really means is narrower and more useful: when more names share your query than the cap allows, the ones you are shown are drawn from the alphabetically first 2,000 of them, not from all of them. Typing more characters is what makes that stop mattering.

Name history only goes back as far as this instance does. It is built by noticing that a tag we already had is now reporting a different name, so a rename that happened before the account was first indexed here is invisible.

How the index gets populated

These are the paths that put a player or club into the local index.

  1. Page views. Opening a player or club page fetches the profile and indexes it: the account row itself, a name-history row, a club-history row, an hourly progression snapshot, the equipped skins, and any ranked tier label the profile carries. This is the main way the corpus grows, and it means a tag becomes name-searchable the first time anyone looks it up here.
  2. The leaderboard bootstrap. On the first start with an API token configured, the app walks the official player and club leaderboards for global, TW, JP, KR, US, BR, DE and MX and writes what those rows carry — tag, name, trophies, icon, club name — so that a brand new instance is not returning nothing for every query. These rows are deliberately stored as summaries with an empty profile payload and a back-dated update time: they are searchable by name immediately, and the background refresh queue fills in the full profile later. The bootstrap runs once; the flag that records it lives in the local database.
  3. The refresh queue. Once a tag is indexed it is re-polled on a schedule, which is how a renamed account’s new name and its name history stay current without anyone visiting the page.

With no API token configured the site runs in demo mode and seeds the index with deterministic synthetic players and clubs so the search boxes do something. Those rows are recorded as synthetic and are deleted in full the moment a real token appears, so they can never leak into live results.

Limits

SettingValue
Player name search, default result limit50
Player name search, hard cap200
Requested by the player search page100
Current names read per search, start-of-name half2,000
Players searched by the match-anywhere half, by trophy ranktop 5,000
Previous-name history rows read per search2,000
Club name search, default result limit50
Club name search, hard cap200
Requested by the club search page100
Tag length accepted3–14
Player profile reused from cache for3 min
Club profile reused from cache for10 min

There is no pagination on name search: results beyond the limit are simply not returned. Narrow the query, or use the exact-match option, to reach an account that a broad query buries.

What a search costs

Every cap on this page exists for one reason, so it is worth stating the number it buys. These are whole-request timings — the complete page request an anonymous visitor makes, not one query inside it — measured against the live index of 5,321,046 players and 5,154,798 recorded names.

Before the caps, the default search took as long as the word you typed was rare, because it walked the trophy table from the top until it had collected enough matches. A common query finished instantly; a rare one read every row. Measured:

QueryBeforeNow
a, one common character0.1 ms1.0 ms
bra, three common characters106.8 ms6.4 ms
zzq, three rare characters1,821.9 ms2.2 ms
toxicfan, a rare name1,666.8 ms1.9 ms

The worst case now is not a rare query at all — the caps made rare queries the cheap ones. It is a single character with both refinements ticked, which has to touch a fresh part of three different indexes: 44 ms typical, 156 ms worst observed, swept over 171 different first characters covering Latin, Cyrillic, Greek, CJK, kana, symbols and emoji. Repeated searches settle at 2–8 ms.

What that protects is other people. With one visitor typing a rare name over and over, an ordinary player page used to take 1,583 ms to answer instead of its usual fraction of a millisecond, and only 7 of the ~400 page requests due in ten seconds completed at all. With the caps in place the same test serves 321–374 of them, at a median of 1 ms.

Technology covers the refresh queue and the rest of the pipeline in more detail.

Search Specification · BrawlPeek