-
Notifications
You must be signed in to change notification settings - Fork 0
Games
Export and stream games played on Lichess.
Namespace: LichessSharp.Api.Contracts, LichessSharp.Models.Games
Access: client.Games
Export a single game by ID in JSON format.
Task<GameJson> ExportAsync(
string gameId,
ExportGameOptions? options = null,
CancellationToken cancellationToken = default)Parameters:
| Name | Type | Description |
|---|---|---|
| gameId | string | The game ID (8 characters) |
| options | ExportGameOptions? | Export options |
ExportGameOptions:
| Property | Type | Description |
|---|---|---|
| Moves | bool? | Include moves (default true) |
| PgnInJson | bool? | Include PGN in JSON response |
| Tags | bool? | Include PGN tags |
| Clocks | bool? | Include clock comments |
| Evals | bool? | Include analysis evaluations |
| Accuracy | bool? | Include accuracy percentages |
| Opening | bool? | Include opening info |
| Literate | bool? | Insert textual annotations |
| Players | string? | URL of a text file with usernames |
Example:
using var client = new LichessClient();
var game = await client.Games.ExportAsync("AbCdEfGh", new ExportGameOptions
{
Moves = true,
Clocks = true,
Evals = true,
Opening = true
});
Console.WriteLine($"Game ID: {game.Id}");
Console.WriteLine($"White: {game.Players?.White?.User?.Name} ({game.Players?.White?.Rating})");
Console.WriteLine($"Black: {game.Players?.Black?.User?.Name} ({game.Players?.Black?.Rating})");
Console.WriteLine($"Result: {game.Winner ?? "draw"}");
Console.WriteLine($"Moves: {game.Moves}");
Console.WriteLine($"Opening: {game.Opening?.Name}");
if (game.Clock != null)
{
Console.WriteLine($"Time Control: {game.Clock.Initial / 60}+{game.Clock.Increment}");
}Export a single game in PGN format.
Task<string> GetPgnAsync(
string gameId,
ExportGameOptions? options = null,
CancellationToken cancellationToken = default)Example:
using var client = new LichessClient();
var pgn = await client.Games.GetPgnAsync("AbCdEfGh", new ExportGameOptions
{
Clocks = true,
Evals = true
});
Console.WriteLine(pgn);
// Outputs:
// [Event "Rated Blitz game"]
// [Site "https://lichess.org/AbCdEfGh"]
// [White "Player1"]
// [Black "Player2"]
// ...
// 1. e4 { [%clk 3:00:00] } e5 { [%clk 3:00:00] } ...Get the ongoing game, or last game, of a user.
Task<GameJson> GetCurrentGameByUserAsync(
string username,
ExportGameOptions? options = null,
CancellationToken cancellationToken = default)Example:
using var client = new LichessClient();
try
{
var game = await client.Games.GetCurrentGameByUserAsync("DrNykterstein");
Console.WriteLine($"Current game: {game.Id}");
Console.WriteLine($"Status: {game.Status}");
}
catch (LichessApiException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
{
Console.WriteLine("User is not currently playing");
}Stream all games of a user.
IAsyncEnumerable<GameJson> StreamUserGamesAsync(
string username,
ExportUserGamesOptions? options = null,
CancellationToken cancellationToken = default)ExportUserGamesOptions:
| Property | Type | Description |
|---|---|---|
| Since | DateTimeOffset? | Only games played since |
| Until | DateTimeOffset? | Only games played until |
| Max | int? | Maximum number of games |
| Vs | string? | Only games against this opponent |
| Rated | bool? | Only rated or casual games |
| PerfType | string? | Only games of this variant |
| Color | string? | Only games as this color |
| Analysed | bool? | Only analysed games |
| Ongoing | bool? | Include ongoing games |
| Finished | bool? | Include finished games |
| Sort | string? | "dateAsc" or "dateDesc" |
| Moves | bool? | Include moves |
| PgnInJson | bool? | Include PGN |
| Tags | bool? | Include PGN tags |
| Clocks | bool? | Include clock comments |
| Evals | bool? | Include evaluations |
| Accuracy | bool? | Include accuracy |
| Opening | bool? | Include opening info |
Example - Export all blitz games:
using var client = new LichessClient();
var options = new ExportUserGamesOptions
{
PerfType = "blitz",
Max = 100,
Moves = true,
Opening = true
};
await foreach (var game in client.Games.StreamUserGamesAsync("DrNykterstein", options))
{
Console.WriteLine($"{game.Id}: {game.Players?.White?.User?.Name} vs {game.Players?.Black?.User?.Name}");
Console.WriteLine($" Opening: {game.Opening?.Name}");
Console.WriteLine($" Result: {game.Winner ?? "draw"}");
}Example - Games in a date range:
var options = new ExportUserGamesOptions
{
Since = DateTimeOffset.UtcNow.AddMonths(-1),
Until = DateTimeOffset.UtcNow,
Rated = true,
Sort = "dateDesc"
};
await foreach (var game in client.Games.StreamUserGamesAsync("username", options))
{
Console.WriteLine($"{game.CreatedAt}: {game.Id}");
}Export multiple games by their IDs.
IAsyncEnumerable<GameJson> StreamByIdsAsync(
IEnumerable<string> gameIds,
ExportGameOptions? options = null,
CancellationToken cancellationToken = default)Example:
using var client = new LichessClient();
var gameIds = new[] { "game1id1", "game2id2", "game3id3" };
await foreach (var game in client.Games.StreamByIdsAsync(gameIds))
{
Console.WriteLine($"{game.Id}: {game.Status}");
}Stream ongoing games of specified users in real-time.
IAsyncEnumerable<GameJson> StreamByUsersAsync(
IEnumerable<string> userIds,
bool withCurrentGames = false,
CancellationToken cancellationToken = default)Parameters:
| Name | Type | Description |
|---|---|---|
| userIds | IEnumerable | User IDs (up to 300) |
| withCurrentGames | bool | Include games already in progress |
Example:
using var client = new LichessClient();
using var cts = new CancellationTokenSource();
var topPlayers = new[] { "DrNykterstein", "Hikaru", "penguingm1" };
Console.WriteLine("Watching for games...");
await foreach (var game in client.Games.StreamByUsersAsync(topPlayers, withCurrentGames: true, cts.Token))
{
Console.WriteLine($"Game: {game.Id}");
Console.WriteLine($" {game.Players?.White?.User?.Name} vs {game.Players?.Black?.User?.Name}");
Console.WriteLine($" Status: {game.Status}");
}Stream a single game's moves in real-time.
IAsyncEnumerable<MoveStreamEvent> StreamGameMovesAsync(
string gameId,
CancellationToken cancellationToken = default)Example:
using var client = new LichessClient();
using var cts = new CancellationTokenSource();
await foreach (var evt in client.Games.StreamGameMovesAsync("AbCdEfGh", cts.Token))
{
Console.WriteLine($"FEN: {evt.Fen}");
Console.WriteLine($"Last Move: {evt.LastMove}");
if (evt.WhiteTime.HasValue)
Console.WriteLine($"White Time: {evt.WhiteTime}ms");
if (evt.BlackTime.HasValue)
Console.WriteLine($"Black Time: {evt.BlackTime}ms");
}Create a stream to watch multiple games with add/remove capability.
IAsyncEnumerable<GameStreamEvent> StreamByIdsAsync(
string streamId,
IEnumerable<string> gameIds,
CancellationToken cancellationToken = default)Add games to an existing stream.
Task AddGameIdsToStreamAsync(
string streamId,
IEnumerable<string> gameIds,
CancellationToken cancellationToken = default)Example:
using var client = new LichessClient();
using var cts = new CancellationTokenSource();
var streamId = Guid.NewGuid().ToString();
var initialGames = new[] { "game1234", "game5678" };
// Start watching
var watchTask = Task.Run(async () =>
{
await foreach (var evt in client.Games.StreamByIdsAsync(streamId, initialGames, cts.Token))
{
Console.WriteLine($"Game {evt.Id}: {evt.Fen}");
}
});
// Add more games later
await Task.Delay(5000);
await client.Games.AddGameIdsToStreamAsync(streamId, new[] { "newgame1" });
await watchTask;Get ongoing games of the authenticated user.
Task<IReadOnlyList<OngoingGame>> GetOngoingGamesAsync(
int count = 9,
CancellationToken cancellationToken = default)Example:
using var client = new LichessClient(token);
var games = await client.Games.GetOngoingGamesAsync(count: 20);
Console.WriteLine($"You have {games.Count} ongoing games:");
foreach (var game in games)
{
Console.WriteLine($" {game.GameId}: vs {game.Opponent?.Username} ({game.Speed})");
Console.WriteLine($" Your turn: {game.IsMyTurn}");
Console.WriteLine($" Time left: {game.SecondsLeft}s");
}Stream all bookmarked games.
Required Scope: OAuth authentication
IAsyncEnumerable<GameJson> StreamBookmarkedGamesAsync(
ExportBookmarksOptions? options = null,
CancellationToken cancellationToken = default)Example:
using var client = new LichessClient(token);
await foreach (var game in client.Games.StreamBookmarkedGamesAsync())
{
Console.WriteLine($"{game.Id}: {game.Players?.White?.User?.Name} vs {game.Players?.Black?.User?.Name}");
}Import a game from PGN.
Task<ImportGameResponse> ImportAsync(
string pgn,
CancellationToken cancellationToken = default)Example:
using var client = new LichessClient(token);
var pgn = @"
[Event ""Casual game""]
[White ""Player1""]
[Black ""Player2""]
1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O *
";
var result = await client.Games.ImportAsync(pgn);
Console.WriteLine($"Imported game: {result.Id}");
Console.WriteLine($"URL: {result.Url}");Export all games you have imported in PGN format.
Required Scope: OAuth authentication
Task<string> ExportImportedGamesAsync(CancellationToken cancellationToken = default)Example:
using var client = new LichessClient(token);
var allImportedPgn = await client.Games.ExportImportedGamesAsync();
// Save to file
await File.WriteAllTextAsync("my-imported-games.pgn", allImportedPgn);Fetch the messages posted in the public spectator chat of a game. No authentication required.
Task<IReadOnlyList<ChatMessage>> GetSpectatorChatAsync(
string gameId,
CancellationToken cancellationToken = default)Example:
using var client = new LichessClient();
var messages = await client.Games.GetSpectatorChatAsync("AbCdEfGh");
foreach (var msg in messages)
{
Console.WriteLine($"{msg.User}: {msg.Text}");
}Note: This returns the public spectator chat. For the private player chat (between the 2 players), use
Board.GetChatAsyncorBot.GetChatAsyncinstead.
- Users API - Get user information
- TV API - Watch featured games
- Board API - Board play (includes player chat)
- Streaming Guide - Patterns for handling streams