SOKU.CLEISTA.CC
Info
Frame dataGuidesModsUptimeForums
Watch
Replays
ReplaysClips
Practice
Practice modeTrials
Packs
Fun
StatsRatingsSavestatesBoxdlePracticeFollow chartPalettesBet historyUsersRandom profileAll
Sign in

API

Frame data and player ratings as JSON. Read-only, no key, CORS open. Please use it instead of fetching the HTML pages, and link back to soku.cleista.cc when you show the data.

Machine-readable: OpenAPI 3.1. For AI agents: /llms.txt. Questions: ping @maristocrat in #hisouten on Discord.

Frame data

GET /api/v1/framedatacharacters, the data build id
GET /api/v1/framedata/{character}moves with startup, recovery, total, damage, advantage; ?kind=normal,skill,spell,system,object|all
GET /api/v1/framedata/{character}/{move}one move in full: frames, advantage, hit data, per hit, cancels, invulnerability and other states, bullets, variants, video; ?level=&charged=1&outcome=whiff
GET /api/v1/framedata/resolve?character=&q=find a move from what a player types: "f5a", "j2b", "6[a]", "alt 236b", "sc209", a card name, "5 card"

Frame ranges are inclusive, frame 1 is the move's first frame. Advantage is measured in the corner against Sanae with no cancel; a value that was not measured is null and unavailable says why.

curl https://soku.cleista.cc/api/v1/framedata/resolve?character=okuu&q=hell%20geyser
curl https://soku.cleista.cc/api/v1/framedata/reimu/5a

Ratings

GET /api/v1/ratingsthe leaderboard: ?character=&min=&status=active|provisional|inactive|all&community=&q=&limit=&offset=
GET /api/v1/ratings/players?names=a,b,cup to 100 players in one request, by in-game name or handle (@handle for a handle only); returns players and notFound
POST /api/v1/ratings/playersthe same from a JSON body {"names": ["a", "b"]} (Content-Type: application/json), up to 1,000 names, body up to 64 KB
GET /api/v1/ratings/export.jsonevery rated player of every status in one file (about 3 MB, brotli or gzip when accepted), rebuilt with the ratings: computedAt, count, players; send If-None-Match
GET /api/v1/ratings/players/{name}one player; for a name more than one person plays under, its default player plus alsoPlayedAs: [{ label, handle? }] (a row with identity: true is such a second person, under its neutral label, with no profile)
GET /api/v1/ratings/bracketswin rate and play share per character by rating bracket
GET /api/v1/ratings/rangesthe same table for a custom range, plus the 20×20 matchup matrix: ?rmin=&rmax= (multiples of 25), gmin=&gmax= (games played), from=&to= (YYYY-MM), close=1 (hide large rating gaps); a matrix game counts only when both players are in range
GET /api/v1/ratings/ranges/playersthe 10 players with the most games in one cell of a range: the same filters plus char= (a table cell) and vs= (a matrix cell)
GET /api/v1/ratings/communitiesthe communities ?community= takes

Only players the public leaderboard shows. Look players up in batches rather than one request each, or take the export for all of them.

Character stats

GET /api/v1/stats/characters?window=7d|30d|allevery character's picks, play share and win rate over the window (30 days by default)
GET /api/v1/stats/characters/{character}/cards?window=card usage in the character's decks: per card the share of decks that run it, average copies, the 1-4 copy counts, and win rate with and without it (null on a small sample)

From the public replays and the decks in their headers; within a set the same player's same deck counts once. Also served without /v1 (/api/stats/characters…). The page: Stats → Characters.

Limits and caching

  • Per address: 120 requests a minute for frame data, 60 for ratings, 120 for character stats. Past that: 429 with Retry-After.
  • Every answer has an ETag; send If-None-Match and get 304 when nothing changed. Frame data changes only when the site is updated (its build changes); ratings are rebuilt at most every 10 minutes, when new games were judged (computedAt).
  • Frame data: cache 5 minutes, or a year with ?build={build} (an old build redirects to the current one). Ratings: 60 seconds. Character stats: 5 minutes.
  • Errors: {"error": "code", "message": "..."}.

Versioning

Within v1 changes only add: new fields, new endpoints, new values. Ignore fields you do not know. Anything that would break a client goes to /api/v2/, and v1 stays up at least six months after that, announced in #hisouten and the changelog.

soku.cleista.ccPrefetchChangelogCreditsPrivacyTermsTouhou Hisoutensoku 12.3 · a fan site, not affiliated with Team Shanghai Alice or Twilight Frontier