Classic Chess · REST API

SDK examples

To connect Claude Code, Codex or another MCP client, see MCP server.

Each example discovers a player, reads their biography, lists notable PGN links, and follows every page of their game archive. Install your language's SDK using its public README first. These examples use public data without credentials and handle empty archives and missing biographies.

Python users can install the MIT-licensed classicchess-sdk package from PyPI. In a Python 3.10+ virtual environment, run:

python -m pip install classicchess-sdk
classicchess-api public players --names

Python

from urllib.parse import urljoin
from classicchess_api import ClassicChessClient

api = ClassicChessClient(user_agent="my-chess-app/1.0")
players = api.public_players()["results"]
if not players:
    raise SystemExit("No curated player archives are available")
player = players[0]
print(player["name"])

bio = api.public_player_bio(player["slug"])["bio"]
print(bio["lede"] if bio else "Biography unavailable")

notable = api.public_notable_games(player["slug"])
for entry in notable["results"]:
    print(entry["title"], urljoin(api.base_url, entry["game"]["urls"]["api_pgn"]))

for game in api.iterate_public_games(archive_player=player["slug"]):
    print(game["token"], urljoin(api.base_url, game["urls"]["api_pgn"]))

JavaScript and TypeScript users can install the MIT-licensed classicchess-sdk package from npm. It requires Node.js 22 or later and includes ESM, CommonJS and TypeScript definitions. From your app directory, run:

npm install classicchess-sdk

Save the following example as example.mjs and run node example.mjs. CommonJS apps use require('classicchess-sdk') and wrap awaited calls in an async function.

JavaScript

import { ClassicChessClient } from "classicchess-sdk";

const api = new ClassicChessClient({ userAgent: "my-chess-app/1.0" });
const { results: players } = await api.publicPlayers();
if (!players.length) throw new Error("No curated player archives are available");
const player = players[0];
console.log(player.name);

const { bio } = await api.publicPlayerBio(player.slug);
console.log(bio?.lede ?? "Biography unavailable");

const notable = await api.publicNotableGames(player.slug);
for (const entry of notable.results) {
  console.log(entry.title, new URL(entry.game.urls.api_pgn, api.baseUrl).href);
}

for await (const game of api.iteratePublicGames({ archivePlayer: player.slug })) {
  console.log(game.token, new URL(game.urls.api_pgn, api.baseUrl).href);
}

Kotlin

import com.classicchess.api.ClassicChessClient
import com.classicchess.api.PublicGameFilters
import java.net.URI
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    ClassicChessClient().use { api ->
        val players = api.publicPlayers().results
        val player = players.firstOrNull()
        if (player == null) {
            println("No curated player archives are available")
            return@use
        }
        println(player.name)

        val bio = api.publicPlayerBio(player.slug).bio
        println(bio?.lede ?: "Biography unavailable")

        val notable = api.publicNotableGames(player.slug)
        for (entry in notable.results) {
            println("${entry.title} ${URI(api.baseUrl).resolve(entry.game.urls.getValue("api_pgn")!!)}")
        }

        api.iteratePublicGames(PublicGameFilters(archivePlayer = player.slug)).collect { game ->
            println("${game.token} ${URI(api.baseUrl).resolve(game.urls.getValue("api_pgn")!!)}")
        }
    }
}

The JavaScript example runs on a server. Cross-origin browser access is not currently enabled; browser apps should call their own backend. Keep account bearer tokens on trusted clients or your backend and send them only to the configured HTTPS API origin.