18-LAB / Documentation
State schema
This reference uses JSON names from the published Rust model, including serde renames. integer is a JSON number whose model type is integral; ordinary number is floating-point. Objects marked omitted are absent when unavailable, not necessarily null. Nullable fields explicitly retain null. Large score/ID numbers follow JavaScript-number representation; do not assume arbitrary-precision integers.
The fields vary with client, ruleset, map readiness, and available process data. A stream can return an error document instead of this tree; HTTP readiness is 500 {"error":"osu is not ready/running"}.
Regular v2
GET /json/v2 and /websocket/v2 publish this document. /websocket/v2/subscribe selects pointers into it. The table recursively expands reused Rust types so each JSON path is explicit; [] denotes array elements.
| Field | JSON type | Availability / compatibility |
|---|---|---|
game |
Game |
|
game.focused |
boolean |
Omitted when unavailable. |
game.paused |
boolean |
|
client |
string |
|
server |
string |
|
state |
NumberName |
|
state.number |
integer |
Omitted when unavailable. |
state.name |
string |
|
session |
Session |
|
session.playTime |
number |
|
session.playCount |
integer |
|
rankedPlay |
RankedPlay |
Omitted when unavailable. |
rankedPlay.stage |
integer (0–9) |
|
rankedPlay.currentRound |
integer |
|
rankedPlay.starRating |
number |
|
rankedPlay.damageMultiplier |
number |
|
rankedPlay.activeUserId |
integer |
|
rankedPlay.winningUserId |
integer |
|
rankedPlay.users |
RankedPlayUserInfo[] |
|
rankedPlay.users[].id |
integer |
|
rankedPlay.users[].rating |
number |
|
rankedPlay.users[].life |
number |
|
rankedPlay.users[].roundsWon |
integer |
|
rankedPlay.users[].damageMultiplier |
number |
|
settings |
Settings |
|
settings.interfaceVisible |
boolean |
|
settings.replayUIVisible |
boolean |
|
settings.chatVisibilityStatus |
NumberName |
|
settings.chatVisibilityStatus.number |
integer |
Omitted when unavailable. |
settings.chatVisibilityStatus.name |
string |
|
settings.leaderboard |
LeaderboardSettings |
|
settings.leaderboard.visible |
boolean |
|
settings.leaderboard.type |
NumberName |
|
settings.leaderboard.type.number |
integer |
Omitted when unavailable. |
settings.leaderboard.type.name |
string |
|
settings.progressBar |
NumberName |
|
settings.progressBar.number |
integer |
Omitted when unavailable. |
settings.progressBar.name |
string |
|
settings.bassDensity |
number |
|
settings.resolution |
Resolution |
|
settings.resolution.fullscreen |
boolean |
|
settings.resolution.width |
integer |
|
settings.resolution.height |
integer |
|
settings.resolution.widthFullscreen |
integer |
|
settings.resolution.heightFullscreen |
integer |
|
settings.client |
Client |
|
settings.client.updateAvailable |
boolean |
|
settings.client.branch |
integer |
|
settings.client.version |
string |
|
settings.scoreMeter |
ScoreMeter |
|
settings.scoreMeter.type |
NumberName |
|
settings.scoreMeter.type.number |
integer |
Omitted when unavailable. |
settings.scoreMeter.type.name |
string |
|
settings.scoreMeter.size |
number |
|
settings.cursor |
Cursor |
|
settings.cursor.useSkinCursor |
boolean |
|
settings.cursor.autoSize |
boolean |
|
settings.cursor.size |
number |
|
settings.cursor.menuSize |
number |
|
settings.mouse |
Mouse |
|
settings.mouse.rawInput |
boolean |
|
settings.mouse.disableButtons |
boolean |
|
settings.mouse.disableWheel |
boolean |
|
settings.mouse.sensitivity |
number |
|
settings.tablet |
Tablet |
|
settings.tablet.enabled |
boolean |
|
settings.tablet.x |
number |
|
settings.tablet.y |
number |
|
settings.tablet.width |
number |
|
settings.tablet.height |
number |
|
settings.tablet.rotation |
number |
|
settings.tablet.pressureThreshold |
number |
|
settings.mania |
Mania |
|
settings.mania.speedBPMScale |
boolean |
|
settings.mania.usePerBeatmapSpeedScale |
boolean |
|
settings.mania.scrollSpeed |
integer |
|
settings.mania.scrollDirection |
ScrollDirection |
|
settings.mania.scrollDirection.number |
integer |
|
settings.mania.scrollDirection.name |
string |
Omitted when unavailable. |
settings.sort |
NumberName |
|
settings.sort.number |
integer |
Omitted when unavailable. |
settings.sort.name |
string |
|
settings.group |
NumberName |
|
settings.group.number |
integer |
Omitted when unavailable. |
settings.group.name |
string |
|
settings.skin |
Skin |
|
settings.skin.useDefaultSkinInEditor |
boolean |
|
settings.skin.ignoreBeatmapSkins |
boolean |
|
settings.skin.tintSliderBall |
boolean |
|
settings.skin.useTaikoSkin |
boolean |
|
settings.skin.name |
string |
|
settings.mode |
NumberName |
|
settings.mode.number |
integer |
Omitted when unavailable. |
settings.mode.name |
string |
|
settings.audio |
Audio |
|
settings.audio.ignoreBeatmapSounds |
boolean |
|
settings.audio.useSkinSamples |
boolean |
|
settings.audio.volume |
Volume |
|
settings.audio.volume.masterInactive |
number |
|
settings.audio.volume.master |
number |
|
settings.audio.volume.music |
number |
|
settings.audio.volume.effect |
number |
|
settings.audio.offset |
Offset |
|
settings.audio.offset.universal |
number |
|
settings.background |
Background |
|
settings.background.storyboard |
boolean |
|
settings.background.video |
boolean |
|
settings.background.blur |
number |
|
settings.background.dim |
number |
|
settings.keybinds |
Keybinds |
|
settings.keybinds.osu |
KeybindsOsu |
|
settings.keybinds.osu.k1 |
string |
|
settings.keybinds.osu.k2 |
string |
|
settings.keybinds.osu.smokeKey |
string |
|
settings.keybinds.fruits |
KeybindsFruits |
|
settings.keybinds.fruits.k1 |
string |
|
settings.keybinds.fruits.k2 |
string |
|
settings.keybinds.fruits.Dash |
string |
|
settings.keybinds.taiko |
KeybindsTaiko |
|
settings.keybinds.taiko.innerLeft |
string |
|
settings.keybinds.taiko.innerRight |
string |
|
settings.keybinds.taiko.outerLeft |
string |
|
settings.keybinds.taiko.outerRight |
string |
|
settings.keybinds.quickRetry |
string |
|
profile |
Profile |
|
profile.userStatus |
NumberName |
Omitted when unavailable. |
profile.userStatus.number |
integer |
Omitted when unavailable. |
profile.userStatus.name |
string |
|
profile.banchoStatus |
NumberName |
Omitted when unavailable. |
profile.banchoStatus.number |
integer |
Omitted when unavailable. |
profile.banchoStatus.name |
string |
|
profile.id |
integer |
Omitted when unavailable. |
profile.name |
string |
Omitted when unavailable. |
profile.mode |
NumberName |
Omitted when unavailable. |
profile.mode.number |
integer |
Omitted when unavailable. |
profile.mode.name |
string |
|
profile.rankedScore |
number |
Omitted when unavailable. |
profile.level |
number |
Omitted when unavailable. |
profile.accuracy |
number |
Omitted when unavailable. |
profile.pp |
number |
Omitted when unavailable. |
profile.playCount |
integer |
Omitted when unavailable. |
profile.globalRank |
integer |
Omitted when unavailable. |
profile.countryCode |
NumberName |
Omitted when unavailable. |
profile.countryCode.number |
integer |
Omitted when unavailable. |
profile.countryCode.name |
string |
|
profile.backgroundColour |
string |
Omitted when unavailable. |
profile.matchmaking |
MatchmakingStats or null |
Omitted when unavailable. |
profile.matchmaking.rating |
number |
|
profile.matchmaking.rank |
integer or null |
|
profile.matchmaking.plays |
integer |
|
profile.matchmaking.wins |
integer |
|
profile.matchmaking.isProvisional |
boolean |
|
beatmap |
Beatmap |
|
beatmap.isKiai |
boolean |
|
beatmap.isBreak |
boolean |
|
beatmap.isConvert |
boolean |
|
beatmap.time |
BeatmapTime |
|
beatmap.time.live |
number |
|
beatmap.time.firstObject |
integer |
|
beatmap.time.lastObject |
number |
|
beatmap.time.mp3Length |
number |
Omitted when unavailable. |
beatmap.status |
BeatmapStatus |
|
beatmap.status.number |
number |
Omitted when unavailable. |
beatmap.status.name |
string |
|
beatmap.checksum |
string |
Omitted when unavailable. |
beatmap.id |
integer |
Omitted when unavailable. |
beatmap.set |
integer |
Omitted when unavailable. |
beatmap.mode |
NumberName |
|
beatmap.mode.number |
integer |
Omitted when unavailable. |
beatmap.mode.name |
string |
|
beatmap.artist |
string |
Omitted when unavailable. |
beatmap.artistUnicode |
string |
Omitted when unavailable. |
beatmap.title |
string |
Omitted when unavailable. |
beatmap.titleUnicode |
string |
Omitted when unavailable. |
beatmap.mapper |
string |
Omitted when unavailable. |
beatmap.version |
string |
Omitted when unavailable. |
beatmap.source |
string |
|
beatmap.tags |
string |
|
beatmap.stats |
Stats |
|
beatmap.stats.stars |
Stars |
|
beatmap.stats.stars.live |
number |
|
beatmap.stats.stars.aim |
number |
Omitted when unavailable. |
beatmap.stats.stars.speed |
number |
Omitted when unavailable. |
beatmap.stats.stars.flashlight |
number |
Omitted when unavailable. |
beatmap.stats.stars.sliderFactor |
number |
Omitted when unavailable. |
beatmap.stats.stars.stamina |
number |
Omitted when unavailable. |
beatmap.stats.stars.rhythm |
number |
Omitted when unavailable. |
beatmap.stats.stars.color |
number |
Omitted when unavailable. |
beatmap.stats.stars.reading |
number |
Omitted when unavailable. |
beatmap.stats.stars.hitWindow |
number |
Omitted when unavailable. |
beatmap.stats.stars.total |
number |
|
beatmap.stats.ar |
Ar |
|
beatmap.stats.ar.original |
number |
|
beatmap.stats.ar.converted |
number |
|
beatmap.stats.cs |
Cs |
|
beatmap.stats.cs.original |
number |
|
beatmap.stats.cs.converted |
number |
|
beatmap.stats.od |
Od |
|
beatmap.stats.od.original |
number |
|
beatmap.stats.od.converted |
number |
|
beatmap.stats.hp |
Hp |
|
beatmap.stats.hp.original |
number |
|
beatmap.stats.hp.converted |
number |
|
beatmap.stats.bpm |
Bpm |
|
beatmap.stats.bpm.realtime |
number |
|
beatmap.stats.bpm.common |
number |
|
beatmap.stats.bpm.min |
number |
|
beatmap.stats.bpm.max |
number |
|
beatmap.stats.objects |
Objects |
|
beatmap.stats.objects.circles |
integer |
|
beatmap.stats.objects.sliders |
integer |
|
beatmap.stats.objects.spinners |
integer |
|
beatmap.stats.objects.holds |
integer |
|
beatmap.stats.objects.total |
integer |
|
beatmap.stats.hitWindow |
HitWindow |
Absolute timing boundaries in milliseconds after clock rate. |
beatmap.stats.hitWindow.miss |
number |
Omitted when unavailable. |
beatmap.stats.hitWindow.meh |
number |
Omitted when unavailable. |
beatmap.stats.hitWindow.ok |
number |
Omitted when unavailable. |
beatmap.stats.hitWindow.good |
number |
Omitted when unavailable. |
beatmap.stats.hitWindow.great |
number |
Omitted when unavailable. |
beatmap.stats.hitWindow.perfect |
number |
Omitted when unavailable. |
beatmap.stats.maxCombo |
integer |
|
play |
Play |
|
play.failed |
boolean |
|
play.playerName |
string |
|
play.mode |
NumberName |
|
play.mode.number |
integer |
Omitted when unavailable. |
play.mode.name |
string |
|
play.score |
number |
|
play.accuracy |
number |
|
play.healthBar |
HealthBar |
|
play.healthBar.normal |
number |
|
play.healthBar.smooth |
number |
|
play.hits |
PlayHits |
|
play.hits.0 |
integer |
|
play.hits.50 |
integer |
|
play.hits.100 |
integer |
|
play.hits.300 |
integer |
|
play.hits.geki |
integer |
|
play.hits.katu |
integer |
|
play.hits.sliderBreaks |
integer |
|
play.hits.sliderEndHits |
integer |
|
play.hits.smallTickHits |
integer |
|
play.hits.largeTickHits |
integer |
|
play.hitErrorArray |
number[] |
|
play.pressHitErrors |
number[] |
vosu only |
play.releaseHitErrors |
number[] |
vosu only |
play.hitOffsets |
number[] |
vosu only Added in vosu 1.1.0. Omitted unless ENABLE_HIT_OFFSETS = true. Flat stride-3 [x, y, error, …]; empty outside standard gameplay when enabled. |
play.keyHitErrors |
KeyHitErrors |
vosu only Added in vosu 1.1.0. Omitted unless ENABLE_MANIA_KEY_HIT_ERRORS = true. |
play.keyHitErrors.press |
number[][] |
Timing errors in ms, indexed by zero-based displayed mania lane. |
play.keyHitErrors.release |
number[][] |
Hold-release timing errors in ms, indexed by zero-based displayed mania lane. |
play.catcher |
Catcher |
vosu only Added in vosu 1.1.0. Omitted outside catch gameplay or without native evidence. |
play.catcher.x |
number |
Stored playfield X in osu! pixels (0–512), not screen space. |
play.catcher.dashing |
boolean |
Ordinary dash, not hyperdash. |
play.combo |
Combo |
|
play.combo.current |
integer |
|
play.combo.max |
integer |
|
play.mods |
CalculateMods |
|
play.mods.checksum |
string |
|
play.mods.number |
integer |
|
play.mods.name |
string |
|
play.mods.array |
Mod[] |
|
play.mods.array[].acronym |
string |
|
play.mods.array[].settings |
JSON object |
Omitted when unavailable. |
play.mods.rate |
number |
|
play.rank |
Rank |
|
play.rank.current |
string |
|
play.rank.maxThisPlay |
string |
|
play.pp |
Pp |
|
play.pp.current |
number |
|
play.pp.fc |
number |
|
play.pp.maxAchieved |
number |
|
play.pp.maxAchievable |
number |
|
play.pp.detailed |
DetailedPp |
|
play.pp.detailed.current |
DetailedPpAttributes |
|
play.pp.detailed.current.aim |
number |
|
play.pp.detailed.current.speed |
number |
|
play.pp.detailed.current.accuracy |
number |
|
play.pp.detailed.current.difficulty |
number |
|
play.pp.detailed.current.flashlight |
number |
|
play.pp.detailed.current.total |
number |
|
play.pp.detailed.fc |
DetailedPpAttributes |
|
play.pp.detailed.fc.aim |
number |
|
play.pp.detailed.fc.speed |
number |
|
play.pp.detailed.fc.accuracy |
number |
|
play.pp.detailed.fc.difficulty |
number |
|
play.pp.detailed.fc.flashlight |
number |
|
play.pp.detailed.fc.total |
number |
|
play.unstableRate |
number |
|
keys |
Keys |
vosu only |
keys.k1 |
KeyOverlayButton |
vosu only |
keys.k1.isPressed |
boolean |
vosu only |
keys.k1.count |
integer |
vosu only |
keys.k2 |
KeyOverlayButton |
vosu only |
keys.k2.isPressed |
boolean |
vosu only |
keys.k2.count |
integer |
vosu only |
keys.m1 |
KeyOverlayButton |
vosu only |
keys.m1.isPressed |
boolean |
vosu only |
keys.m1.count |
integer |
vosu only |
keys.m2 |
KeyOverlayButton |
vosu only |
keys.m2.isPressed |
boolean |
vosu only |
keys.m2.count |
integer |
vosu only |
keys.all |
Keypress[] |
vosu only |
keys.all[].name |
string |
vosu only |
keys.all[].isPressed |
boolean |
vosu only |
keys.all[].count |
integer |
vosu only |
keys.all[].pressedAt |
number or null |
Nullable gameplay time in ms: stable replay-frame edge, lazer sampled edge. vosu only |
keys.all[].releasedAt |
number or null |
Nullable gameplay time in ms: stable replay-frame edge, lazer sampled edge. vosu only |
leaderboard |
Leaderboard[] |
|
leaderboard[].isFailed |
boolean |
|
leaderboard[].position |
integer |
|
leaderboard[].team |
integer |
|
leaderboard[].id |
integer |
|
leaderboard[].name |
string |
|
leaderboard[].score |
number |
|
leaderboard[].accuracy |
number |
|
leaderboard[].hits |
LeaderboardHits |
|
leaderboard[].hits.0 |
integer |
|
leaderboard[].hits.50 |
integer |
|
leaderboard[].hits.100 |
integer |
|
leaderboard[].hits.300 |
integer |
|
leaderboard[].hits.geki |
integer |
|
leaderboard[].hits.katu |
integer |
|
leaderboard[].combo |
Combo |
|
leaderboard[].combo.current |
integer |
|
leaderboard[].combo.max |
integer |
|
leaderboard[].mods |
CalculateMods |
|
leaderboard[].mods.checksum |
string |
|
leaderboard[].mods.number |
integer |
|
leaderboard[].mods.name |
string |
|
leaderboard[].mods.array |
Mod[] |
|
leaderboard[].mods.array[].acronym |
string |
|
leaderboard[].mods.array[].settings |
JSON object |
Omitted when unavailable. |
leaderboard[].mods.rate |
number |
|
leaderboard[].rank |
string |
|
performance |
Performance |
|
performance.accuracy |
Accuracy |
|
performance.accuracy.90 |
number |
|
performance.accuracy.91 |
number |
|
performance.accuracy.92 |
number |
|
performance.accuracy.93 |
number |
|
performance.accuracy.94 |
number |
|
performance.accuracy.95 |
number |
|
performance.accuracy.96 |
number |
|
performance.accuracy.97 |
number |
|
performance.accuracy.98 |
number |
|
performance.accuracy.99 |
number |
|
performance.accuracy.100 |
number |
|
performance.graph |
Graph |
|
performance.graph.series |
Series[] |
|
performance.graph.series[].name |
string |
|
performance.graph.series[].data |
number[] |
|
performance.graph.xaxis |
number[] |
|
resultsScreen |
ResultsScreen |
|
resultsScreen.scoreId |
number |
|
resultsScreen.playerName |
string |
|
resultsScreen.mode |
NumberName |
|
resultsScreen.mode.number |
integer |
Omitted when unavailable. |
resultsScreen.mode.name |
string |
|
resultsScreen.score |
number |
|
resultsScreen.accuracy |
number |
|
resultsScreen.name |
string |
|
resultsScreen.hits |
ResultsHits |
|
resultsScreen.hits.0 |
integer |
|
resultsScreen.hits.50 |
integer |
|
resultsScreen.hits.100 |
integer |
|
resultsScreen.hits.300 |
integer |
|
resultsScreen.hits.geki |
integer |
|
resultsScreen.hits.katu |
integer |
|
resultsScreen.hits.sliderEndHits |
integer |
|
resultsScreen.hits.smallTickHits |
integer |
|
resultsScreen.hits.largeTickHits |
integer |
|
resultsScreen.mods |
CalculateMods |
|
resultsScreen.mods.checksum |
string |
|
resultsScreen.mods.number |
integer |
|
resultsScreen.mods.name |
string |
|
resultsScreen.mods.array |
Mod[] |
|
resultsScreen.mods.array[].acronym |
string |
|
resultsScreen.mods.array[].settings |
JSON object |
Omitted when unavailable. |
resultsScreen.mods.rate |
number |
|
resultsScreen.maxCombo |
integer |
|
resultsScreen.rank |
string |
|
resultsScreen.pp |
ResultsPp |
|
resultsScreen.pp.current |
number |
|
resultsScreen.pp.fc |
number |
|
resultsScreen.createdAt |
string |
|
folders |
Folders |
|
folders.game |
string |
|
folders.skin |
string |
|
folders.songs |
string |
|
folders.beatmap |
string |
Omitted when unavailable. |
files |
Files |
|
files.beatmap |
string |
Omitted when unavailable. |
files.background |
string |
Omitted when unavailable. |
files.audio |
string |
Omitted when unavailable. |
directPath |
DirectPath |
|
directPath.beatmapFile |
string |
|
directPath.beatmapBackground |
string |
|
directPath.beatmapAudio |
string |
|
directPath.beatmapFolder |
string |
Omitted when unavailable. |
directPath.skinFolder |
string |
|
tourney |
Tourney |
Omitted when unavailable. |
tourney.scoreVisible |
boolean |
|
tourney.starsVisible |
boolean |
|
tourney.ipcState |
integer |
|
tourney.bestOF |
integer |
|
tourney.team |
{ left: string, right: string } |
|
tourney.points |
{ left: integer, right: integer } |
|
tourney.chat |
{ team, name, message, timestamp: string }[] |
|
tourney.totalScore |
{ left: number, right: number } |
|
tourney.clients |
TourneyClient[] |
|
tourney.clients[].ipcId |
number |
|
tourney.clients[].team |
"left" or "right" |
|
tourney.clients[].settings |
TourneyClientSettings |
|
tourney.clients[].settings.mania |
TourneyManiaSettings |
|
tourney.clients[].settings.mania.scrollSpeed |
integer |
|
tourney.clients[].user |
TourneyUser |
|
tourney.clients[].user.id |
integer |
|
tourney.clients[].user.name |
string |
|
tourney.clients[].user.country |
string |
|
tourney.clients[].user.accuracy |
number |
|
tourney.clients[].user.rankedScore |
number |
|
tourney.clients[].user.playCount |
integer |
|
tourney.clients[].user.globalRank |
integer |
|
tourney.clients[].user.totalPP |
number |
|
tourney.clients[].beatmap |
TourneyBeatmap |
|
tourney.clients[].beatmap.stats |
Stats |
|
tourney.clients[].beatmap.stats.stars |
Stars |
|
tourney.clients[].beatmap.stats.stars.live |
number |
|
tourney.clients[].beatmap.stats.stars.aim |
number |
Omitted when unavailable. |
tourney.clients[].beatmap.stats.stars.speed |
number |
Omitted when unavailable. |
tourney.clients[].beatmap.stats.stars.flashlight |
number |
Omitted when unavailable. |
tourney.clients[].beatmap.stats.stars.sliderFactor |
number |
Omitted when unavailable. |
tourney.clients[].beatmap.stats.stars.stamina |
number |
Omitted when unavailable. |
tourney.clients[].beatmap.stats.stars.rhythm |
number |
Omitted when unavailable. |
tourney.clients[].beatmap.stats.stars.color |
number |
Omitted when unavailable. |
tourney.clients[].beatmap.stats.stars.reading |
number |
Omitted when unavailable. |
tourney.clients[].beatmap.stats.stars.hitWindow |
number |
Omitted when unavailable. |
tourney.clients[].beatmap.stats.stars.total |
number |
|
tourney.clients[].beatmap.stats.ar |
Ar |
|
tourney.clients[].beatmap.stats.ar.original |
number |
|
tourney.clients[].beatmap.stats.ar.converted |
number |
|
tourney.clients[].beatmap.stats.cs |
Cs |
|
tourney.clients[].beatmap.stats.cs.original |
number |
|
tourney.clients[].beatmap.stats.cs.converted |
number |
|
tourney.clients[].beatmap.stats.od |
Od |
|
tourney.clients[].beatmap.stats.od.original |
number |
|
tourney.clients[].beatmap.stats.od.converted |
number |
|
tourney.clients[].beatmap.stats.hp |
Hp |
|
tourney.clients[].beatmap.stats.hp.original |
number |
|
tourney.clients[].beatmap.stats.hp.converted |
number |
|
tourney.clients[].beatmap.stats.bpm |
Bpm |
|
tourney.clients[].beatmap.stats.bpm.realtime |
number |
|
tourney.clients[].beatmap.stats.bpm.common |
number |
|
tourney.clients[].beatmap.stats.bpm.min |
number |
|
tourney.clients[].beatmap.stats.bpm.max |
number |
|
tourney.clients[].beatmap.stats.objects |
Objects |
|
tourney.clients[].beatmap.stats.objects.circles |
integer |
|
tourney.clients[].beatmap.stats.objects.sliders |
integer |
|
tourney.clients[].beatmap.stats.objects.spinners |
integer |
|
tourney.clients[].beatmap.stats.objects.holds |
integer |
|
tourney.clients[].beatmap.stats.objects.total |
integer |
|
tourney.clients[].beatmap.stats.hitWindow |
HitWindow |
|
tourney.clients[].beatmap.stats.hitWindow.miss |
number |
Omitted when unavailable. |
tourney.clients[].beatmap.stats.hitWindow.meh |
number |
Omitted when unavailable. |
tourney.clients[].beatmap.stats.hitWindow.ok |
number |
Omitted when unavailable. |
tourney.clients[].beatmap.stats.hitWindow.good |
number |
Omitted when unavailable. |
tourney.clients[].beatmap.stats.hitWindow.great |
number |
Omitted when unavailable. |
tourney.clients[].beatmap.stats.hitWindow.perfect |
number |
Omitted when unavailable. |
tourney.clients[].beatmap.stats.maxCombo |
integer |
|
tourney.clients[].play |
Play |
|
tourney.clients[].play.failed |
boolean |
|
tourney.clients[].play.playerName |
string |
|
tourney.clients[].play.mode |
NumberName |
|
tourney.clients[].play.mode.number |
integer |
Omitted when unavailable. |
tourney.clients[].play.mode.name |
string |
|
tourney.clients[].play.score |
number |
|
tourney.clients[].play.accuracy |
number |
|
tourney.clients[].play.healthBar |
HealthBar |
|
tourney.clients[].play.healthBar.normal |
number |
|
tourney.clients[].play.healthBar.smooth |
number |
|
tourney.clients[].play.hits |
PlayHits |
|
tourney.clients[].play.hits.0 |
integer |
|
tourney.clients[].play.hits.50 |
integer |
|
tourney.clients[].play.hits.100 |
integer |
|
tourney.clients[].play.hits.300 |
integer |
|
tourney.clients[].play.hits.geki |
integer |
|
tourney.clients[].play.hits.katu |
integer |
|
tourney.clients[].play.hits.sliderBreaks |
integer |
|
tourney.clients[].play.hits.sliderEndHits |
integer |
|
tourney.clients[].play.hits.smallTickHits |
integer |
|
tourney.clients[].play.hits.largeTickHits |
integer |
|
tourney.clients[].play.hitErrorArray |
number[] |
|
tourney.clients[].play.pressHitErrors |
number[] |
vosu only |
tourney.clients[].play.releaseHitErrors |
number[] |
vosu only |
tourney.clients[].play.combo |
Combo |
|
tourney.clients[].play.combo.current |
integer |
|
tourney.clients[].play.combo.max |
integer |
|
tourney.clients[].play.mods |
CalculateMods |
|
tourney.clients[].play.mods.checksum |
string |
|
tourney.clients[].play.mods.number |
integer |
|
tourney.clients[].play.mods.name |
string |
|
tourney.clients[].play.mods.array |
Mod[] |
|
tourney.clients[].play.mods.array[].acronym |
string |
|
tourney.clients[].play.mods.array[].settings |
JSON object |
Omitted when unavailable. |
tourney.clients[].play.mods.rate |
number |
|
tourney.clients[].play.rank |
Rank |
|
tourney.clients[].play.rank.current |
string |
|
tourney.clients[].play.rank.maxThisPlay |
string |
|
tourney.clients[].play.pp |
Pp |
|
tourney.clients[].play.pp.current |
number |
|
tourney.clients[].play.pp.fc |
number |
|
tourney.clients[].play.pp.maxAchieved |
number |
|
tourney.clients[].play.pp.maxAchievable |
number |
|
tourney.clients[].play.pp.detailed |
DetailedPp |
|
tourney.clients[].play.pp.detailed.current |
DetailedPpAttributes |
|
tourney.clients[].play.pp.detailed.current.aim |
number |
|
tourney.clients[].play.pp.detailed.current.speed |
number |
|
tourney.clients[].play.pp.detailed.current.accuracy |
number |
|
tourney.clients[].play.pp.detailed.current.difficulty |
number |
|
tourney.clients[].play.pp.detailed.current.flashlight |
number |
|
tourney.clients[].play.pp.detailed.current.total |
number |
|
tourney.clients[].play.pp.detailed.fc |
DetailedPpAttributes |
|
tourney.clients[].play.pp.detailed.fc.aim |
number |
|
tourney.clients[].play.pp.detailed.fc.speed |
number |
|
tourney.clients[].play.pp.detailed.fc.accuracy |
number |
|
tourney.clients[].play.pp.detailed.fc.difficulty |
number |
|
tourney.clients[].play.pp.detailed.fc.flashlight |
number |
|
tourney.clients[].play.pp.detailed.fc.total |
number |
|
tourney.clients[].play.unstableRate |
number |
|
room |
Room |
Omitted when unavailable. |
room.roomID |
integer |
|
room.users |
RoomUser[] |
|
room.users[].id |
integer |
|
room.users[].username |
string |
|
room.users[].countryCode |
integer |
|
room.users[].avatarUrl |
string |
Omitted when unavailable. |
Precise v2
GET /json/v2/precise and /websocket/v2/precise publish this smaller, independently sampled document. It is not a complete regular v2 state object.
| Field | JSON type | Availability / compatibility |
|---|---|---|
keys |
Keys |
|
keys.k1 |
KeyOverlayButton |
|
keys.k1.isPressed |
boolean |
|
keys.k1.count |
integer |
|
keys.k2 |
KeyOverlayButton |
|
keys.k2.isPressed |
boolean |
|
keys.k2.count |
integer |
|
keys.m1 |
KeyOverlayButton |
|
keys.m1.isPressed |
boolean |
|
keys.m1.count |
integer |
|
keys.m2 |
KeyOverlayButton |
|
keys.m2.isPressed |
boolean |
|
keys.m2.count |
integer |
|
keys.all |
Keypress[] |
vosu only |
keys.all[].name |
string |
vosu only |
keys.all[].isPressed |
boolean |
vosu only |
keys.all[].count |
integer |
vosu only |
keys.all[].pressedAt |
number or null |
Nullable gameplay time in ms: stable replay-frame edge, lazer sampled edge. vosu only |
keys.all[].releasedAt |
number or null |
Nullable gameplay time in ms: stable replay-frame edge, lazer sampled edge. vosu only |
hitErrors |
number[] |
|
pressHitErrors |
number[] |
vosu only |
releaseHitErrors |
number[] |
vosu only |
hitOffsets |
number[] |
vosu only Added in vosu 1.1.0. Omitted unless ENABLE_HIT_OFFSETS = true. Flat stride-3 [x, y, error, …], as in regular v2 play.hitOffsets. |
keyHitErrors |
KeyHitErrors |
vosu only Added in vosu 1.1.0. Omitted unless ENABLE_MANIA_KEY_HIT_ERRORS = true. |
keyHitErrors.press |
number[][] |
Per-displayed-lane press timing errors in ms. |
keyHitErrors.release |
number[][] |
Per-displayed-lane hold-release timing errors in ms. |
catcher |
Catcher |
vosu only Added in vosu 1.1.0. Omitted outside catch gameplay or without native evidence. |
catcher.x |
number |
Stored playfield X in osu! pixels (0–512), not screen space. |
catcher.dashing |
boolean |
Ordinary dash, not hyperdash. |
tourney |
PreciseTourney[] |
|
tourney[].ipcId |
number |
|
tourney[].keys |
Keys |
|
tourney[].keys.k1 |
KeyOverlayButton |
|
tourney[].keys.k1.isPressed |
boolean |
|
tourney[].keys.k1.count |
integer |
|
tourney[].keys.k2 |
KeyOverlayButton |
|
tourney[].keys.k2.isPressed |
boolean |
|
tourney[].keys.k2.count |
integer |
|
tourney[].keys.m1 |
KeyOverlayButton |
|
tourney[].keys.m1.isPressed |
boolean |
|
tourney[].keys.m1.count |
integer |
|
tourney[].keys.m2 |
KeyOverlayButton |
|
tourney[].keys.m2.isPressed |
boolean |
|
tourney[].keys.m2.count |
integer |
|
tourney[].keys.all |
Keypress[] |
vosu only |
tourney[].keys.all[].name |
string |
vosu only |
tourney[].keys.all[].isPressed |
boolean |
vosu only |
tourney[].keys.all[].count |
integer |
vosu only |
tourney[].keys.all[].pressedAt |
number or null |
Nullable gameplay time in ms: stable replay-frame edge, lazer sampled edge. vosu only |
tourney[].keys.all[].releasedAt |
number or null |
Nullable gameplay time in ms: stable replay-frame edge, lazer sampled edge. vosu only |
tourney[].hitErrors |
number[] |
|
tourney[].pressHitErrors |
number[] |
vosu only |
tourney[].releaseHitErrors |
number[] |
vosu only |
Timing and input semantics
beatmap.stats.hitWindowcontains optional judgement membersmiss,meh,ok,good,great, andperfect: maximum absolute timing errors in milliseconds after the active clock rate is applied. Unsupported members are omitted. Missing/unparsed maps use{}. Catch publishes zeros for all six and omitsstars.hitWindow; spatial catcher width is not a timing window. The judgement object is distinct from the scalarstars.hitWindow.hitErrorArray(regular v2) andhitErrors(precise v2) retain the original ordered timing-event history.pressHitErrorsandreleaseHitErrorsvosu only split note presses and osu!mania hold-note releases; together they hold every value of the original array exactly once, in order. osu!lazer classifies from its judgement results. osu!stable classifies native mania maps, including with the Mirror mod, by matching each error to the map's judgement times and the replay's key transitions, so classification can lag the original array while that evidence arrives. An error that matches no transition (for example under the Random mod) is published as a press once the replay has moved 250 ms past it or one second has passed, so it never holds back later errors. Stable converted maps and maps without metadata stay press-only; osu!, taiko, and catch have no release judgements.- Pause/results retain the current attempt’s history. Exiting the attempt clears it; a genuine quick retry begins fresh history. Polling before the first object and temporarily shrinking native lists do not clear history.
keys.allvosu only uses logicalB1-onwards names, not physical key names. Added in vosu 1.1.0: stable replay-frame parity and lazer's full 20-action mania range. Stable counts retained frame down-edges, including complete taps between polls, and timestamps exact replay-frame transitions up to the current play clock (including preloaded replays/spectating). Lazer timestamps sampled edges only; count jumps do not fabricate timestamps. The legacy four buttons keep their existing stable in-game-overlay source.- The whole regular-v2
keysobject vosu only is additional relative to upstream tosu; tosu exposes its four-button object only in precise v2. rankedPlay.stage: 0 WaitForJoin, 1 RoundWarmup, 2 CardDiscard, 3 FinishCardDiscard, 4 CardPlay, 5 FinishCardPlay, 6 GameplayWarmup, 7 Gameplay, 8 Results, 9 Ended.
Logical action order
vosu only Added in vosu 1.1.0: stable keys.all uses the same names/order as lazer.
| Ruleset | keys.all order |
Stable replay mapping |
|---|---|---|
| osu! | B1 left button, B2 right button, B3 Smoke |
Bits 1 or 4, 2 or 8, 16; keyboard/mouse merge into logical actions. |
| taiko | B1 left rim, B2 left centre, B3 right centre, B4 right rim |
Bits 2, 1, 4, 8. |
| catch | B1 move left, B2 move right, B3 dash |
Left/right never pressed, counts zero, timestamps null; stable records position instead. Dash is button state exactly 1. |
| mania | B1 through BN, displayed column order |
X-slot column bitfield, bit 0 first; N is converted-map key count including key mods/dual stages. |
Lazer enumerates distinct default-binding triggers, not available-action enums. Single-stage 4K–10K yields B1–B4 through B1–B10; dual-stage N+N yields B1–B(2N), stage one then stage two, up to 20. ENABLE_KEY_OVERLAY still gates updates after the opening 150 ms. Stable all follows replay frames independently of in-game overlay visibility; live osu!stable b20260924.1 confirmed the button byte in all four rulesets and counting with the in-game key overlay hidden.
Stable retry/rewind resets the attempt; rolling-window eviction preserves accumulated counts. Missing more than 8192 frames takes the first available state as a baseline without inventing a press. Lost edges and history evicted before a mid-play attachment cannot be recovered. Catch left/right and unrecoverable history remain parity differences, not physical-input measurements.
Spatial and per-key extensions
vosu only Added in vosu 1.1.0: hitOffsets, keyHitErrors, and catcher. The regular document nests them under play; precise v2 exposes them at the top level in the same order after releaseHitErrors. They are not added to v1 or streamCompanion. Precise tourney[] retains only its existing keys and aggregate error arrays.
Enable ENABLE_HIT_OFFSETS = true (Game data → Standard hit offsets in the dashboard) to expose hitOffsets. The default is false: the field is omitted entirely from both regular v2 play and precise v2 while disabled, not sent as an empty array. Enabling mid-attempt records subsequent hits only, without backfilling history; keys.all and catcher are independent of this setting.
hitOffsets contains cursor-minus-stacked-center X/Y in displayed 512×384 playfield pixels and the original matching timing error in ms. Missing spatial evidence omits a triple, not a zero position. keyHitErrors indexes displayed mania lanes including Mirror; untouched lanes before the highest observed lane are empty, and outside mania attempts both outer arrays are empty. Its history follows the existing reset/retention rules; enabling mid-attempt starts with subsequent classifications only.
catcher is omitted in menus, results and other rulesets. On lazer, hitOffsets, keyHitErrors and catcher use offsets measured for lazer 2026.921.0 (2026.1005.0 has the same layout) or generated at runtime for other versions. See extension semantics and remaining stable/lazer limitations.
v1 and streamCompanion
The v1 family (/json, /ws) exposes the gosuMemory-compatible grouped snapshot; streamCompanion (/json/sc, /tokens) exposes the compatibility token object. Use the upstream tosu wiki for those full compatibility references rather than a second duplicated schema.
vosu retains v1 hitErrorArray and streamCompanion hitErrors and adds sibling pressHitErrors / releaseHitErrors vosu only. Their split-history semantics are the same as above. Treat these additions as optional on other servers. Do not infer that the added v2 keys tree exists in the older schemas.