Protocol Documentation

General

neomod uses and extends the bancho protocol.

Whenever "convars" or "variables" are mentioned, this means in-game variables, accessible by pressing Shift+F1.
The full list of variables is available here. This should give you a nice idea of how customizable neomod is for server admins.

You do not have to implement any of the features below; neomod will gracefully fallback to "vanilla" behavior.

Identification

Client Detection

Detect neomod clients via header on c. endpoint:

x-mcosu-ver: <version>

User Agent

API endpoints use this user agent:

Mozilla/5.0 (compatible; neomod/<version info>; +https://neomod.net/)
When using the web client, the default browser user agent will be sent instead.

Browser client

To support the in-browser client, you need to handle CORS by including these headers in EVERY response:

Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: *
Access-Control-Expose-Headers: cho-token, x-mcosu-features

You must also handle preflight requests to each subdomain (e.g. OPTION https://c.neomod.net/), by replying with a 204 No content and the above headers.

Score Submission

Enable score submission with header:

x-mcosu-features: submit=1
Regardless of this setting, scores will not submit when using PROTECTED variables.
By default, all non-vanilla mods are PROTECTED. Use the UNPROTECT_VARIABLES packet for allowing individual mods and features.

OAuth

Enabled Domains

OAuth authentication is automatically enabled for:

Local Testing: Set ssl_verify convar to 0 for neomod.local

Login Flow

Step 1: Authorization

When clicking the "Log in with osu!" button, neomod will open the browser to:

GEThttps://neomod.net/connect/start?challenge={b64(sha256(verification_bytes))}&client=release-43.00

Step 2: Token polling

neomod will poll the server to get the refresh token:

GEThttps://neomod.net/connect/finish?challenge={b64(sha256(verification_bytes))}&proof={b64(verification_bytes)}

If the login is still in process, the server will return an HTTP 204 response.

If the login completed, the server will return the refresh token in an HTTP 200 response.

Step 3: Session Login

We use the c. endpoint login packet, with:

Server returns cho-token like for regular clients.

Websockets

After logging in, neomod will attempt to connect to wss://c.neomod.net/ws/. If the server returns a different HTTP code than 101, neomod will fall back to HTTP polling, like regular clients.

If you're planning to add support for websockets on your server, remember to treat websocket connections the same as a polling client: CloudFlare tends to close websocket connections after 2 minutes, so a connection closing does not mean the client has actually stopped playing.

API Requests

Score submission

Submitted scores have an extra neomod-mods section, containing base64-encoded data representing neomod-specific mods.

Leaderboards

Requests: neomod has a "Team" leaderboard filter, which sets the parameter v=5 (as opposed to, say, v=4 for "Country").

Responses: Score lines have an extra section after the "has_replay" flag, containing base64-encoded data representing neomod-specific mods.

OAuth mode

In OAuth mode, in requests where the username and password hash are passed as parameters, username will be $token and password hash will be {cho-token}.

This includes score submission, where the username is passed and hashed in the score data.

Custom Endpoints

Map submission

POSThttps://osu.neomod.net/web/neomod-submit-map.php

URL Parameters
Form data

Server should verify that the map md5 matches the file data.

Server Packets

128 PROTECT_VARIABLES

Marks variables as PROTECTED. Score submission disabled when value differ from defaults.

129 UNPROTECT_VARIABLES

Removes PROTECTED flag. Scores submit regardless of variable value.

130 FORCE_VALUES

Forces variables to specific values.

131 RESET_VALUES

Resets variables to client-side value.

132 REQUEST_MAP

Requests an .osu file from the client. Used for unranked/unavailable maps.

Client should send the .osu file to the neomod-submit-map endpoint.