A CS2 Discord bot in one file.
A /cs2live slash command that posts every match in progress with the map and score, written with discord.js. Add results, transfers and rankings the same way.
- Slash command example
- Live, results, transfers
- 500 free requests / month
{ "data": [ ... { "team1Name": "SINNERS", "team2Name": "Ninjas in Pyjamas", "currentMap": "de_ancient", "currentMapScore": { "team1": 3, "team2": 0 }, "currentRound": 3 } ]}Seamless Integration with our MCP Server
Give Claude, Cursor and ChatGPT the CS2 data. One command writes the MCP config; agents call live scoreboard, team map stat, opening duel and transfer tools instead of inventing match IDs, and your key stays on your machine.
MCPInstall the Cito MCP serverCommands a CS2 server wants
Each command is one API call.
/cs2live
Every match in progress with map score and round.
/results
The latest finished matches.
/schedule
What is on next today.
/rank
The VRS or world ranking top 10.
/player
A player's recent form.
Transfer alerts
Post new roster moves to a channel.
The /cs2live command
Needs DISCORD_TOKEN, DISCORD_APP_ID and CITO_API_KEY.
// bot.mjs (discord.js v14, Node 18+)
import { Client, GatewayIntentBits, REST, Routes, SlashCommandBuilder } from "discord.js";
const command = new SlashCommandBuilder().setName("cs2live").setDescription("CS2 matches in progress");
await new REST({ version: "10" })
.setToken(process.env.DISCORD_TOKEN)
.put(Routes.applicationCommands(process.env.DISCORD_APP_ID), { body: [command.toJSON()] });
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.on("interactionCreate", async (interaction) => {
if (!interaction.isChatInputCommand() || interaction.commandName !== "cs2live") return;
const res = await fetch("https://api.citoapi.com/api/v1/cs2/live", {
headers: { "x-api-key": process.env.CITO_API_KEY },
});
const { data } = await res.json();
const lines = data.slice(0, 10).map(
(m) =>
`**${m.team1Name}** ${m.team1Score}-${m.team2Score} **${m.team2Name}** · ` +
`${m.currentMap ?? "TBA"} ${m.currentMapScore?.team1 ?? 0}-${m.currentMapScore?.team2 ?? 0}`,
);
await interaction.reply(lines.join("\n") || "No CS2 matches live right now.");
});
client.login(process.env.DISCORD_TOKEN);Endpoints you can ship with
The endpoints behind each bot command.
Live matches
Poll the live list for every match in progress, open one match for its round, timer, bomb and players, or keep an SSE stream open and get each update pushed.
- GET
/api/v1/cs2/liveMatches in progress: series score, map in play, map score, current round.
- GET
/api/v1/cs2/live/{matchId}/stateOne live match: score, round, round timer, bomb status and players.
- GET
/api/v1/cs2/live/{matchId}/scoreboardSeries score, current map and round, and each player's kills, deaths, money and equipment.
- GET
/api/v1/cs2/live/{matchId}/roundsRound-by-round results so far: winner, side and how each round ended.
- GET
/api/v1/cs2/live/streamServer-Sent Events push of every live update. Every plan; counts like polling.
- GET
/api/v1/cs2/live/wsWebSocket with a room per match. Scale and Enterprise.
Add more commands
- CS2 live score APISeries, map and round score for every match in progress.
- CS2 transfers APIPlayer moves and roster changes, newest first.
- CS2 rankings APIWorld ranking and Valve Regional Standings with movement.
- CS2 match results APIFinal series scores, map scores and box scores.
- CS2 API in Node.jsFetch CS2 data from JavaScript and TypeScript.
- CS2 schedule APIUpcoming matches, today's slate and the tournament calendar.