βš”οΈ CSSBattle API

Scrape CSSBattle player profiles with ease

πŸš€ Getting Started

The CSSBattle API allows you to fetch player profile data from CSSBattle in JSON format. No authentication required!

βœ… Real-time Data

Get live player statistics and rankings

⚑ Fast & Cached

1-hour cache for optimal performance

πŸ”’ Reliable

Production-ready API with error handling

🌐 CORS Enabled

Use from any frontend application

πŸ“‘ API Endpoint

GET /api/player/[username]

Parameters

username (required)
The CSSBattle player username (alphanumeric, hyphens, underscores allowed)

πŸ§ͺ Try It Out

πŸ“¨ Example Request

URL

GET /api/player/zerhouni

Using cURL

curl -X GET "https://cssbattle-api.vercel.app/api/player/zerhouni"

Using JavaScript Fetch

fetch('/api/player/zerhouni') .then(res => res.json()) .then(data => console.log(data))

πŸ“¬ Example Response

200 OK
{ "username": "zerhouni", "profileUrl": "https://cssbattle.dev/player/zerhouni", "profilePicture": "https://ik.imagekit.io/cssbattle/user%2F.../avatar.jpeg", "streaks": { "current": 18, "longest": 18 }, "battleStats": { "globalRank": 6238, "targetsPlayed": 36, "totalScore": 22960.62 }, "dailyTargets": { "targetsPlayed": 33, "avgMatch": 99.94, "avgCharacters": 257 }, "versus": { "rating": 1200, "gamesPlayed": 0, "wins": 0 } }

⚠️ Error Responses

400 - Invalid Username

400 Bad Request
{ "error": "Invalid username format", "message": "Username can only contain letters, numbers, hyphens, and underscores" }

404 - Player Not Found

404 Not Found
{ "error": "Player not found", "message": "No player found with username: invalid" }

500 - Server Error

500 Internal Server Error
{ "error": "Internal server error", "message": "Failed to scrape profile" }

πŸ“Š Response Fields Explained

Profile Information

username - Player's username
profileUrl - Direct link to player profile
profilePicture - URL to player's profile picture/avatar

Streaks

current - Current daily streak (in days)
longest - Longest streak achieved (in days)

Battle Stats

globalRank - Player's global rank
targetsPlayed - Total number of targets played
totalScore - Overall score (decimal)

Daily Targets

targetsPlayed - Daily targets played
avgMatch - Average match percentage
avgCharacters - Average characters used

Versus Stats

rating - Current versus rating
gamesPlayed - Total versus games played
wins - Total versus wins

⚑ Performance

First Request

5-10 seconds
(Browser rendering)

Cached Requests

< 100ms
(1 hour cache)

Function Timeout

15 seconds
(Maximum)

πŸ”— Integration Examples

React Component

import { useEffect, useState } from 'react';

function PlayerProfile({ username }) {

β€…β€…β€…β€…β€…β€…β€…const [player, setPlayer] = useState(null);
β€…β€…β€…β€…β€…β€…β€…const [loading, setLoading] = useState(true);

β€…β€…β€…β€…β€…β€…β€…useEffect(() => {
β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…fetch(`/api/player/${username}`)
β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€….then(res => res.json())
β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€….then(data => {
β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…setPlayer(data);
β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…setLoading(false);
β€…β€…β€…β€…β€…β€…β€…β€…});
β€…β€…β€…β€…β€…β€…β€…}, [username]);

β€…β€…β€…β€…β€…β€…β€…if (loading) return <div>Loading...</div>;

β€…β€…β€…β€…β€…β€…β€…return (
β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…<div>
β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…<h1>{player.username}</h1>
β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…<p>Rank: {player.battleStats.globalRank}</p>
β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…<p>Score: {player.battleStats.totalScore}</p>
β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…β€…</div>
β€…β€…β€…β€…β€…β€…β€…β€…);
}

πŸ“ˆ Best Practices

  • Cache responses on your end (1 hour minimum)
  • Handle errors gracefully with user-friendly messages
  • Validate usernames before sending requests
  • Respect the 15-second function timeout
  • Don't make excessive parallel requests