Quick Links: Features ​ / ​ Usage ​ / ​ Install ​ / ​ Quickstart ​ / ​ Tools
- Api
- osu api v1:
- osu api v2 (82+ api routes):
- Auto session refresh
- Does not require you to login for each action
- Built-in Tools
tools.build_url
- Create link foruser
,score
,editor_timing
and otherstools.calculate_accuracy
- Calculate accuracy from play hitstools.calculate_hits
- Calculate hits if play was an FCtools.calculate_mods
- Calculate mods Number/Name from Number/Nametools.calculate_net_pp
- Calculate how much pp would you gain from a playtools.calculate_pp
- Create link foruser
,score
,editor_timing
and otherstools.calculate_rank
- Calculate rank from play hitstools.calculate_total_passed_objects
- Calculate total passed objectstools.country_details
- Get country name and code by providing country name/codetools.download_beatmaps
- Downloads a beatmap or beatmap set by given ID. (Supports different hosts)- See documentation
- Setting to prevent throw, instead send .error
npm i osu-api-extended
yarn install osu-api-extended
pnpm install osu-api-extended
bun install osu-api-extended
Links: create your client here ​ / ​ get your api key here
Quick Links: v2 - client auth ​ / ​ v2 - lazer auth ​ / ​ v2 - cli auth ​ / ​ v2 - Discord Verify ​ / ​ v2 - Website login ​ / ​ v1 usage ​ / ​ v2 - prevent throw errors
import { auth } from 'osu-api-extended';
async function main() {
try {
await auth.login({
type: 'v2',
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
cachedTokenPath: './client.json' // path to the file your auth token will be saved (to prevent osu!api spam)
});
const result = await v2.users.details({ user: 'mrekk', mode: 'osu', key: '@' });
if (result.error != null) {
console.log(result.error);
return;
};
console.log(result);
} catch (error) {
console.log(error);
};
};
main();
Authorization though your account
import { auth } from 'osu-api-extended';
async function main() {
try {
await auth.login({
type: 'v2',
login: LOGIN,
password: PASSWORD,
cachedTokenPath: './lazer.json' // path to the file your auth token will be saved (to prevent osu!api spam)
});
const result = await v2.me.details();
if (result.error != null) {
console.log(result.error);
return;
};
console.log(result);
} catch (error) {
console.log(error);
};
};
main();
import { auth } from 'osu-api-extended';
async function main() {
try {
await auth.login({
type: 'cli',
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
redirect_url: REDIRECT_URL,
scopes: ['public'],
cachedTokenPath: './cli.json' // path to the file your auth token will be saved (to prevent osu!api spam)
});
const result = await v2.me.details();
if (result.error != null) {
console.log(result.error);
return;
};
console.log(result);
} catch (error) {
console.log(error);
};
};
main();
import { Client } from 'discord.js';
import { auth } from 'osu-api-extended';
const discord_bot = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.MessageContent, GatewayIntentBits.GuildMessages] }); // no clue why i need those intents
// send this link to user
discord_bot.on('messageCreate', async message => {
if (message.author.bot) return;
if (!message.content.startsWith('!')) return;
const [command, value1, value2] = message.content.split('!').join('').split(' ');
logger('command', { _c: 'yellowBright', v: command }, value1, value2);
if (command == 'verify') {
const url = const url = auth.build_url({
client_id: CLIENT_ID,
redirect_url: REDIRECT_URL,
scopes: ['identify'],
state: message.author.id
});
message.reply(`Verify via this link: ${url}`);
return;
};
});
// somewhere else verify this
function verifyUser(code, state) {
// it returns user object
const verify = await auth.authorize({
code: code,
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
redirect_url: REDIRECT_URL
});
console.log(verify);
};
Nitro framework example
import { auth } from 'osu-api-extended';
// /auth page
export default defineEventHandler(event => {
const build_url = auth.build_url({
client_id: CLIENT_ID,
redirect_uri: REDIRECT_URL,
scopes: ['identify'],
});
return sendRedirect(event, build_url);
});
// /callback page
export default defineEventHandler(async event => {
const { code } = getQuery(event);
const verify = await auth.authorize({
code: code.toString(),
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
redirect_url: REDIRECT_URL,
});
setCookie(event, 'user_id', verify.id.toString());
setCookie(event, 'user_name', verify.username.toString());
setCookie(event, 'access_token', verify.access_token);
setCookie(event, 'refresh_token', verify.refresh_token);
return sendRedirect(event, '/');
});
import { auth, v1 } from 'osu-api-extended';
async function main() {
try {
auth.login({
type: 'v1',
api_key: API_KEY,
});
const beatmap = await v1.beatmap.diff(3798013);
console.log(beatmap);
} catch (error) {
console.log(error);
};
};
main();
import { auth } from 'osu-api-extended';
auth.settings.throwErrors = false;
async function main() {
try {
await auth.login({
type: 'v2',
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
});
const result = await v2.beatmaps.events.list({ types: ['approve'] });
if (result.error instanceof Error) {
// or
if (result.error != null) {
console.log(result.error);
return;
};
console.log(result);
} catch (error) {
console.log(error);
};
};
main();
import { tools } from 'osu-api-extended';
function build_url() {
try {
const result = tools.build_url({ type: 'beatmap', value: 4397592 });
if (result.error != null) {
console.log(result.error);
return;
};
console.log(result);
} catch (error) {
console.log(error);
};
};
function download_beatmaps() {
try {
const set_id = 320118;
const progress_update = (...args) => {
console.log(args);
};
const result = await tools.download_beatmaps({
type: 'set',
host: 'gatari',
id: set_id,
file_path: `./cache/${set_id}.osz`,
progress_log_fn: progress_update
});
if (result.error != null) {
console.log(result.error);
return;
};
console.log(result);
} catch (error) {
console.log(error);
};
};
function calculate_accuracy() {
try {
const hits = { 300: 123, 100: 12, 50: 1, 0: 1 };
const result = tools.calculate_accuracy(hits, 'osu');
if (result.error != null) {
console.log(result.error);
return;
};
console.log(result);
} catch (error) {
console.log(error);
};
};
function calculate_mods() {
try {
const result = tools.calculate_mods('HDDT');
// or
const result = tools.calculate_mods(72);
// or
const result = tools.calculate_mods([{ acronym: "EZ" }]);
if (result.error != null) {
console.log(result.error);
return;
};
console.log(result);
} catch (error) {
console.log(error);
};
};
function country_details() {
try {
const result = tools.country_details('US');
// or
const result = tools.country_details('United States');
if (result.error != null) {
console.log(result.error);
return;
};
console.log(result);
} catch (error) {
console.log(error);
};
};
function calculate_rank() {
try {
const hits = { 300: 123, 100: 12, 50: 1, 0: 1 };
const result = tools.calculate_rank(hits, 72, 'osu');
if (result.error != null) {
console.log(result.error);
return;
};
console.log(result);
} catch (error) {
console.log(error);
};
};
function calculate_total_passed_objects() {
try {
const hits = { 300: 123, 100: 12, 50: 1, 0: 1 };
const result = tools.calculate_total_passed_objects(hits, 'osu');
if (result.error != null) {
console.log(result.error);
return;
};
console.log(result);
} catch (error) {
console.log(error);
};
};
function calculate_hits() {
try {
const hits = { 300: 123, 100: 12, 50: 1, 0: 1 };
const result = tools.calculate_hits(hits, 'osu');
if (result.error != null) {
console.log(result.error);
return;
};
console.log(result);
} catch (error) {
console.log(error);
};
};
function calculate_net_pp() {
try {
const plays = [1000, 900, 800, 700];
const scores = [{ id: 123, pp: 1000 }, { id: 123, pp: 555 }, { id: 123, pp: 234 }, { id: 123, pp: 100 }];
const result = tools.calculate_net_pp(plays, 400);
// or
const result = tools.calculate_net_pp(scores, 400);
if (result.error != null) {
console.log(result.error);
return;
};
console.log(result);
} catch (error) {
console.log(error);
};
};
zero
request.ts
by AqilCont