Welcome to the reference for the Lichess API! Lichess is free/libre, open-source chess server powered by volunteers and donations.
All requests are rate limited using various strategies, to ensure the API remains responsive for everyone. Only make one request at a time. If you receive an HTTP response with a 429 status, please wait a full minute before resuming API usage.
Some API endpoints stream their responses as Newline Delimited JSON a.k.a. nd-json, with one JSON object per line.
Here's a JavaScript utility function to help reading NDJSON streamed responses.
Read about the Lichess API authentication methods and code examples
Personal API access tokens allow you to quickly interact with Lichess API without going through an OAuth flow.
curl https://lichess.org/api/account -H "Authorization: Bearer {token}"
The authorization code flow with PKCE allows your users to login with Lichess.
Lichess supports unregistered and public clients (no client authentication, choose any unique client id).
The only accepted code challenge method is S256
.
Access tokens are long-lived (expect one year), unless they are revoked.
Refresh tokens are not supported.
See the documentation for the OAuth endpoints or the PKCE RFC for a precise protocol description.
Access tokens and authorization codes match ^[A-Za-z0-9_]+$
.
The length of tokens can be increased without notice. Make sure your application can handle at least 512 characters.
By convention tokens have a recognizable prefix, but do not rely on this.
Read and write account information and preferences. https://lichess.org/account/preferences/game-display
{- "id": "georges",
- "username": "Georges",
- "perfs": {
- "chess960": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "atomic": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "racingKings": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "ultraBullet": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "blitz": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "kingOfTheHill": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "bullet": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "correspondence": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "horde": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "puzzle": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "classical": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "rapid": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "storm": {
- "runs": 44,
- "score": 61
}, - "racer": {
- "runs": 44,
- "score": 61
}, - "streak": {
- "runs": 44,
- "score": 61
}
}, - "createdAt": 1290415680000,
- "disabled": false,
- "tosViolation": false,
- "profile": {
- "country": "EC",
- "location": "string",
- "bio": "Free bugs!",
- "firstName": "Thibault",
- "lastName": "Duplessis",
- "fideRating": 1500,
- "uscfRating": 1500,
- "ecfRating": 1500,
- "links": "github.com/ornicar\r\ntwitter.com/ornicar"
}, - "seenAt": 1522636452014,
- "patron": true,
- "verified": true,
- "playTime": {
- "total": 3296897,
- "tv": 12134
}, - "title": "NM",
- "count": {
- "all": 9265,
- "rated": 7157,
- "ai": 531,
- "draw": 340,
- "drawH": 331,
- "loss": 4480,
- "lossH": 4207,
- "win": 4440,
- "winH": 4378,
- "bookmark": 71,
- "playing": 6,
- "import": 66,
- "me": 0
}, - "streaming": false,
- "streamer": {
}, - "followable": true,
- "following": false,
- "blocking": false,
- "followsYou": false
}
{- "prefs": {
- "dark": true,
- "transp": false,
- "is3d": false,
- "theme": "blue",
- "pieceSet": "cburnett",
- "theme3d": "Black-White-Aluminium",
- "pieceSet3d": "Basic",
- "soundSet": "silent",
- "blindfold": 0,
- "autoQueen": 2,
- "autoThreefold": 2,
- "takeback": 3,
- "moretime": 3,
- "clockTenths": 1,
- "clockBar": true,
- "clockSound": true,
- "premove": true,
- "animation": 2,
- "captured": true,
- "follow": true,
- "highlight": true,
- "destination": true,
- "coords": 2,
- "replay": 2,
- "challenge": 4,
- "message": 3,
- "coordColor": 2,
- "submitMove": 4,
- "confirmResign": 1,
- "insightShare": 1,
- "keyboardMove": 0,
- "zen": 0,
- "moveEvent": 2,
- "rookCastle": 1
}, - "language": "en-GB"
}
Get the timeline events of the logged in user.
since | integer >= 1356998400070 Show events since this timestamp. |
nb | integer [ 1 .. 30 ] Default: 15 Max number of events to fetch. |
{- "entries": [
- {
- "type": "follow",
- "data": {
- "u1": "neio",
- "u2": "chess-network"
}, - "date": 1644232201429
}, - {
- "type": "team-join",
- "data": {
- "userId": "neio",
- "teamId": "coders"
}, - "date": 1644232201429
}, - {
- "type": "team-create",
- "data": {
- "userId": "neio",
- "teamId": "coders"
}, - "date": 1644232201429
}, - {
- "type": "forum-post",
- "data": {
- "userId": "neio",
- "topicId": "AAAAAAAN",
- "topicName": "World's Tallest LEGO Tower Completed in City Square",
- "postId": "AAAAAAAL"
}, - "date": 1644232201429
}, - {
- "type": "ublog-post",
- "data": {
- "userId": "neio",
- "id": "og5pkt1c",
- "slug": "gotta-go-fast",
- "title": "Gotta Go Fast"
}, - "date": 1644232201429
}, - {
- "type": "tour-join",
- "data": {
- "userId": "chess-network",
- "tourId": "Z24oxqgU",
- "tourName": "Daily Blitz Arena"
}, - "date": 1644232201429
}, - {
- "type": "game-end",
- "data": {
- "fullId": "iGkAXUdEfLZC",
- "perf": "correspondence",
- "opponent": "chess-network",
- "win": false
}, - "date": 1644232201429
}, - {
- "type": "simul-create",
- "data": {
- "userId": "neio",
- "simulId": "m3c0Wvu3",
- "simulName": "RCA 1st Jan simul"
}, - "date": 1644232201429
}, - {
- "type": "simul-join",
- "data": {
- "userId": "chess-network",
- "simulId": "m3c0Wvu3",
- "simulName": "RCA 1st Jan simul"
}, - "date": 1644232201429
}, - {
- "type": "study-like",
- "data": {
- "userId": "neio",
- "studyId": "ma5AvZ7o",
- "studyName": "Free wins | Danish Gambit"
}, - "date": 1644232201429
}, - {
- "type": "plan-start",
- "data": {
- "userId": "chess-network"
}, - "date": 1644232201429
}, - {
- "type": "plan-renew",
- "data": {
- "userId": "chess-network",
- "months": 64
}, - "date": 1644232201429
}, - {
- "type": "blog-post",
- "data": {
- "id": "ZUviXRIAACYAVtMm",
- "slug": "lichess-development-made-easy-with-gitpod",
- "title": "Lichess Development Made Easy With Gitpod"
}, - "date": 1644232201429
}, - {
- "type": "ublog-post-like",
- "data": {
- "userId": "neio",
- "id": "ZUviXRIAACYAVtMm",
- "title": "Lichess Development Made Easy With Gitpod"
}, - "date": 1644232201429
}, - {
- "type": "stream-start",
- "data": {
- "userId": "chess-network",
- "title": "Streamers Battle December !team | lichess.org"
}, - "date": 1644232201429
}
], - "users": {
- "neio": {
- "id": "neio",
- "name": "Neio",
- "title": "NM"
}, - "chess-network": {
- "id": "chess-network",
- "name": "Chess-Network",
- "title": "NM",
- "patron": true
}
}
}
Access registered users on Lichess. https://lichess.org/player
Read the online
, playing
and streaming
flags of several users.
This API is very fast and cheap on lichess side. So you can call it quite often (like once every 5 seconds).
Use it to track players and know when they're connected on lichess and playing games.
ids required | string Example: ids=aliquantus,chess-network,lovlas User IDs separated by commas. Up to 100 IDs. |
withGameIds | boolean Example: withGameIds=true Also return the ID of the game being played, if any, for each player, in a |
[- {
- "id": "aliquantus",
- "name": "Aliquantus"
}, - {
- "id": "chess-network",
- "name": "Chess-Network",
- "title": "NM",
- "online": true,
- "playing": true,
- "streaming": true,
- "patron": true
}
]
{- "bullet": [
- {
- "id": "bahadirozen",
- "username": "BahadirOzen",
- "perfs": {
- "bullet": {
- "rating": 3018,
- "progress": 18
}
}, - "online": true,
- "title": "FM"
}, - {
- "id": "penguingim1",
- "username": "penguingim1",
- "perfs": {
- "bullet": {
- "rating": 2983,
- "progress": -36
}
}, - "title": "GM",
- "online": true,
- "patron": true
}, - {
- "id": "night-king96",
- "username": "Night-King96",
- "perfs": {
- "bullet": {
- "rating": 2958,
- "progress": 35
}
}, - "title": "GM"
}
], - "blitz": [ ],
- "rapid": [ ],
- "classical": [ ],
- "ultraBullet": [ ],
- "chess960": [ ],
- "crazyhouse": [ ],
- "antichess": [ ],
- "atomic": [ ],
- "horde": [ ],
- "kingOfTheHill": [ ],
- "racingKings": [ ],
- "threeCheck": [ ]
}
Get the leaderboard for a single speed or variant (a.k.a. perfType
).
There is no leaderboard for correspondence or puzzles.
nb required | integer [ 1 .. 200 ] Example: 100 How many users to fetch |
perfType required | string Enum: "ultraBullet" "bullet" "blitz" "rapid" "classical" "chess960" "crazyhouse" "antichess" "atomic" "horde" "kingOfTheHill" "racingKings" "threeCheck" Example: bullet The speed or variant |
{- "users": [
- {
- "id": "bahadirozen",
- "username": "BahadirOzen",
- "perfs": {
- "bullet": {
- "rating": 3018,
- "progress": 18
}
}, - "online": true,
- "title": "FM"
}, - {
- "id": "penguingim1",
- "username": "penguingim1",
- "perfs": {
- "bullet": {
- "rating": 2983,
- "progress": -36
}
}, - "title": "GM",
- "online": true,
- "patron": true
}, - {
- "id": "night-king96",
- "username": "Night-King96",
- "perfs": {
- "bullet": {
- "rating": 2958,
- "progress": 35
}
}, - "title": "GM"
}
]
}
Read public data of a user.
If the request is authenticated with OAuth2,
then extra fields might be present in the response: followable
, following
, blocking
, followsYou
.
username required | string |
trophies | boolean Default: false Include user trophies |
{- "id": "georges",
- "username": "Georges",
- "perfs": {
- "chess960": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "atomic": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "racingKings": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "ultraBullet": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "blitz": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "kingOfTheHill": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "bullet": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "correspondence": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "horde": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "puzzle": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "classical": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "rapid": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "storm": {
- "runs": 44,
- "score": 61
}, - "racer": {
- "runs": 44,
- "score": 61
}, - "streak": {
- "runs": 44,
- "score": 61
}
}, - "createdAt": 1290415680000,
- "disabled": false,
- "tosViolation": false,
- "profile": {
- "country": "EC",
- "location": "string",
- "bio": "Free bugs!",
- "firstName": "Thibault",
- "lastName": "Duplessis",
- "fideRating": 1500,
- "uscfRating": 1500,
- "ecfRating": 1500,
- "links": "github.com/ornicar\r\ntwitter.com/ornicar"
}, - "seenAt": 1522636452014,
- "patron": true,
- "verified": true,
- "playTime": {
- "total": 3296897,
- "tv": 12134
}, - "title": "NM",
- "count": {
- "all": 9265,
- "rated": 7157,
- "ai": 531,
- "draw": 340,
- "drawH": 331,
- "loss": 4480,
- "lossH": 4207,
- "win": 4440,
- "winH": 4378,
- "bookmark": 71,
- "playing": 6,
- "import": 66,
- "me": 0
}, - "streaming": false,
- "streamer": {
}, - "followable": true,
- "following": false,
- "blocking": false,
- "followsYou": false
}
Read rating history of a user, for all perf types.
There is at most one entry per day.
Format of an entry is [year, month, day, rating]
.
month
starts at zero (January).
username required | string |
[- {
- "name": "Bullet",
- "points": [
- [
- 2011,
- 0,
- 8,
- 1472
], - [
- 2011,
- 0,
- 9,
- 1332
], - [
- 2011,
- 8,
- 12,
- 1314
]
]
}, - {
- "name": "Blitz",
- "points": [
- [
- 2011,
- 7,
- 29,
- 1332
]
]
}
]
Read performance statistics of a user, for a single performance. Similar to the performance pages on the website.
username required | string |
perf required | string (PerfType) Enum: "ultraBullet" "bullet" "blitz" "rapid" "classical" "correspondence" "chess960" "crazyhouse" "antichess" "atomic" "horde" "kingOfTheHill" "racingKings" "threeCheck" |
{- "perf": {
- "glicko": {
- "rating": 1672.42,
- "deviation": 45.13,
- "provisional": false
}, - "nb": 5692,
- "progress": -27
}, - "rank": 98121,
- "percentile": 69.7,
- "stat": {
- "perfType": {
- "key": "bullet",
- "name": "Bullet"
}, - "highest": {
- "int": 1902,
- "at": "2021-05-31T08:58:53.701Z",
- "gameId": "YEDqtwig"
}, - "lowest": {
- "int": 1417,
- "at": "2016-06-28T13:54:39.656Z",
- "gameId": "rNM4J1GJ"
}, - "bestWins": {
- "results": [
- {
- "opInt": 2238,
- "opId": {
- "id": "hyperdragon84",
- "name": "HyperDragon84"
}, - "at": "2019-06-19T17:09:05.187Z",
- "gameId": "DGB53z9w"
}, - {
- "opInt": 2089,
- "opId": {
- "id": "osipov",
- "name": "osipov"
}, - "at": "2017-06-18T09:46:05.016Z",
- "gameId": "gurRhuMi"
}, - {
- "opInt": 2071,
- "opId": {
- "id": "spark50",
- "name": "Spark50"
}, - "at": "2020-07-04T08:36:12.948Z",
- "gameId": "a93Dk1mv"
}, - {
- "opInt": 2045,
- "opId": {
- "id": "yasha43",
- "name": "Yasha43"
}, - "at": "2021-05-17T14:01:41.098Z",
- "gameId": "j3jZnGTr"
}, - {
- "opInt": 2034,
- "opId": {
- "id": "midedu",
- "name": "midedu"
}, - "at": "2020-06-27T17:32:47.001Z",
- "gameId": "OiaMVLQ8"
}
]
}, - "worstLosses": {
- "results": [
- {
- "opInt": 1186,
- "opId": {
- "id": "happy0",
- "name": "Happy0"
}, - "at": "2016-07-07T19:48:29.077Z",
- "gameId": "Q01bbiN4"
}, - {
- "opInt": 1197,
- "opId": {
- "id": "kazmankiller86",
- "name": "KazmanKiller86"
}, - "at": "2016-10-16T14:21:37.748Z",
- "gameId": "Aivqh9Sp"
}, - {
- "opInt": 1201,
- "opId": {
- "id": "artem555",
- "name": "artem555"
}, - "at": "2016-08-28T16:21:30.923Z",
- "gameId": "tiRAbhnX"
}, - {
- "opInt": 1265,
- "opId": {
- "id": "arcenuu",
- "name": "Arcenuu"
}, - "at": "2016-12-24T14:28:03.866Z",
- "gameId": "A68wUOoh"
}, - {
- "opInt": 1283,
- "opId": {
- "id": "amritalib76",
- "name": "Amritalib76"
}, - "at": "2018-06-26T09:55:39.354Z",
- "gameId": "sbNVikmo"
}
]
}, - "count": {
- "all": 5858,
- "rated": 5688,
- "win": 2789,
- "loss": 2806,
- "draw": 263,
- "tour": 654,
- "berserk": 1,
- "opAvg": 1671.44,
- "seconds": 784886,
- "disconnects": 0
}, - "resultStreak": {
- "win": {
- "cur": {
- "v": 0
}, - "max": {
- "v": 11,
- "from": {
- "at": "2021-06-14T15:38:50.681Z",
- "gameId": "wTX2IExo"
}, - "to": {
- "at": "2021-06-15T18:41:46.970Z",
- "gameId": "1z4rrjgw"
}
}
}, - "loss": {
- "cur": {
- "v": 3,
- "from": {
- "at": "2021-06-29T17:53:23.642Z",
- "gameId": "pfcnjgik"
}, - "to": {
- "at": "2021-06-29T18:04:48.358Z",
- "gameId": "6sPaGL8T"
}
}, - "max": {
- "v": 14,
- "from": {
- "at": "2018-06-11T14:43:39.296Z",
- "gameId": "1fc9dqun"
}, - "to": {
- "at": "2018-06-11T15:10:30.908Z",
- "gameId": "Nzy6UgwY"
}
}
}
}, - "playStreak": {
- "nb": {
- "cur": {
- "v": 0
}, - "max": {
- "v": 118,
- "from": {
- "at": "2018-06-11T10:32:21.248Z",
- "gameId": "UAsNnJbN"
}, - "to": {
- "at": "2018-06-11T15:13:01.193Z",
- "gameId": "T7fHRaFG"
}
}
}, - "time": {
- "cur": {
- "v": 0
}, - "max": {
- "v": 12683,
- "from": {
- "at": "2018-06-12T14:11:14.021Z",
- "gameId": "IrZCAW58"
}, - "to": {
- "at": "2018-06-12T18:02:57.010Z",
- "gameId": "RNF1mQ68"
}
}
}, - "lastDate": "2021-06-29T18:04:48.358Z"
}
}
}
Get up to 300 users by their IDs. Users are returned in the same order as the IDs.
The method is POST
to allow a longer list of IDs to be sent in the request body.
Please do not try to download all the Lichess users with this endpoint, or any other endpoint. An API is not a way to fully export a website. We do not provide a full download of the Lichess users.
This endpoint is limited to 8,000 users every 10 minutes, and 120,000 every day.
User IDs separated by commas.
aliquantus,chess-network,lovlas
[- {
- "id": "georges",
- "username": "Georges",
- "perfs": {
- "chess960": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "atomic": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "racingKings": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "ultraBullet": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "blitz": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "kingOfTheHill": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "bullet": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "correspondence": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "horde": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "puzzle": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "classical": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "rapid": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "storm": {
- "runs": 44,
- "score": 61
}, - "racer": {
- "runs": 44,
- "score": 61
}, - "streak": {
- "runs": 44,
- "score": 61
}
}, - "createdAt": 1290415680000,
- "disabled": false,
- "tosViolation": false,
- "profile": {
- "country": "EC",
- "location": "string",
- "bio": "Free bugs!",
- "firstName": "Thibault",
- "lastName": "Duplessis",
- "fideRating": 1500,
- "uscfRating": 1500,
- "ecfRating": 1500,
- "links": "github.com/ornicar\r\ntwitter.com/ornicar"
}, - "seenAt": 1522636452014,
- "patron": true,
- "verified": true,
- "playTime": {
- "total": 3296897,
- "tv": 12134
}, - "title": "NM"
}
]
Get basic info about currently streaming users.
This API is very fast and cheap on lichess side. So you can call it quite often (like once every 5 seconds).
[- {
- "id": "chess-network",
- "name": "Chess-Network",
- "title": "NM",
- "patron": true,
- "stream": {
- "service": "twitch",
- "status": "Tuesday night 🐴 chess | lichess.org",
- "lang": "en"
}, - "streamer": {
- "name": "ChessNetwork",
- "headline": "Chess with commentary, tournament competition, viewer interaction, and more.",
- "description": "I'm a self-taught National Master in chess from Pennsylvania, USA who was introduced to the game by my father in 1988 at age 8. I've been playing since, enjoy teaching, and have been a broadcaster of all things chess since 2011. It's my hope your experience with this stream is both fun and educational. 😎 -Jerry",
}
}
]
Get total number of games, and current score, of any two users.
If the matchup
flag is provided, and the users are currently playing, also gets the current match game number and scores.
user1 required | string |
user2 required | string |
matchup | boolean Whether to get the current match data, if any |
{- "users": {
- "neio": 201.5,
- "thibault": 144.5
}, - "nbGames": 346,
- "matchup": {
- "users": {
- "neio": 44,
- "thibault": 43
}, - "nbGames": 87
}
}
Provides autocompletion options for an incomplete username.
term required | string >= 3 characters The beginning of a username |
object | boolean Default: false
|
friend | boolean Returns followed players matching |
{- "result": [
- {
- "id": "chess-network",
- "name": "Chess-Network",
- "title": "NM",
- "patron": true,
- "online": true
}
]
}
Add a private note available only to you about this account.
username required | string Example: thibault |
text required | string The contents of the note |
{- "ok": true
}
Get the private notes that you have added for a user.
username required | string Example: thibault |
[- {
- "from": {
- "name": "thibault",
- "patron": true,
- "id": "thibault"
}, - "to": {
- "name": "DrNykterstein",
- "title": "GM",
- "patron": true,
- "id": "drnykterstein"
}, - "text": "This guy is good at chess",
- "date": 1690585691898
}
]
Users are streamed as ndjson.
{- "id": "georges",
- "username": "Georges",
- "perfs": {
- "chess960": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "atomic": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "racingKings": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "ultraBullet": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "blitz": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "kingOfTheHill": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "bullet": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "correspondence": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "horde": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "puzzle": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "classical": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "rapid": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "storm": {
- "runs": 44,
- "score": 61
}, - "racer": {
- "runs": 44,
- "score": 61
}, - "streak": {
- "runs": 44,
- "score": 61
}
}, - "createdAt": 1290415680000,
- "disabled": false,
- "tosViolation": false,
- "profile": {
- "country": "EC",
- "location": "string",
- "bio": "Free bugs!",
- "firstName": "Thibault",
- "lastName": "Duplessis",
- "fideRating": 1500,
- "uscfRating": 1500,
- "ecfRating": 1500,
- "links": "github.com/ornicar\r\ntwitter.com/ornicar"
}, - "seenAt": 1522636452014,
- "patron": true,
- "verified": true,
- "playTime": {
- "total": 3296897,
- "tv": 12134
}, - "title": "NM",
- "count": {
- "all": 9265,
- "rated": 7157,
- "ai": 531,
- "draw": 340,
- "drawH": 331,
- "loss": 4480,
- "lossH": 4207,
- "win": 4440,
- "winH": 4378,
- "bookmark": 71,
- "playing": 6,
- "import": 66,
- "me": 0
}, - "streaming": false,
- "streamer": {
}, - "followable": true,
- "following": false,
- "blocking": false,
- "followsYou": false
}
Access games played on Lichess. https://lichess.org/games
Download one game in either PGN or JSON format.
Ongoing games are delayed by a few seconds ranging from 3 to 60 depending on the time control, as to prevent cheat bots from using this API.
gameId required | string The game ID (8 characters). |
moves | boolean Default: true Include the PGN moves. |
pgnInJson | boolean Default: false Include the full PGN within the JSON response, in a |
tags | boolean Default: true Include the PGN tags. |
clocks | boolean Default: true Include clock status when available. Either as PGN comments: Or in a |
evals | boolean Default: true Include analysis evaluations and comments, when available. Either as PGN comments: Or in an |
accuracy | |
opening | boolean Default: true Include the opening name. Example: |
division | boolean Default: true Plies which mark the beginning of the middlegame and endgame. Only available in JSON |
literate | boolean Default: false Insert textual annotations in the PGN about the opening, analysis variations, mistakes, and game termination. Example: |
players | string URL of a text file containing real names and ratings, to replace Lichess usernames and ratings in the PGN. Example: https://gist.githubusercontent.com/ornicar/6bfa91eb61a2dcae7bcd14cce1b2a4eb/raw/768b9f6cc8a8471d2555e47ba40fb0095e5fba37/gistfile1.txt |
Download the ongoing game, or the last game played, of a user. Available in either PGN or JSON format.
Ongoing games are delayed by a few seconds ranging from 3 to 60 depending on the time control, as to prevent cheat bots from using this API.
username required | string |
moves | boolean Default: true Include the PGN moves. |
pgnInJson | boolean Default: false Include the full PGN within the JSON response, in a |
tags | boolean Default: true Include the PGN tags. |
clocks | boolean Default: true Include clock status when available. Either as PGN comments: Or in a |
evals | boolean Default: true Include analysis evaluations and comments, when available. Either as PGN comments: Or in an |
accuracy | |
opening | boolean Default: true Include the opening name. Example: |
division | boolean Default: false Plies which mark the beginning of the middlegame and endgame. Only available in JSON |
literate | boolean Default: false Insert textual annotations in the PGN about the opening, analysis variations, mistakes, and game termination. Example: |
players | string URL of a text file containing real names and ratings, to replace Lichess usernames and ratings in the PGN. Example: https://gist.githubusercontent.com/ornicar/6bfa91eb61a2dcae7bcd14cce1b2a4eb/raw/768b9f6cc8a8471d2555e47ba40fb0095e5fba37/gistfile1.txt |
Download all games of any user in PGN or ndjson format.
Games are sorted by reverse chronological order (most recent first).
We recommend streaming the response, for it can be very long. https://lichess.org/@/german11 for instance has more than 500,000 games.
The game stream is throttled, depending on who is making the request:
username required | string The user name. |
since | integer >= 1356998400070 Download games played since this timestamp. Defaults to account creation date. |
until | integer >= 1356998400070 Download games played until this timestamp. Defaults to now. |
max | integer >= 1 How many games to download. Leave empty to download all games. |
vs | string [Filter] Only games played against this opponent |
rated | boolean [Filter] Only rated ( |
perfType | string Default: null Enum: "ultraBullet" "bullet" "blitz" "rapid" "classical" "correspondence" "chess960" "crazyhouse" "antichess" "atomic" "horde" "kingOfTheHill" "racingKings" "threeCheck" [Filter] Only games in these speeds or variants. Multiple perf types can be specified, separated by a comma. Example: blitz,rapid,classical |
color | string Enum: "white" "black" [Filter] Only games played as this color. |
analysed | boolean [Filter] Only games with or without a computer analysis available |
moves | boolean Default: true Include the PGN moves. |
pgnInJson | boolean Default: false Include the full PGN within the JSON response, in a |
tags | boolean Default: true Include the PGN tags. |
clocks | boolean Default: false Include clock status when available. Either as PGN comments: Or in a |
evals | boolean Default: false Include analysis evaluations and comments, when available. Either as PGN comments: Or in an |
accuracy | |
opening | boolean Default: false Include the opening name. Example: |
division | boolean Default: false Plies which mark the beginning of the middlegame and endgame. Only available in JSON |
ongoing | boolean Default: false Ongoing games are delayed by a few seconds ranging from 3 to 60 depending on the time control, as to prevent cheat bots from using this API. |
finished | boolean Default: true Include finished games. Set to |
literate | boolean Default: false Insert textual annotations in the PGN about the opening, analysis variations, mistakes, and game termination. Example: |
lastFen | boolean Default: false Include the FEN notation of the last position of the game. The response type must be set to |
players | string URL of a text file containing real names and ratings, to replace Lichess usernames and ratings in the PGN. Example: https://gist.githubusercontent.com/ornicar/6bfa91eb61a2dcae7bcd14cce1b2a4eb/raw/768b9f6cc8a8471d2555e47ba40fb0095e5fba37/gistfile1.txt |
sort | string Default: "dateDesc" Enum: "dateAsc" "dateDesc" Sort order of the games. |
Download games by IDs in PGN or ndjson format, depending on the request Accept
header.
Games are sorted by reverse chronological order (most recent first)
The method is POST
so a longer list of IDs can be sent in the request body.
300 IDs can be submitted.
Ongoing games are delayed by a few seconds ranging from 3 to 60 depending on the time control, as to prevent cheat bots from using this API.
moves | boolean Default: true Include the PGN moves. |
pgnInJson | boolean Default: false Include the full PGN within the JSON response, in a |
tags | boolean Default: true Include the PGN tags. |
clocks | boolean Default: false Include clock status when available. Either as PGN comments: Or in a |
evals | boolean Default: false Include analysis evaluations and comments, when available. Either as PGN comments: Or in an |
accuracy | |
opening | boolean Default: false Include the opening name. Example: |
division | boolean Default: false Plies which mark the beginning of the middlegame and endgame. Only available in JSON |
literate | boolean Default: false Insert textual annotations in the PGN about the opening, analysis variations, mistakes, and game termination. Example: |
players | string URL of a text file containing real names and ratings, to replace Lichess usernames and ratings in the PGN. Example: https://gist.githubusercontent.com/ornicar/6bfa91eb61a2dcae7bcd14cce1b2a4eb/raw/768b9f6cc8a8471d2555e47ba40fb0095e5fba37/gistfile1.txt |
Game IDs separated by commas. Up to 300.
TJxUmbWK,4OtIh2oh,ILwozzRZ
Stream the games played between a list of users, in real time. Only games where both players are part of the list are included.
The stream emits an event each time a game is started or finished.
To also get all current ongoing games at the beginning of the stream, use the withCurrentGames
flag.
Games are streamed as ndjson.
Maximum number of users: 300.
The method is POST
so a longer list of IDs can be sent in the request body.
withCurrentGames | boolean Default: false Include the already started games at the beginning of the stream. |
Up to 300 user IDs separated by commas.
Example: aliquantus,chess-network,lovlas
[- {
- "id": "A5fcMO3k",
- "rated": true,
- "variant": "standard",
- "speed": "bullet",
- "perf": "bullet",
- "createdAt": 1525789431889,
- "status": 20,
- "statusName": "started",
- "clock": {
- "initial": 60,
- "increment": 0,
- "totalTime": 60
}, - "players": {
- "white": {
- "userId": "kastorcito",
- "rating": 2617
}, - "black": {
- "userId": "er_or",
- "rating": 2288
}
}
}
]
Creates a stream of games from an arbitrary streamId, and a list of game IDs.
The stream first outputs the games that already exists, then emits an event each time a game is started or finished.
Games are streamed as ndjson.
Maximum number of games: 500 for anonymous requests, or 1000 for OAuth2 authenticated requests.
While the stream is open, it is possible to add new game IDs to watch.
streamId required | string Example: myAppName-someRandomId Arbitrary stream ID that you can later use to add game IDs to the stream. |
Up to 500 or 1000 game IDs separated by commas.
Example: gameId01,gameId02,gameId03
[- {
- "id": "A5fcMO3k",
- "rated": true,
- "variant": "standard",
- "speed": "bullet",
- "perf": "bullet",
- "createdAt": 1525789431889,
- "status": 20,
- "statusName": "started",
- "clock": {
- "initial": 60,
- "increment": 0,
- "totalTime": 60
}, - "players": {
- "white": {
- "userId": "kastorcito",
- "rating": 2617
}, - "black": {
- "userId": "er_or",
- "rating": 2288
}
}
}
]
Add new game IDs for an existing stream to watch. The stream will immediately outputs the games that already exists, then emit an event each time a game is started or finished.
streamId required |
Up to 500 or 1000 game IDs separated by commas.
Example: gameId04,gameId05,gameId06
{- "ok": true
}
Get the ongoing games of the current user. Real-time and correspondence games are included. The most urgent games are listed first.
nb | integer [ 1 .. 50 ] Default: 9 Max number of games to fetch |
{- "nowPlaying": [
- {
- "gameId": "rCRw1AuO",
- "fullId": "rCRw1AuOvonq",
- "color": "black",
- "fen": "r1bqkbnr/pppp2pp/2n1pp2/8/8/3PP3/PPPB1PPP/RN1QKBNR w KQkq - 2 4",
- "hasMoved": true,
- "isMyTurn": false,
- "lastMove": "b8c6",
- "opponent": {
- "id": "philippe",
- "rating": 1790,
- "username": "Philippe"
}, - "perf": "correspondence",
- "rated": false,
- "secondsLeft": 1209600,
- "source": "friend",
- "speed": "correspondence",
- "variant": {
- "key": "standard",
- "name": "Standard"
}
}
]
}
Stream positions and moves of any ongoing game, in ndjson.
A description of the game is sent as a first message. Then a message is sent each time a move is played. Finally a description of the game is sent when it finishes, and the stream is closed.
Ongoing games are delayed by a few seconds ranging from 3 to 60 depending on the time control, as to prevent cheat bots from using this API.
No more than 8 game streams can be opened at the same time from the same IP address.
id required | string Example: LuGQwhBb |
[- {
- "id": "LuGQwhBb",
- "variant": {
- "key": "standard",
- "name": "Standard",
- "short": "Std"
}, - "speed": "blitz",
- "perf": "blitz",
- "rated": true,
- "initialFen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
- "fen": "rnbqkb1r/1p1ppppp/p6n/2p4Q/8/1P2P3/P1PP1PPP/RNB1KBNR w KQkq - 0 4",
- "player": "white",
- "turns": 6,
- "startedAtTurn": 0,
- "source": "pool",
- "status": {
- "id": 20,
- "name": "started"
}, - "createdAt": 1620029815106,
- "lastMove": "c7c5",
- "players": {
- "white": {
- "user": {
- "name": "ARM-777777",
- "title": "GM",
- "id": "arm-777777"
}, - "rating": 3120
}, - "black": {
- "user": {
- "name": "Flash_Marafon",
- "id": "flash_marafon"
}, - "rating": 3015
}
}
}, - {
- "fen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w",
- "wc": 180,
- "bc": 180
}, - {
- "fen": "rnbqkbnr/pppppppp/8/8/8/4P3/PPPP1PPP/RNBQKBNR b",
- "lm": "e2e3",
- "wc": 180,
- "bc": 180
}, - {
- "fen": "rnbqkb1r/pppppppp/7n/8/8/4P3/PPPP1PPP/RNBQKBNR w",
- "lm": "g8h6",
- "wc": 180,
- "bc": 180
}, - {
- "fen": "rnbqkb1r/pppppppp/7n/8/8/1P2P3/P1PP1PPP/RNBQKBNR b",
- "lm": "b2b3",
- "wc": 177,
- "bc": 180
}, - {
- "fen": "rnbqkb1r/1ppppppp/p6n/8/8/1P2P3/P1PP1PPP/RNBQKBNR w",
- "lm": "a7a6",
- "wc": 177,
- "bc": 177
}
]
Import a game from PGN. See https://lichess.org/paste.
Rate limiting: 200 games per hour for OAuth requests, 100 games per hour for anonymous requests.
To broadcast ongoing games, consider pushing to a broadcast instead.
To analyse a position or a line, just construct an analysis board URL: https://lichess.org/analysis/pgn/e4_e5_Nf3_Nc6_Bc4_Bc5_Bxf7+
A single game to import
pgn | string The PGN. It can contain only one game. Most standard tags are supported. |
{- "id": "R6iLjwz5",
}
Access Lichess TV channels and games. https://lichess.org/tv & https://lichess.org/games
Get basic info about the best games being played for each speed and variant, but also computer games and bot games.
See lichess.org/tv.
{- "bot": {
- "user": {
- "id": "leelachess",
- "name": "LeelaChess",
- "title": "BOT"
}, - "rating": 2660,
- "gameId": "Zznv9MIl",
- "color": "black"
}, - "blitz": {
- "user": {
- "id": "lekkerkortook",
- "name": "LekkerKortOok"
}, - "rating": 2603,
- "gameId": "hTJ4v7Mp",
- "color": "black"
}, - "racingKings": {
- "user": {
- "id": "chesslo21",
- "name": "chesslo21"
}, - "rating": 2123,
- "gameId": "lgCDl5Of",
- "color": "white"
}, - "ultraBullet": {
- "user": {
- "id": "farmville",
- "name": "Farmville"
}, - "rating": 2338,
- "gameId": "NEY6OQ32",
- "color": "white"
}, - "bullet": {
- "user": {
- "id": "nurmibrah",
- "name": "nurmiBrah"
}, - "rating": 2499,
- "gameId": "5LgyE516",
- "color": "black"
}, - "classical": {
- "user": {
- "id": "holden_m_j_thomas",
- "name": "Holden_M_J_Thomas"
}, - "rating": 1806,
- "gameId": "k3oLby6N",
- "color": "white"
}, - "threeCheck": {
- "user": {
- "id": "pepellou",
- "name": "pepellou",
- "patron": true
}, - "rating": 1978,
- "gameId": "Og5RCvmu",
- "color": "black"
}, - "antichess": {
- "user": {
- "id": "maria-bakkar",
- "name": "maria-bakkar"
}, - "rating": 2103,
- "gameId": "toCr41yx",
- "color": "black"
}, - "computer": {
- "user": {
- "id": "oh_my_goat_im_so_bat",
- "name": "oh_my_goat_Im_so_bat"
}, - "rating": 2314,
- "gameId": "TkI4qZxu",
- "color": "black"
}, - "horde": {
- "user": {
- "id": "habitualchess",
- "name": "HabitualChess"
}, - "rating": 1803,
- "gameId": "oMofN63H",
- "color": "white"
}, - "rapid": {
- "user": {
- "id": "denpayd",
- "name": "DenpaYD"
}, - "rating": 2289,
- "gameId": "IcWOl8ee"
}, - "atomic": {
- "user": {
- "id": "meetyourdemise",
- "name": "MeetYourDemise"
}, - "rating": 2210,
- "gameId": "tvMxtCMN",
- "color": "white"
}, - "crazyhouse": {
- "user": {
- "id": "mathace",
- "name": "mathace"
}, - "rating": 2397,
- "gameId": "i3gTZlUb",
- "color": "black"
}, - "chess960": {
- "user": {
- "id": "voja_7",
- "name": "voja_7"
}, - "rating": 1782,
- "gameId": "lrXLcedu",
- "color": "white"
}, - "kingOfTheHill": {
- "user": {
- "id": "nadime",
- "name": "Nadime"
}, - "rating": 1500,
- "gameId": "DsQn8aEV",
- "color": "white"
}, - "topRated": {
- "user": {
- "id": "lekkerkortook",
- "name": "LekkerKortOok"
}, - "rating": 2603,
- "gameId": "hTJ4v7Mp",
- "color": "black"
}
}
{- "t": "featured",
- "d": {
- "id": "qVSOPtMc",
- "orientation": "black",
- "players": [
- {
- "color": "white",
- "user": {
- "name": "lizen9",
- "id": "lizen9",
- "title": "GM"
}, - "rating": 2531
}, - {
- "color": "black",
- "user": {
- "name": "lizen29",
- "title": "WGM",
- "id": "lizen29"
}, - "rating": 2594
}
], - "fen": "rnbqk1r1/ppp1ppbp/8/N2p2p1/8/1PQPP3/P1P2PPn/R1B1K1NR"
}
}
Get a list of ongoing games for a given TV channel. Similar to lichess.org/games.
Available in PGN or ndjson format, depending on the request Accept
header.
channel required | string The name of the channel in camel case. |
nb | number [ 1 .. 30 ] Default: 10 Number of games to fetch. |
moves | boolean Default: true Include the PGN moves. |
pgnInJson | boolean Default: false Include the full PGN within the JSON response, in a |
tags | boolean Default: true Include the PGN tags. |
clocks | boolean Default: false Include clock status when available. Either as PGN comments: Or in a |
opening | boolean Default: false Include the opening name. Example: |
Access Lichess puzzle history and dashboard.
Our collection of puzzles is in the public domain, you can download it here. For a list of our puzzle themes with their description, check out the theme translation file. The daily puzzle can be posted in your slack workspace.
Get the daily Lichess puzzle in JSON format.
Alternatively, you can post it in your slack workspace.
{- "game": {
- "clock": "10+0",
- "id": "VpVdGbna",
- "perf": {
- "key": "rapid",
- "name": "Rapid"
}, - "pgn": "d4 Nf6 Nf3 g6 Nc3 d6 e4 c5 Be3 cxd4 Bxd4 Nc6 Be3 Qa5 Bd2 Bg7 Be2 O-O O-O Qb6 Rb1 Bg4 h3 Bxf3 Bxf3 Nd4 Be3 Nxf3+ Qxf3 Qc6 Bd4 a6 Bxf6 Bxf6 Nd5 Qxc2 Nxf6+ exf6 Qxf6 Qxe4 Qxd6 Rad8 Qb6 Rfe8 Rfe1 Qxe1+ Rxe1 Rxe1+ Kh2 Rd2 Kg3 Ree2 Qxb7 Rxb2 Qxa6 Rxa2 Qc8+ Kg7 Qc3+ Kg8 Qc5 Rxf2 Qc8+ Kg7 Qc3+ Kh6 Qe3+ Kg7 Qe5+ Kf8 Qh8+ Ke7 Qe5+ Kf8 Qb8+ Kg7 Qe5+ f6 Qe7+ Kh6 Qf8+ Kg5 h4+ Kh5 Qc5+ f5 Qc1 Rxg2+ Kh3 Rh2+ Kg3 Rag2+ Kf3 Rg4 Qd1 Rhxh4 Kf2 Rh2+ Kf3 Rh3+ Ke2 Rg2+ Kf1+ Rg4 Kf2 g5 Qd8 h6 Qe8+ Kh4 Kf1 h5 Qe1+ Rhg3 Qe5 f4 Qe1 f3 Kf2 Rf4 Qh1+ Rh3 Qe1 g4",
- "players": [
- {
- "color": "white",
- "name": "borska (2013)",
- "userId": "borska"
}, - {
- "color": "black",
- "name": "Xxn00bkillar69xX (1990)",
- "userId": "xxn00bkillar69xx"
}
], - "rated": true
}, - "puzzle": {
- "id": "K69di",
- "initialPly": 123,
- "plays": 1970,
- "rating": 2022,
- "solution": [
- "e1e7",
- "f4f6",
- "e7f6"
], - "themes": [
- "short",
- "queenRookEndgame",
- "endgame",
- "mateIn2"
]
}
}
Get a single Lichess puzzle in JSON format.
id required | string The puzzle ID |
{- "game": {
- "clock": "10+0",
- "id": "VpVdGbna",
- "perf": {
- "key": "rapid",
- "name": "Rapid"
}, - "pgn": "d4 Nf6 Nf3 g6 Nc3 d6 e4 c5 Be3 cxd4 Bxd4 Nc6 Be3 Qa5 Bd2 Bg7 Be2 O-O O-O Qb6 Rb1 Bg4 h3 Bxf3 Bxf3 Nd4 Be3 Nxf3+ Qxf3 Qc6 Bd4 a6 Bxf6 Bxf6 Nd5 Qxc2 Nxf6+ exf6 Qxf6 Qxe4 Qxd6 Rad8 Qb6 Rfe8 Rfe1 Qxe1+ Rxe1 Rxe1+ Kh2 Rd2 Kg3 Ree2 Qxb7 Rxb2 Qxa6 Rxa2 Qc8+ Kg7 Qc3+ Kg8 Qc5 Rxf2 Qc8+ Kg7 Qc3+ Kh6 Qe3+ Kg7 Qe5+ Kf8 Qh8+ Ke7 Qe5+ Kf8 Qb8+ Kg7 Qe5+ f6 Qe7+ Kh6 Qf8+ Kg5 h4+ Kh5 Qc5+ f5 Qc1 Rxg2+ Kh3 Rh2+ Kg3 Rag2+ Kf3 Rg4 Qd1 Rhxh4 Kf2 Rh2+ Kf3 Rh3+ Ke2 Rg2+ Kf1+ Rg4 Kf2 g5 Qd8 h6 Qe8+ Kh4 Kf1 h5 Qe1+ Rhg3 Qe5 f4 Qe1 f3 Kf2 Rf4 Qh1+ Rh3 Qe1 g4",
- "players": [
- {
- "color": "white",
- "name": "borska (2013)",
- "userId": "borska"
}, - {
- "color": "black",
- "name": "Xxn00bkillar69xX (1990)",
- "userId": "xxn00bkillar69xx"
}
], - "rated": true
}, - "puzzle": {
- "id": "K69di",
- "initialPly": 123,
- "plays": 1970,
- "rating": 2022,
- "solution": [
- "e1e7",
- "f4f6",
- "e7f6"
], - "themes": [
- "short",
- "queenRookEndgame",
- "endgame",
- "mateIn2"
]
}
}
Download your puzzle activity in ndjson format.
Puzzle activity is sorted by reverse chronological order (most recent first)
We recommend streaming the response, for it can be very long.
max | integer >= 1 How many entries to download. Leave empty to download all activity. |
before | integer >= 1356998400070 Download entries before this timestamp. Defaults to now. Use |
{- "date": 1514505150384,
- "win": true,
- "puzzle": {
- "id": "K69di",
- "fen": "6k1/6b1/8/4p1N1/7Q/2P2pP1/1Pq2P1K/8 w - - 14 49",
- "plays": 1970,
- "rating": 2022,
- "solution": [
- "e1e7",
- "f4f6",
- "e7f6"
], - "themes": [
- "short",
- "queenRookEndgame",
- "endgame",
- "mateIn2"
]
}
}
Download your puzzle dashboard as JSON.
Also includes all puzzle themes played, with aggregated results.
Allows re-creating the improvement/strengths interfaces.
days required | integer >= 1 How many days to look back when aggregating puzzle results. 30 is sensible. |
{- "days": 30,
- "global": {
- "firstWins": 276,
- "nb": 501,
- "performance": 1570,
- "puzzleRatingAvg": 1523,
- "replayWins": 2
}, - "themes": {
- "advancedPawn": {
- "results": {
- "firstWins": 19,
- "nb": 39,
- "performance": 1438,
- "puzzleRatingAvg": 1476,
- "replayWins": 1
}, - "theme": "Advanced pawn"
}, - "anastasiaMate": {
- "results": {
- "firstWins": 5,
- "nb": 6,
- "performance": 1720,
- "puzzleRatingAvg": 1387,
- "replayWins": 0
}, - "theme": "Anastasia's mate"
}
}
}
Download the storm dashboard of any player as JSON.
Contains the aggregated highscores, and the history of storm runs aggregated by days.
Use ?days=0
if you only care about the highscores.
username required | string Username of the player |
days | integer [ 0 .. 365 ] Default: 30 How many days of history to return |
{- "high": {
- "allTime": 11,
- "day": 0,
- "month": 7,
- "week": 0
}, - "days": [
- {
- "_id": "2021/1/28",
- "combo": 8,
- "errors": 1,
- "highest": 1084,
- "moves": 9,
- "runs": 26,
- "score": 4,
- "time": 175
}, - {
- "_id": "2021/1/27",
- "combo": 14,
- "errors": 1,
- "highest": 1095,
- "moves": 15,
- "runs": 15,
- "score": 7,
- "time": 23
}, - {
- "_id": "2021/1/22",
- "combo": 14,
- "errors": 1,
- "highest": 1095,
- "moves": 15,
- "runs": 15,
- "score": 3,
- "time": 23
}
]
}
Create a new private puzzle race. The Lichess user who creates the race must join the race page, and manually start the race when enough players have joined.
{- "id": "Kj1t0",
}
Access and manage Lichess teams and their members. https://lichess.org/team
Get all swiss tournaments of a team.
Tournaments are sorted by reverse chronological order of start date (last starting first).
Tournaments are streamed as ndjson.
teamId required | string Example: coders |
max | integer >= 1 Default: 100 How many tournaments to download. |
{- "rated": true,
- "clock": {
- "increment": 0,
- "limit": 300
}, - "createdBy": "thibault",
- "id": "ZmKWCOye",
- "name": "Wang",
- "nbOngoing": 0,
- "nbPlayers": 0,
- "nbRounds": 2,
- "nextRound": {
- "at": "2020-05-11T12:23:18.233-06:00",
- "in": 600
}, - "round": 0,
- "startsAt": "2020-05-11T12:23:18.233-06:00",
- "status": "created",
- "variant": "standard",
- "isRecentlyFinished": false,
- "password": true,
- "stats": {
- "absences": 1608,
- "averageRating": 1588,
- "blackWins": 42541,
- "byes": 12,
- "draws": 0,
- "games": 42689,
- "whiteWins": 42837
}
}
Public info about a team. Includes the list of publicly visible leaders.
teamId required | string |
{- "id": "coders",
- "name": "Coders",
- "description": "There are 10 kinds of people in the world: those who understand binary, and the others.\r\n\r\nIf you want to join the team, prove (briefly) that you can code in the request message!",
- "open": false,
- "leaders": [
- {
- "id": "chess-network",
- "name": "Chess-Network",
- "title": "NM",
- "patron": true
}
], - "nbMembers": 3129
}
Paginator of the most popular teams.
page | number Default: 1 Example: page=1 |
{- "currentPage": 4,
- "maxPerPage": 15,
- "currentPageResults": [
- {
- "id": "coders",
- "name": "Coders",
- "description": "There are 10 kinds of people in the world: those who understand binary, and the others.\r\n\r\nIf you want to join the team, prove (briefly) that you can code in the request message!",
- "open": false,
- "leaders": [
- {
- "id": "chess-network",
- "name": "Chess-Network",
- "title": "NM",
- "patron": true
}
], - "nbMembers": 3129
}
], - "nbResults": 205194,
- "previousPage": 3,
- "nextPage": 5,
- "nbPages": 13680
}
All the teams a player is a member of.
username required | string Example: thibault |
[- {
- "id": "coders",
- "name": "Coders",
- "description": "There are 10 kinds of people in the world: those who understand binary, and the others.\r\n\r\nIf you want to join the team, prove (briefly) that you can code in the request message!",
- "open": false,
- "leaders": [
- {
- "id": "chess-network",
- "name": "Chess-Network",
- "title": "NM",
- "patron": true
}
], - "nbMembers": 3129
}
]
Paginator of team search results for a keyword.
text | string Example: text=coders |
page | number Default: 1 Example: page=1 |
{- "currentPage": 4,
- "maxPerPage": 15,
- "currentPageResults": [
- {
- "id": "coders",
- "name": "Coders",
- "description": "There are 10 kinds of people in the world: those who understand binary, and the others.\r\n\r\nIf you want to join the team, prove (briefly) that you can code in the request message!",
- "open": false,
- "leaders": [
- {
- "id": "chess-network",
- "name": "Chess-Network",
- "title": "NM",
- "patron": true
}
], - "nbMembers": 3129
}
], - "nbResults": 205194,
- "previousPage": 3,
- "nextPage": 5,
- "nbPages": 13680
}
Members are sorted by reverse chronological order of joining the team (most recent first). OAuth is only required if the list of members is private.
Members are streamed as ndjson.
teamId required | string Example: coders |
{- "id": "georges",
- "username": "Georges",
- "perfs": {
- "chess960": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "atomic": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "racingKings": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "ultraBullet": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "blitz": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "kingOfTheHill": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "bullet": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "correspondence": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "horde": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "puzzle": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "classical": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "rapid": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "storm": {
- "runs": 44,
- "score": 61
}, - "racer": {
- "runs": 44,
- "score": 61
}, - "streak": {
- "runs": 44,
- "score": 61
}
}, - "createdAt": 1290415680000,
- "disabled": false,
- "tosViolation": false,
- "profile": {
- "country": "EC",
- "location": "string",
- "bio": "Free bugs!",
- "firstName": "Thibault",
- "lastName": "Duplessis",
- "fideRating": 1500,
- "uscfRating": 1500,
- "ecfRating": 1500,
- "links": "github.com/ornicar\r\ntwitter.com/ornicar"
}, - "seenAt": 1522636452014,
- "patron": true,
- "verified": true,
- "playTime": {
- "total": 3296897,
- "tv": 12134
}, - "title": "NM",
- "count": {
- "all": 9265,
- "rated": 7157,
- "ai": 531,
- "draw": 340,
- "drawH": 331,
- "loss": 4480,
- "lossH": 4207,
- "win": 4440,
- "winH": 4378,
- "bookmark": 71,
- "playing": 6,
- "import": 66,
- "me": 0
}, - "streaming": false,
- "streamer": {
}, - "followable": true,
- "following": false,
- "blocking": false,
- "followsYou": false
}
Get all Arena tournaments relevant to a team.
Tournaments are sorted by reverse chronological order of start date (last starting first).
Tournaments are streamed as ndjson.
teamId required | string ID of the team |
max | integer >= 1 Default: 100 How many tournaments to download. |
{- "id": "QITRjufu",
- "createdBy": "lichess",
- "system": "arena",
- "minutes": 57,
- "clock": {
- "limit": 0,
- "increment": 0
}, - "rated": true,
- "fullName": "U1700 SuperBlitz Arena",
- "nbPlayers": 154,
- "variant": {
- "key": "standard",
- "name": "string",
- "short": "string"
}, - "startsAt": 1522803600000,
- "finishesAt": 1522807200000,
- "status": 30,
- "perf": {
- "key": "blitz",
- "name": "Blitz",
- "position": 1,
- "icon": ")"
}, - "secondsToStart": 576,
- "hasMaxRating": true,
- "maxRating": {
- "perf": "ultraBullet",
- "rating": 1700
}, - "minRating": {
- "perf": "ultraBullet",
- "rating": 1700
}, - "minRatedGames": {
- "nb": 20,
- "perf": "ultraBullet"
}, - "onlyTitled": false,
- "teamMember": "coders",
- "private": true,
- "position": {
- "eco": "C41",
- "name": "Philidor Defense",
- "fen": "rnbqkbnr/ppp2ppp/3p4/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq -",
}, - "schedule": {
- "freq": "hourly",
- "speed": "superblitz"
}, - "teamBattle": {
- "teams": [
- "coders"
], - "nbLeaders": 3
}, - "winner": {
- "id": "lichess",
- "name": "lichess",
- "title": "NM"
}
}
Join a team.
If the team requires a password but the password
field is incorrect,
then the call fails with 403 Forbidden
.
Similarly, if the team join policy requires a confirmation but the
message
parameter is not given, then the call fails with
403 Forbidden
.
teamId required | string Example: coders |
message | string Optional request message, if the team requires one. |
password | string Optional password, if the team requires one. |
{- "ok": true
}
Get pending join requests of your team
teamId required | string |
declined | boolean Default: false Get the declined join requests |
[- {
- "request": {
- "date": 1644232474472,
- "message": "Hello, I would like to join the team!",
- "teamId": "coders",
- "userId": "neio"
}, - "user": {
- "createdAt": 1338509698620,
- "id": "neio",
- "perfs": {
- "blitz": {
- "games": 70,
- "prog": 81,
- "prov": true,
- "rating": 1729,
- "rd": 124
}, - "chess960": {
- "games": 2,
- "prog": 0,
- "prov": true,
- "rating": 1528,
- "rd": 266
}
}, - "playTime": {
- "total": 152902,
- "tv": 20800
}, - "profile": {
- "bio": "yuwnt uyn",
- "country": "AL",
- "firstName": "wyutn w[fuyt",
- "lastName": "ywut wyufth"
}, - "seenAt": 1644232201429,
- "title": "NM",
- "username": "Neio"
}
}
]
Send a private message to all members of a team. You must be a team leader with the "Messages" permission.
teamId required | string Example: coders |
message | string The message to send to all your team members. |
{- "ok": true
}
Play on Lichess with physical boards and third-party clients. Works with normal Lichess accounts. Engine play or assistance is forbidden.
Stream the events reaching a lichess user in real time as ndjson.
An empty line is sent every 6 seconds for keep alive purposes.
Each non-empty line is a JSON object containing a type
field. Possible values are:
gameStart
Start of a gamegameFinish
Completion of a gamechallenge
A player sends you a challenge or you challenge someonechallengeCanceled
A player cancels their challenge to youchallengeDeclined
The opponent declines your challengeWhen the stream opens, all current challenges and games are sent.
{- "type": "challenge",
- "challenge": {
- "id": "7pGLxJ4F",
- "status": "created",
- "compat": {
- "bot": false,
- "board": true
}, - "challenger": {
- "id": "lovlas",
- "name": "Lovlas",
- "title": "IM",
- "rating": 2506,
- "patron": true,
- "online": true,
- "lag": 24
}, - "destUser": {
- "id": "thibot",
- "name": "thibot",
- "rating": 1500,
- "provisional": true,
- "online": true,
- "lag": 45
}, - "variant": {
- "key": "standard",
- "name": "Standard",
- "short": "Std"
}, - "rated": true,
- "timeControl": {
- "type": "clock",
- "limit": 300,
- "increment": 25,
- "show": "5+25"
}, - "color": "random",
- "finalColor": "white",
- "speed": "rapid",
- "perf": {
- "icon": "#",
- "name": "Rapid"
}
}
}
Create a public seek, to start a game with a random player.
Specify the time
and increment
clock values. The response is streamed but doesn't contain any information.
Keep the connection open to keep the seek active.
If the client closes the connection, the seek is canceled. This way, if the client terminates, the user won't be paired in a game they wouldn't play. When the seek is accepted, or expires, the server closes the connection.
Make sure to also have an Event stream open, to be notified when a game starts. We recommend opening the Event stream first, then the seek stream. This way, you won't miss the game event if the seek is accepted immediately.
Specify the days
per turn value. The response is not streamed, it immediately completes with the seek ID. The seek remains active on the server until it is joined by someone.
Parameters of the seek
rated | boolean Default: false Whether the game is rated and impacts players ratings. |
time | number [ 0 .. 180 ] Clock initial time in minutes. Required for real-time seeks. |
increment | integer [ 0 .. 180 ] Clock increment in seconds. Required for real-time seeks. |
days | integer Enum: 1 2 3 5 7 10 14 Days per turn. Required for correspondence seeks. |
variant | string (VariantKey) Enum: "standard" "chess960" "crazyhouse" "antichess" "atomic" "horde" "kingOfTheHill" "racingKings" "threeCheck" "fromPosition" |
color | string Default: "random" Enum: "random" "white" "black" The color to play. Better left empty to automatically get 50% white. |
ratingRange | string The rating range of potential opponents. Better left empty. Example: 1500-1800 |
Stream the state of a game being played with the Board API, as ndjson.
Use this endpoint to get updates about the game in real-time, with a single request.
Each line is a JSON object containing a type
field. Possible values are:
gameFull
Full game data. All values are immutable, except for the state
field.
gameState
Current state of the game. Immutable values not included. Sent when a move is played, a draw is offered, or when the game ends.
chatLine
Chat message sent by a user in the room
"player" or "spectator".
opponentGone
Whether the opponent has left the game, and how long before you can claim a win or draw.
The first line is always of type gameFull
.
The server closes the stream when the game ends, or if the game has already ended.
gameId required | string Example: 5IrD6Gzz |
{- "type": "gameFull",
- "id": "5IrD6Gzz",
- "rated": true,
- "variant": {
- "key": "standard",
- "name": "Standard",
- "short": "Std"
}, - "clock": {
- "initial": 1200000,
- "increment": 10000
}, - "speed": "classical",
- "perf": {
- "name": "Classical"
}, - "createdAt": 1523825103562,
- "white": {
- "id": "lovlas",
- "name": "lovlas",
- "provisional": false,
- "rating": 2500,
- "title": "IM"
}, - "black": {
- "id": "leela",
- "name": "leela",
- "rating": 2390
}, - "initialFen": "startpos",
- "state": {
- "type": "gameState",
- "moves": "e2e4 c7c5 f2f4 d7d6 g1f3 b8c6 f1c4 g8f6 d2d3 g7g6 e1g1 f8g7",
- "wtime": 7598040,
- "btime": 8395220,
- "winc": 10000,
- "binc": 10000,
- "status": "started"
}
}
Make a move in a game being played with the Board API.
The move can also contain a draw offer/agreement.
gameId required | string Example: 5IrD6Gzz |
move required | string Example: e2e4 The move to play, in UCI format |
offeringDraw | boolean Whether to offer (or agree to) a draw |
{- "ok": true
}
Post a message to the player or spectator chat, in a game being played with the Board API.
gameId required | string Example: 5IrD6Gzz |
room required | string Enum: "player" "spectator" |
text required | string |
{- "ok": true
}
Get the messages posted in the game chat
gameId required | string Example: 5IrD6Gzz |
[- {
- "text": "Takeback sent",
- "user": "lichess"
}, - {
- "text": "Takeback accepted",
- "user": "lichess"
}, - {
- "text": "Good game, well played",
- "user": "thibault"
}
]
Create/accept/decline draw offers.
yes
: Offer a draw, or accept the opponent's draw offer.no
: Decline a draw offer from the opponent.gameId required | string Example: 5IrD6Gzz |
required | boolean or "yes" (string) Example: yes |
{- "ok": true
}
Create/accept/decline takebacks.
yes
: Propose a takeback, or accept the opponent's takeback offer.no
: Decline a takeback offer from the opponent.gameId required | string Example: 5IrD6Gzz |
required | boolean or "yes" (string) Example: yes |
{- "ok": true
}
Go berserk on an arena tournament game. Halves the clock time, grants an extra point upon winning. Only available in arena tournaments that allow berserk, and before each player has made a move.
gameId required | string Example: 5IrD6Gzz |
{- "ok": true
}
Play on Lichess as a bot. Allows engine play. Read the blog post announcement of lichess bots.
Only works with Bot accounts.
Stream the events reaching a lichess user in real time as ndjson.
An empty line is sent every 6 seconds for keep alive purposes.
Each non-empty line is a JSON object containing a type
field. Possible values are:
gameStart
Start of a gamegameFinish
Completion of a gamechallenge
A player sends you a challenge or you challenge someonechallengeCanceled
A player cancels their challenge to youchallengeDeclined
The opponent declines your challengeWhen the stream opens, all current challenges and games are sent.
{- "type": "challenge",
- "challenge": {
- "id": "7pGLxJ4F",
- "status": "created",
- "compat": {
- "bot": false,
- "board": true
}, - "challenger": {
- "id": "lovlas",
- "name": "Lovlas",
- "title": "IM",
- "rating": 2506,
- "patron": true,
- "online": true,
- "lag": 24
}, - "destUser": {
- "id": "thibot",
- "name": "thibot",
- "rating": 1500,
- "provisional": true,
- "online": true,
- "lag": 45
}, - "variant": {
- "key": "standard",
- "name": "Standard",
- "short": "Std"
}, - "rated": true,
- "timeControl": {
- "type": "clock",
- "limit": 300,
- "increment": 25,
- "show": "5+25"
}, - "color": "random",
- "finalColor": "white",
- "speed": "rapid",
- "perf": {
- "icon": "#",
- "name": "Rapid"
}
}
}
Stream the online bot users, as ndjson. Throttled to 50 bot users per second.
nb | integer >= 1 Example: nb=20 How many bot users to fetch |
{- "id": "georges",
- "username": "Georges",
- "perfs": {
- "chess960": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "atomic": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "racingKings": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "ultraBullet": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "blitz": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "kingOfTheHill": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "bullet": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "correspondence": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "horde": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "puzzle": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "classical": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "rapid": {
- "games": 2945,
- "rating": 1609,
- "rd": 60,
- "prog": -22,
- "prov": true
}, - "storm": {
- "runs": 44,
- "score": 61
}, - "racer": {
- "runs": 44,
- "score": 61
}, - "streak": {
- "runs": 44,
- "score": 61
}
}, - "createdAt": 1290415680000,
- "disabled": false,
- "tosViolation": false,
- "profile": {
- "country": "EC",
- "location": "string",
- "bio": "Free bugs!",
- "firstName": "Thibault",
- "lastName": "Duplessis",
- "fideRating": 1500,
- "uscfRating": 1500,
- "ecfRating": 1500,
- "links": "github.com/ornicar\r\ntwitter.com/ornicar"
}, - "seenAt": 1522636452014,
- "patron": true,
- "verified": true,
- "playTime": {
- "total": 3296897,
- "tv": 12134
}, - "title": "NM"
}
Upgrade a lichess player account into a Bot account. Only Bot accounts can use the Bot API.
The account cannot have played any game before becoming a Bot account. The upgrade is irreversible. The account will only be able to play as a Bot.
To upgrade an account to Bot, use the official lichess-bot client, or follow these steps:
curl -d '' https://lichess.org/api/bot/account/upgrade -H "Authorization: Bearer <yourTokenHere>"
To know if an account has already been upgraded, use the Get my profile API:
the title
field should be set to BOT
.
{- "ok": true
}
Stream the state of a game being played with the Bot API, as ndjson.
Use this endpoint to get updates about the game in real-time, with a single request.
Each line is a JSON object containing a type
field. Possible values are:
gameFull
Full game data. All values are immutable, except for the state
field.
gameState
Current state of the game. Immutable values not included.
chatLine
Chat message sent by a user (or the bot itself) in the room
"player" or "spectator".
opponentGone
Whether the opponent has left the game, and how long before you can claim a win or draw.
The first line is always of type gameFull
.
gameId required | string Example: 5IrD6Gzz |
{- "type": "gameFull",
- "id": "5IrD6Gzz",
- "rated": true,
- "variant": {
- "key": "standard",
- "name": "Standard",
- "short": "Std"
}, - "clock": {
- "initial": 1200000,
- "increment": 10000
}, - "speed": "classical",
- "perf": {
- "name": "Classical"
}, - "createdAt": 1523825103562,
- "white": {
- "id": "lovlas",
- "name": "lovlas",
- "provisional": false,
- "rating": 2500,
- "title": "IM"
}, - "black": {
- "id": "leela",
- "name": "leela",
- "rating": 2390
}, - "initialFen": "startpos",
- "state": {
- "type": "gameState",
- "moves": "e2e4 c7c5 f2f4 d7d6 g1f3 b8c6 f1c4 g8f6 d2d3 g7g6 e1g1 f8g7",
- "wtime": 7598040,
- "btime": 8395220,
- "winc": 10000,
- "binc": 10000,
- "status": "started"
}
}
Make a move in a game being played with the Bot API.
The move can also contain a draw offer/agreement.
gameId required | string Example: 5IrD6Gzz |
move required | string Example: e2e4 The move to play, in UCI format |
offeringDraw | boolean Whether to offer (or agree to) a draw |
{- "ok": true
}
Post a message to the player or spectator chat, in a game being played with the Bot API.
gameId required | string Example: 5IrD6Gzz |
room required | string Enum: "player" "spectator" |
text required | string |
{- "ok": true
}
Get the messages posted in the game chat
gameId required | string Example: 5IrD6Gzz |
[- {
- "text": "Takeback sent",
- "user": "lichess"
}, - {
- "text": "Takeback accepted",
- "user": "lichess"
}, - {
- "text": "Good game, well played",
- "user": "thibault"
}
]
Create/accept/decline draw offers in bot games
yes
: Offer a draw, or accept the opponent's draw offer.no
: Decline a draw offer from the opponent.gameId required | string Example: 5IrD6Gzz |
required | boolean or "yes" (string) Example: yes |
{- "ok": true
}
Send and receive challenges to play.
To create a lot of challenges, consider bulk pairing instead.
Get a list of challenges created by or targeted at you.
{- "in": [
- {
- "id": "VU0nyvsW",
- "color": "random",
- "direction": "out",
- "timeControl": {
- "increment": 2,
- "limit": 300,
- "show": "5+2",
- "type": "clock"
}, - "variant": {
- "key": "standard",
- "name": "Standard",
- "short": "Std"
}, - "challenger": {
- "id": "thibot",
- "name": "thibot",
- "online": true,
- "provisional": false,
- "rating": 1940,
- "title": "BOT"
}, - "destUser": {
- "id": "leelachess",
- "name": "LeelaChess",
- "online": true,
- "provisional": true,
- "rating": 2670,
- "title": "BOT"
}, - "perf": {
- "icon": ";",
- "name": "Correspondence"
}, - "rated": true,
- "speed": "blitz",
- "status": "created"
}
], - "out": [
- {
- "id": "VU0nyvsW",
- "color": "random",
- "direction": "out",
- "timeControl": {
- "increment": 2,
- "limit": 300,
- "show": "5+2",
- "type": "clock"
}, - "variant": {
- "key": "standard",
- "name": "Standard",
- "short": "Std"
}, - "challenger": {
- "id": "thibot",
- "name": "thibot",
- "online": true,
- "provisional": false,
- "rating": 1940,
- "title": "BOT"
}, - "destUser": {
- "id": "leelachess",
- "name": "LeelaChess",
- "online": true,
- "provisional": true,
- "rating": 2670,
- "title": "BOT"
}, - "perf": {
- "icon": ";",
- "name": "Correspondence"
}, - "rated": true,
- "speed": "blitz",
- "status": "created"
}
]
}
Challenge someone to play. The targeted player can choose to accept or decline.
If the challenge is accepted, you will be notified on the event stream that a new game has started. The game ID will be the same as the challenge ID.
Challenges for realtime games (not correspondence) expire after 20s if not accepted.
To prevent that, use the keepAliveStream
flag described below.
username required | string Example: LeelaChess |
Parameters of the challenge
rated | boolean Default: false Game is rated and impacts players ratings |
clock.limit | number [ 0 .. 10800 ] Clock initial time in seconds. If empty, a correspondence game is created. Valid values are 0, 15, 30, 45, 60, 90, and any multiple of 60 up to 10800 (3 hours). |
clock.increment | integer [ 0 .. 60 ] Clock increment in seconds. If empty, a correspondence game is created. |
days | integer Enum: 1 2 3 5 7 10 14 Days per move, for correspondence games. Clock settings must be omitted. |
color | string Default: "random" Enum: "random" "white" "black" Which color you get to play |
variant | string (VariantKey) Enum: "standard" "chess960" "crazyhouse" "antichess" "atomic" "horde" "kingOfTheHill" "racingKings" "threeCheck" "fromPosition" |
fen | string (FromPositionFEN) Custom initial position (in FEN). Variant must be standard, fromPosition, or chess960 (if a valid 960 starting position), and the game cannot be rated. |
keepAliveStream | boolean If set, the response is streamed as ndjson.
The challenge is kept alive until the connection is closed by the client.
When the challenge is accepted, declined or canceled, a message of the form |
rules | string Enum: "noAbort" "noRematch" "noGiveTime" "noClaimWin" "noEarlyDraw" Extra game rules separated by commas.
Example: |
{- "challenge": {
- "id": "VU0nyvsW",
- "color": "random",
- "direction": "out",
- "timeControl": {
- "increment": 2,
- "limit": 300,
- "show": "5+2",
- "type": "clock"
}, - "variant": {
- "key": "standard",
- "name": "Standard",
- "short": "Std"
}, - "challenger": {
- "id": "thibot",
- "name": "thibot",
- "online": true,
- "provisional": false,
- "rating": 1940,
- "title": "BOT"
}, - "destUser": {
- "id": "leelachess",
- "name": "LeelaChess",
- "online": true,
- "provisional": true,
- "rating": 2670,
- "title": "BOT"
}, - "perf": {
- "icon": ";",
- "name": "Correspondence"
}, - "rated": true,
- "speed": "blitz",
- "status": "created"
}
}
Accept an incoming challenge.
You should receive a gameStart
event on the incoming events stream.
challengeId required | string Example: 5IrD6Gzz |
{- "ok": true
}
Decline an incoming challenge.
challengeId required | string Example: 5IrD6Gzz |
Details related to decline of challenge
reason | string Enum: "generic" "later" "tooFast" "tooSlow" "timeControl" "rated" "casual" "standard" "variant" "noBot" "onlyBot" Reason challenge was declined. It will be translated to the player's language. See the full list in the translation file. |
{- "ok": true
}
Cancel a challenge you sent, or aborts the game if the challenge was accepted, but the game was not yet played. Note that the ID of a game is the same as the ID of the challenge that created it.
Works for user challenges and open challenges alike.
challengeId required | string Example: 5IrD6Gzz |
opponentToken | string Optional |
{- "ok": true
}
Start a game with Lichess AI.
You will be notified on the event stream that a new game has started.
Parameters of the game
level | number [ 1 .. 8 ] AI strength |
clock.limit | number [ 0 .. 10800 ] Clock initial time in seconds. If empty, a correspondence game is created. |
clock.increment | integer [ 0 .. 60 ] Clock increment in seconds. If empty, a correspondence game is created. |
days | integer Enum: 1 2 3 5 7 10 14 Days per move, for correspondence games. Clock settings must be omitted. |
color | string Default: "random" Enum: "random" "white" "black" Which color you get to play |
variant | string (VariantKey) Enum: "standard" "chess960" "crazyhouse" "antichess" "atomic" "horde" "kingOfTheHill" "racingKings" "threeCheck" "fromPosition" |
fen | string (FromPositionFEN) Custom initial position (in FEN). Variant must be standard, fromPosition, or chess960 (if a valid 960 starting position), and the game cannot be rated. |
{- "id": "q7ZvsdUF",
- "rated": true,
- "variant": "standard",
- "speed": "blitz",
- "perf": "blitz",
- "createdAt": 1514505150384,
- "lastMoveAt": 1514505592843,
- "status": "draw",
- "players": {
- "white": {
- "user": {
- "name": "Lance5500",
- "title": "LM",
- "patron": true,
- "id": "lance5500"
}, - "rating": 2389,
- "ratingDiff": 4
}, - "black": {
- "user": {
- "name": "TryingHard87",
- "id": "tryinghard87"
}, - "rating": 2498,
- "ratingDiff": -4
}
}, - "opening": {
- "eco": "D31",
- "name": "Semi-Slav Defense: Marshall Gambit",
- "ply": 7
}, - "moves": "d4 d5 c4 c6 Nc3 e6 e4 Nd7 exd5 cxd5 cxd5 exd5 Nxd5 Nb6 Bb5+ Bd7 Qe2+ Ne7 Nxb6 Qxb6 Bxd7+ Kxd7 Nf3 Qa6 Ne5+ Ke8 Qf3 f6 Nd3 Qc6 Qe2 Kf7 O-O Kg8 Bd2 Re8 Rac1 Nf5 Be3 Qe6 Rfe1 g6 b3 Bd6 Qd2 Kf7 Bf4 Qd7 Bxd6 Nxd6 Nc5 Rxe1+ Rxe1 Qc6 f3 Re8 Rxe8 Nxe8 Kf2 Nc7 Qb4 b6 Qc4+ Nd5 Nd3 Qe6 Nb4 Ne7 Qxe6+ Kxe6 Ke3 Kd6 g3 h6 Kd3 h5 Nc2 Kd5 a3 Nc6 Ne3+ Kd6 h4 Nd8 g4 Ne6 Ke4 Ng7 Nc4+ Ke6 d5+ Kd7 a4 g5 gxh5 Nxh5 hxg5 fxg5 Kf5 Nf4 Ne3 Nh3 Kg4 Ng1 Nc4 Kc7 Nd2 Kd6 Kxg5 Kxd5 f4 Nh3+ Kg4 Nf2+ Kf3 Nd3 Ke3 Nc5 Kf3 Ke6 Ke3 Kf5 Kd4 Ne6+ Kc4",
- "clock": {
- "initial": 300,
- "increment": 3,
- "totalTime": 420
}
}
Create a challenge that any 2 players can join.
Share the URL of the challenge. the first 2 players to click it will be paired for a game.
The response body also contains whiteUrl
and blackUrl
.
You can control which color each player gets by giving them these URLs,
instead of the main challenge URL.
Open challenges expire after 24h.
If the challenge creation is authenticated with OAuth2, then you can use the challenge cancel endpoint to cancel it.
To directly pair 2 known players, use this endpoint instead.
Parameters of the game
rated | boolean Default: false Game is rated and impacts players ratings |
clock.limit | number [ 0 .. 10800 ] Clock initial time in seconds. If empty, a correspondence game is created. |
clock.increment | integer [ 0 .. 60 ] Clock increment in seconds. If empty, a correspondence game is created. |
days | integer Enum: 1 2 3 5 7 10 14 Days per turn. For correspondence challenges. |
variant | string (VariantKey) Enum: "standard" "chess960" "crazyhouse" "antichess" "atomic" "horde" "kingOfTheHill" "racingKings" "threeCheck" "fromPosition" |
fen | string (FromPositionFEN) Custom initial position (in FEN). Variant must be standard, fromPosition, or chess960 (if a valid 960 starting position), and the game cannot be rated. |
name | string Optional name for the challenge, that players will see on the challenge page. |
rules | string Enum: "noRematch" "noGiveTime" "noClaimWin" "noEarlyDraw" "noAbort" Extra game rules separated by commas.
Example: |
users | string Optional pair of usernames, separated by a comma.
If set, only these users will be allowed to join the game.
The first username gets the white pieces.
Example: |
expiresAt | integer Timestamp in milliseconds to expire the challenge. Defaults to 24h after creation. Can't be more than 2 weeks after creation. |
{- "id": "VU0nyvsW",
- "color": "random",
- "direction": "out",
- "timeControl": {
- "increment": 2,
- "limit": 300,
- "show": "5+2",
- "type": "clock"
}, - "variant": {
- "key": "standard",
- "name": "Standard",
- "short": "Std"
}, - "challenger": {
- "id": "thibot",
- "name": "thibot",
- "online": true,
- "provisional": false,
- "rating": 1940,
- "title": "BOT"
}, - "destUser": {
- "id": "leelachess",
- "name": "LeelaChess",
- "online": true,
- "provisional": true,
- "rating": 2670,
- "title": "BOT"
}, - "perf": {
- "icon": ";",
- "name": "Correspondence"
}, - "rated": true,
- "speed": "blitz",
- "status": "created"
}
Start the clocks of a game immediately, even if a player has not yet made a move.
Requires the OAuth tokens of both players with challenge:write
scope.
If the clocks have already started, the call will have no effect.
gameId required | string ID of the game |
token1 | string OAuth token of a player |
token2 | string OAuth token of the other player |
{- "ok": true
}
Add seconds to the opponent's clock. Can be used to create games with time odds.
gameId required | string ID of the game |
seconds required | string [ 1 .. 86400 ] How many seconds to give |
{- "ok": true
}
This endpoint can only be used by Lichess administrators. It will not work if you do not have the appropriate permissions. Tournament organizers should instead use OAuth to obtain challenge:write
tokens from users in order to perform bulk pairing.*
Create and obtain challenge:write
tokens for multiple users.
If a similar token already exists for a user, it is reused. This endpoint is idempotent.
users required | string Usernames separated with commas |
description required | string User visible description of the token |
{- "thibault": "lLOEkpH58W599xH9",
- "neio": "nAYTIJphwWFwKmKk",
- "lizen2": "1cnHhuWKHROgiPC4",
- "lizen3": "SszJ9Sj1bto0UQCK"
}
Create many games for other players.
These endpoints are intended for tournament organisers.
[- {
- "id": "RVAcwgg7",
- "games": [
- {
- "id": "NKop9IyD",
- "black": "lizen1",
- "white": "thibault"
}, - {
- "id": "KT8374ut",
- "black": "lizen3",
- "white": "lizen2"
}, - {
- "id": "wInQr8Sk",
- "black": "lizen5",
- "white": "lizen4"
}
], - "variant": "standard",
- "clock": {
- "increment": 0,
- "limit": 300
}, - "pairAt": 1612289869919,
- "pairedAt": null,
- "rated": false,
- "startClocksAt": 1612200422971,
- "scheduledAt": 1612203514628
}
]
Schedule many games at once, up to 24h in advance.
OAuth tokens are required for all paired players, with the challenge:write
scope.
You can schedule up to 500 games every 10 minutes. Contact us if you need higher limits.
If games have a real-time clock, each player must have only one pairing. For correspondence games, players can have multiple pairings within the same bulk.
The entire bulk is rejected if:
challenge:write
scopePartial bulks are never created. Either it all fails, or it all succeeds. When it fails, it does so with an error message explaining the issue. Failed bulks are not counted in the rate limiting, they are free. Fix the issues, manually or programmatically, then retry to schedule the bulk.
A successful bulk creation returns a JSON bulk document. Its ID can be used for further operations.
Parameters of the pairings
players | string OAuth tokens of all the players to pair, with the syntax The 2 tokens of the players of a game are separated with Up to 1000 tokens can be sent, for a max of 500 games. Each token must be included at most once. Example: |
clock.limit | number [ 0 .. 10800 ] Clock initial time in seconds. Example: |
clock.increment | integer [ 0 .. 60 ] Clock increment in seconds. Example: |
days | integer Enum: 1 2 3 5 7 10 14 Days per turn. For correspondence games only. |
pairAt | integer Date at which the games will be created as a Unix timestamp in milliseconds.
Up to 7 days in the future.
Omit, or set to current date and time, to start the games immediately.
Example: |
startClocksAt | integer Date at which the clocks will be automatically started as a Unix timestamp in milliseconds.
Up to 7 days in the future.
Note that the clocks can start earlier than specified, if players start making moves in the game.
If omitted, the clocks will not start automatically.
Example: |
rated | boolean Default: false Game is rated and impacts players ratings |
variant | string (VariantKey) Enum: "standard" "chess960" "crazyhouse" "antichess" "atomic" "horde" "kingOfTheHill" "racingKings" "threeCheck" "fromPosition" |
fen | string (FromPositionFEN) Custom initial position (in FEN). Variant must be standard, fromPosition, or chess960 (if a valid 960 starting position), and the game cannot be rated. |
message | string Default: "Your game with {opponent} is ready: {game}." Message that will be sent to each player, when the game is created. It is sent from your user account.
You can omit this field to send the default message,
but if you set your own message, it must at least contain the |
rules | string Enum: "noAbort" "noRematch" "noGiveTime" "noClaimWin" "noEarlyDraw" Extra game rules separated by commas.
Example: |
{- "id": "RVAcwgg7",
- "games": [
- {
- "id": "NKop9IyD",
- "black": "lizen1",
- "white": "thibault"
}, - {
- "id": "KT8374ut",
- "black": "lizen3",
- "white": "lizen2"
}, - {
- "id": "wInQr8Sk",
- "black": "lizen5",
- "white": "lizen4"
}
], - "variant": "standard",
- "clock": {
- "increment": 0,
- "limit": 300
}, - "pairAt": 1612289869919,
- "pairedAt": null,
- "rated": false,
- "startClocksAt": 1612200422971,
- "scheduledAt": 1612203514628
}
Immediately start all clocks of the games of a bulk pairing.
This overrides the startClocksAt
value of an existing bulk pairing.
If the games have not yet been created (bulk.pairAt
is in the future), then this does nothing.
If the clocks have already started (bulk.startClocksAt
is in the past), then this does nothing.
id required | string Example: 5IrD6Gzz The ID of the bulk pairing |
{- "ok": true
}
Get a single bulk pairing by its ID.
id required | string Example: 5IrD6Gzz The ID of the bulk pairing |
{- "id": "RVAcwgg7",
- "games": [
- {
- "id": "NKop9IyD",
- "black": "lizen1",
- "white": "thibault"
}, - {
- "id": "KT8374ut",
- "black": "lizen3",
- "white": "lizen2"
}, - {
- "id": "wInQr8Sk",
- "black": "lizen5",
- "white": "lizen4"
}
], - "variant": "standard",
- "clock": {
- "increment": 0,
- "limit": 300
}, - "pairAt": 1612289869919,
- "pairedAt": null,
- "rated": false,
- "startClocksAt": 1612200422971,
- "scheduledAt": 1612203514628
}
Cancel and delete a bulk pairing that is scheduled in the future.
If the games have already been created, then this does nothing.
Canceling a bulk pairing does not refund the rate limit cost of that bulk pairing.
id required | string Example: 5IrD6Gzz The ID of the bulk pairing |
{- "ok": true
}
Access Arena tournaments played on Lichess. Official Arena tournaments are maintained by Lichess, but you can create your own Arena tournaments as well.
Get recently finished, ongoing, and upcoming tournaments.
This API is used to display the Lichess tournament schedule.
{- "created": [
- {
- "id": "QITRjufu",
- "createdBy": "lichess",
- "system": "arena",
- "minutes": 57,
- "clock": {
- "limit": 0,
- "increment": 0
}, - "rated": true,
- "fullName": "U1700 SuperBlitz Arena",
- "nbPlayers": 154,
- "variant": {
- "key": "standard",
- "name": "string",
- "short": "string"
}, - "startsAt": 1522803600000,
- "finishesAt": 1522807200000,
- "status": 30,
- "perf": {
- "key": "blitz",
- "name": "Blitz",
- "position": 1,
- "icon": ")"
}, - "secondsToStart": 576,
- "hasMaxRating": true,
- "maxRating": {
- "perf": "ultraBullet",
- "rating": 1700
}, - "minRating": {
- "perf": "ultraBullet",
- "rating": 1700
}, - "minRatedGames": {
- "nb": 20,
- "perf": "ultraBullet"
}, - "onlyTitled": false,
- "teamMember": "coders",
- "private": true,
- "position": {
- "eco": "C41",
- "name": "Philidor Defense",
- "fen": "rnbqkbnr/ppp2ppp/3p4/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq -",
}, - "schedule": {
- "freq": "hourly",
- "speed": "superblitz"
}, - "teamBattle": {
- "teams": [
- "coders"
], - "nbLeaders": 3
}, - "winner": {
- "id": "lichess",
- "name": "lichess",
- "title": "NM"
}
}
], - "started": [
- {
- "id": "QITRjufu",
- "createdBy": "lichess",
- "system": "arena",
- "minutes": 57,
- "clock": {
- "limit": 0,
- "increment": 0
}, - "rated": true,
- "fullName": "U1700 SuperBlitz Arena",
- "nbPlayers": 154,
- "variant": {
- "key": "standard",
- "name": "string",
- "short": "string"
}, - "startsAt": 1522803600000,
- "finishesAt": 1522807200000,
- "status": 30,
- "perf": {
- "key": "blitz",
- "name": "Blitz",
- "position": 1,
- "icon": ")"
}, - "secondsToStart": 576,
- "hasMaxRating": true,
- "maxRating": {
- "perf": "ultraBullet",
- "rating": 1700
}, - "minRating": {
- "perf": "ultraBullet",
- "rating": 1700
}, - "minRatedGames": {
- "nb": 20,
- "perf": "ultraBullet"
}, - "onlyTitled": false,
- "teamMember": "coders",
- "private": true,
- "position": {
- "eco": "C41",
- "name": "Philidor Defense",
- "fen": "rnbqkbnr/ppp2ppp/3p4/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq -",
}, - "schedule": {
- "freq": "hourly",
- "speed": "superblitz"
}, - "teamBattle": {
- "teams": [
- "coders"
], - "nbLeaders": 3
}, - "winner": {
- "id": "lichess",
- "name": "lichess",
- "title": "NM"
}
}
], - "finished": [
- {
- "id": "QITRjufu",
- "createdBy": "lichess",
- "system": "arena",
- "minutes": 57,
- "clock": {
- "limit": 0,
- "increment": 0
}, - "rated": true,
- "fullName": "U1700 SuperBlitz Arena",
- "nbPlayers": 154,
- "variant": {
- "key": "standard",
- "name": "string",
- "short": "string"
}, - "startsAt": 1522803600000,
- "finishesAt": 1522807200000,
- "status": 30,
- "perf": {
- "key": "blitz",
- "name": "Blitz",
- "position": 1,
- "icon": ")"
}, - "secondsToStart": 576,
- "hasMaxRating": true,
- "maxRating": {
- "perf": "ultraBullet",
- "rating": 1700
}, - "minRating": {
- "perf": "ultraBullet",
- "rating": 1700
}, - "minRatedGames": {
- "nb": 20,
- "perf": "ultraBullet"
}, - "onlyTitled": false,
- "teamMember": "coders",
- "private": true,
- "position": {
- "eco": "C41",
- "name": "Philidor Defense",
- "fen": "rnbqkbnr/ppp2ppp/3p4/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq -",
}, - "schedule": {
- "freq": "hourly",
- "speed": "superblitz"
}, - "teamBattle": {
- "teams": [
- "coders"
], - "nbLeaders": 3
}, - "winner": {
- "id": "lichess",
- "name": "lichess",
- "title": "NM"
}
}
]
}
Create a public or private Arena tournament.
This endpoint mirrors the form on https://lichess.org/tournament/new.
You can create up to 12 public tournaments per day, or 24 private tournaments.
A team battle can be created by specifying the teamBattleByTeam
argument.
Additional restrictions:
Parameters of the tournament
name | string [ 2 .. 30 ] characters The tournament name. Leave empty to get a random Grandmaster name |
clockTime required | number Enum: 0 0.25 0.5 0.75 1 1.5 2 3 4 5 6 7 8 10 15 20 25 30 40 50 60 Clock initial time in minutes |
clockIncrement required | integer Enum: 0 1 2 3 4 5 6 7 10 15 20 25 30 40 50 60 Clock increment in seconds |
minutes required | integer Enum: 20 25 30 35 40 45 50 55 60 70 80 90 100 110 120 150 180 210 240 270 300 330 360 420 480 540 600 720 How long the tournament lasts, in minutes |
waitMinutes | integer Default: 5 Enum: 1 2 3 5 10 15 20 30 45 60 How long to wait before starting the tournament, from now, in minutes |
startDate | integer Timestamp (in milliseconds) to start the tournament at a given date and time. Overrides the |
variant | string (VariantKey) Enum: "standard" "chess960" "crazyhouse" "antichess" "atomic" "horde" "kingOfTheHill" "racingKings" "threeCheck" "fromPosition" |
rated | boolean Default: true Games are rated and impact players ratings |
position | string (FromPositionFEN) Custom initial position (in FEN). Variant must be standard, fromPosition, or chess960 (if a valid 960 starting position), and the game cannot be rated. |
berserkable | boolean Default: true Whether the players can use berserk. Only allowed if clockIncrement <= clockTime * 2 |
streakable | boolean Default: true After 2 wins, consecutive wins grant 4 points instead of 2. |
hasChat | boolean Default: true Whether the players can discuss in a chat |
description | string Anything you want to tell players about the tournament |
password | string Make the tournament private, and restrict access with a password. You can also generate user-specific entry codes based on this password. |
teamBattleByTeam | string Set the ID of a team you lead to create a team battle. The other teams can be added using the team battle edit endpoint. |
conditions.teamMember.teamId | string Restrict entry to members of a team. The teamId is the last part of a team URL, e.g. Leave empty to let everyone join the tournament. Do not use this to create team battles, use |
conditions.minRating.rating | integer Enum: 1000 1100 1200 1300 1400 1500 1600 1700 1800 1900 2000 2100 2200 2300 2400 2500 2600 Minimum rating to join. Leave empty to let everyone join the tournament. |
conditions.maxRating.rating | integer Enum: 2200 2100 2000 1900 1800 1700 1600 1500 1400 1300 1200 1100 1000 900 800 Maximum rating to join. Based on best rating reached in the last 7 days. Leave empty to let everyone join the tournament. |
conditions.nbRatedGame.nb | integer Enum: 0 5 10 15 20 30 40 50 75 100 150 200 Minimum number of rated games required to join. |
conditions.allowList | string Predefined list of usernames that are allowed to join, separated by commas.
If this list is non-empty, then usernames absent from this list will be forbidden to join.
Adding |
{- "id": "QITRjufu",
- "fullName": "U1700 SuperBlitz Arena",
- "rated": true,
- "clock": {
- "increment": 0,
- "limit": 180
}, - "minutes": 57,
- "createdBy": "lichess",
- "system": "arena",
- "secondsToStart": 0,
- "secondsToFinish": 36000,
- "isFinished": true,
- "isRecentlyFinished": true,
- "pairingsClosed": true,
- "startsAt": 1522803600000,
- "nbPlayers": 154,
- "perf": {
- "icon": ")",
- "key": "blitz",
- "name": "Blitz",
- "position": 1
}, - "schedule": {
- "freq": "hourly",
- "speed": "superblitz"
}, - "variant": "standard",
- "duels": [
- {
- "id": "0MM6q4tQ",
- "p": [
- {
- "n": "player1",
- "r": 1500,
- "k": 3
}, - {
- "n": "player2",
- "r": 1500,
- "k": 3
}
]
}
], - "standings": {
- "page": 1,
- "players": [
- {
- "name": "player1",
- "rank": 1,
- "rating": 1500,
- "score": 3,
- "sheet": {
- "scores": [
- {
- "0": 2,
- "1": 2
}, - {
- "0": 4,
- "1": 3
}, - 0
], - "total": 6,
- "fire": true
}
}
]
}, - "featured": {
- "id": "khe72Fer",
- "fen": "rn1qkb1r/pQ3ppp/2b2n2/8/5P2/4P3/PP4PP/RNB1KBNR",
- "color": "black",
- "lastMove": "d7c6",
- "white": {
- "rank": 2,
- "name": "player1",
- "rating": 1360
}, - "black": {
- "rank": 5,
- "name": "player2",
- "rating": 1431
}
}, - "podium": [
- {
- "name": "player1",
- "rank": 1,
- "rating": 1500,
- "score": 3,
- "sheet": {
- "scores": [
- {
- "0": 2,
- "1": 2
}, - {
- "0": 4,
- "1": 3
}, - 0
], - "total": 6,
- "fire": true
}, - "nb": {
- "game": 3,
- "beserk": 0,
- "win": 2
}, - "performance": 1787
}
], - "stats": {
- "games": 454,
- "moves": 27542,
- "whiteWins": 236,
- "blackWins": 207,
- "draws": 11,
- "berserks": 0,
- "averageRating": 1320
}
}
Get detailed info about recently finished, current, or upcoming tournament's duels, player standings, and other info.
id required | string The tournament ID. |
page | number [ 1 .. 200 ] Default: 1 Example: page=1 Specify which page of player standings to view. |
{- "id": "QITRjufu",
- "fullName": "U1700 SuperBlitz Arena",
- "rated": true,
- "clock": {
- "increment": 0,
- "limit": 180
}, - "minutes": 57,
- "createdBy": "lichess",
- "system": "arena",
- "secondsToStart": 0,
- "secondsToFinish": 36000,
- "isFinished": true,
- "isRecentlyFinished": true,
- "pairingsClosed": true,
- "startsAt": 1522803600000,
- "nbPlayers": 154,
- "perf": {
- "icon": ")",
- "key": "blitz",
- "name": "Blitz",
- "position": 1
}, - "schedule": {
- "freq": "hourly",
- "speed": "superblitz"
}, - "variant": "standard",
- "duels": [
- {
- "id": "0MM6q4tQ",
- "p": [
- {
- "n": "player1",
- "r": 1500,
- "k": 3
}, - {
- "n": "player2",
- "r": 1500,
- "k": 3
}
]
}
], - "standings": {
- "page": 1,
- "players": [
- {
- "name": "player1",
- "rank": 1,
- "rating": 1500,
- "score": 3,
- "sheet": {
- "scores": [
- {
- "0": 2,
- "1": 2
}, - {
- "0": 4,
- "1": 3
}, - 0
], - "total": 6,
- "fire": true
}
}
]
}, - "featured": {
- "id": "khe72Fer",
- "fen": "rn1qkb1r/pQ3ppp/2b2n2/8/5P2/4P3/PP4PP/RNB1KBNR",
- "color": "black",
- "lastMove": "d7c6",
- "white": {
- "rank": 2,
- "name": "player1",
- "rating": 1360
}, - "black": {
- "rank": 5,
- "name": "player2",
- "rating": 1431
}
}, - "podium": [
- {
- "name": "player1",
- "rank": 1,
- "rating": 1500,
- "score": 3,
- "sheet": {
- "scores": [
- {
- "0": 2,
- "1": 2
}, - {
- "0": 4,
- "1": 3
}, - 0
], - "total": 6,
- "fire": true
}, - "nb": {
- "game": 3,
- "beserk": 0,
- "win": 2
}, - "performance": 1787
}
], - "stats": {
- "games": 454,
- "moves": 27542,
- "whiteWins": 236,
- "blackWins": 207,
- "draws": 11,
- "berserks": 0,
- "averageRating": 1320
}
}
Update an Arena tournament.
Be mindful not to make important changes to ongoing tournaments.
Can be used to update a team battle.
Additional restrictions:
id required | string The tournament ID. |
Parameters of the tournament
name | string [ 2 .. 30 ] characters The tournament name. Leave empty to get a random Grandmaster name |
clockTime required | number Enum: 0 0.25 0.5 0.75 1 1.5 2 3 4 5 6 7 8 10 15 20 25 30 40 50 60 Clock initial time in minutes |
clockIncrement required | integer Enum: 0 1 2 3 4 5 6 7 10 15 20 25 30 40 50 60 Clock increment in seconds |
minutes required | integer Enum: 20 25 30 35 40 45 50 55 60 70 80 90 100 110 120 150 180 210 240 270 300 330 360 420 480 540 600 720 How long the tournament lasts, in minutes |
waitMinutes | integer Default: 5 Enum: 1 2 3 5 10 15 20 30 45 60 How long to wait before starting the tournament, from now, in minutes |
startDate | integer Timestamp (in milliseconds) to start the tournament at a given date and time. Overrides the |
variant | string (VariantKey) Enum: "standard" "chess960" "crazyhouse" "antichess" "atomic" "horde" "kingOfTheHill" "racingKings" "threeCheck" "fromPosition" |
rated | boolean Default: true Games are rated and impact players ratings |
position | string (FromPositionFEN) Custom initial position (in FEN). Variant must be standard, fromPosition, or chess960 (if a valid 960 starting position), and the game cannot be rated. |
berserkable | boolean Default: true Whether the players can use berserk. Only allowed if clockIncrement <= clockTime * 2 |
streakable | boolean Default: true After 2 wins, consecutive wins grant 4 points instead of 2. |
hasChat | boolean Default: true Whether the players can discuss in a chat |
description | string Anything you want to tell players about the tournament |
password | string Make the tournament private, and restrict access with a password |
conditions.minRating.rating | integer Enum: 1000 1100 1200 1300 1400 1500 1600 1700 1800 1900 2000 2100 2200 2300 2400 2500 2600 Minimum rating to join. Leave empty to let everyone join the tournament. |
conditions.maxRating.rating | integer Enum: 2200 2100 2000 1900 1800 1700 1600 1500 1400 1300 1200 1100 1000 900 800 Maximum rating to join. Based on best rating reached in the last 7 days. Leave empty to let everyone join the tournament. |
conditions.nbRatedGame.nb | integer Enum: 0 5 10 15 20 30 40 50 75 100 150 200 Minimum number of rated games required to join. |
conditions.allowList | string Predefined list of usernames that are allowed to join, separated by commas.
If this list is non-empty, then usernames absent from this list will be forbidden to join.
Adding |
{- "id": "QITRjufu",
- "fullName": "U1700 SuperBlitz Arena",
- "rated": true,
- "clock": {
- "increment": 0,
- "limit": 180
}, - "minutes": 57,
- "createdBy": "lichess",
- "system": "arena",
- "secondsToStart": 0,
- "secondsToFinish": 36000,
- "isFinished": true,
- "isRecentlyFinished": true,
- "pairingsClosed": true,
- "startsAt": 1522803600000,
- "nbPlayers": 154,
- "perf": {
- "icon": ")",
- "key": "blitz",
- "name": "Blitz",
- "position": 1
}, - "schedule": {
- "freq": "hourly",
- "speed": "superblitz"
}, - "variant": "standard",
- "duels": [
- {
- "id": "0MM6q4tQ",
- "p": [
- {
- "n": "player1",
- "r": 1500,
- "k": 3
}, - {
- "n": "player2",
- "r": 1500,
- "k": 3
}
]
}
], - "standings": {
- "page": 1,
- "players": [
- {
- "name": "player1",
- "rank": 1,
- "rating": 1500,
- "score": 3,
- "sheet": {
- "scores": [
- {
- "0": 2,
- "1": 2
}, - {
- "0": 4,
- "1": 3
}, - 0
], - "total": 6,
- "fire": true
}
}
]
}, - "featured": {
- "id": "khe72Fer",
- "fen": "rn1qkb1r/pQ3ppp/2b2n2/8/5P2/4P3/PP4PP/RNB1KBNR",
- "color": "black",
- "lastMove": "d7c6",
- "white": {
- "rank": 2,
- "name": "player1",
- "rating": 1360
}, - "black": {
- "rank": 5,
- "name": "player2",
- "rating": 1431
}
}, - "podium": [
- {
- "name": "player1",
- "rank": 1,
- "rating": 1500,
- "score": 3,
- "sheet": {
- "scores": [
- {
- "0": 2,
- "1": 2
}, - {
- "0": 4,
- "1": 3
}, - 0
], - "total": 6,
- "fire": true
}, - "nb": {
- "game": 3,
- "beserk": 0,
- "win": 2
}, - "performance": 1787
}
], - "stats": {
- "games": 454,
- "moves": 27542,
- "whiteWins": 236,
- "blackWins": 207,
- "draws": 11,
- "berserks": 0,
- "averageRating": 1320
}
}
Join an Arena tournament, possibly with a password and/or a team. Also unpauses if you had previously paused the tournament.
id required | string Example: hL7vMrFQ The tournament ID. |
You may need these depending on the tournament to join
password | string The tournament password, if one is required. Can also be a user-specific entry code generated and shared by the organizer. |
team | string The team to join the tournament with, for team battle tournaments |
pairMeAsap | boolean Default: false If the tournament is started, attempt to pair the user, even if they are not connected to the tournament page. This expires after one minute, to avoid pairing a user who is long gone. You may call "join" again to extend the waiting. |
{- "ok": true
}
Leave a future Arena tournament, or take a break on an ongoing Arena tournament. It's possible to join again later. Points and streaks are preserved.
id required | string Example: hL7vMrFQ The tournament ID. |
{- "ok": true
}
Set the teams and number of leaders of a team battle.
To update the other attributes of a team battle, use the tournament update endpoint.
id required | string The tournament ID (8 characters).. |
teams required | string All team IDs of the team battle, separated by commas. Make sure to always send the full list. Teams that are not in the list will be removed from the team battle. Example: |
nbLeaders required | integer Number team leaders per team. |
{- "id": "QITRjufu",
- "fullName": "U1700 SuperBlitz Arena",
- "rated": true,
- "clock": {
- "increment": 0,
- "limit": 180
}, - "minutes": 57,
- "createdBy": "lichess",
- "system": "arena",
- "secondsToStart": 0,
- "secondsToFinish": 36000,
- "isFinished": true,
- "isRecentlyFinished": true,
- "pairingsClosed": true,
- "startsAt": 1522803600000,
- "nbPlayers": 154,
- "perf": {
- "icon": ")",
- "key": "blitz",
- "name": "Blitz",
- "position": 1
}, - "schedule": {
- "freq": "hourly",
- "speed": "superblitz"
}, - "variant": "standard",
- "duels": [
- {
- "id": "0MM6q4tQ",
- "p": [
- {
- "n": "player1",
- "r": 1500,
- "k": 3
}, - {
- "n": "player2",
- "r": 1500,
- "k": 3
}
]
}
], - "standings": {
- "page": 1,
- "players": [
- {
- "name": "player1",
- "rank": 1,
- "rating": 1500,
- "score": 3,
- "sheet": {
- "scores": [
- {
- "0": 2,
- "1": 2
}, - {
- "0": 4,
- "1": 3
}, - 0
], - "total": 6,
- "fire": true
}
}
]
}, - "featured": {
- "id": "khe72Fer",
- "fen": "rn1qkb1r/pQ3ppp/2b2n2/8/5P2/4P3/PP4PP/RNB1KBNR",
- "color": "black",
- "lastMove": "d7c6",
- "white": {
- "rank": 2,
- "name": "player1",
- "rating": 1360
}, - "black": {
- "rank": 5,
- "name": "player2",
- "rating": 1431
}
}, - "podium": [
- {
- "name": "player1",
- "rank": 1,
- "rating": 1500,
- "score": 3,
- "sheet": {
- "scores": [
- {
- "0": 2,
- "1": 2
}, - {
- "0": 4,
- "1": 3
}, - 0
], - "total": 6,
- "fire": true
}, - "nb": {
- "game": 3,
- "beserk": 0,
- "win": 2
}, - "performance": 1787
}
], - "stats": {
- "games": 454,
- "moves": 27542,
- "whiteWins": 236,
- "blackWins": 207,
- "draws": 11,
- "berserks": 0,
- "averageRating": 1320
}
}
Download games of a tournament in PGN or ndjson format.
Games are sorted by reverse chronological order (most recent first).
The game stream is throttled, depending on who is making the request:
id required | string The tournament ID. |
player | string Only games of a particular player. Leave empty to fetch games of all players. |
moves | boolean Default: true Include the PGN moves. |
pgnInJson | boolean Default: false Include the full PGN within the JSON response, in a |
tags | boolean Default: true Include the PGN tags. |
clocks | boolean Default: false Include clock status when available. Either as PGN comments: Or in a |
evals | boolean Default: false Include analysis evaluations and comments, when available. Either as PGN comments: Or in an |
accuracy | |
opening | boolean Default: false Include the opening name. Example: |
division | boolean Default: false Plies which mark the beginning of the middlegame and endgame. Only available in JSON |
Players of an Arena tournament, with their score and performance, sorted by rank (best first).
Players are streamed as ndjson, i.e. one JSON object per line.
If called on an ongoing tournament, results can be inconsistent due to ranking changes while the players are being streamed. Use on finished tournaments for guaranteed consistency.
id required | string The tournament ID. |
nb | integer >= 1 Max number of players to fetch |
sheet | boolean Default: false Add a |
{- "rank": 4,
- "score": 389,
- "rating": 2618,
- "username": "opperwezen",
- "title": "IM",
- "performance": 2423,
- "team": "coders"
}
Teams of a team battle tournament, with top players, sorted by rank (best first).
id required | string The tournament ID. |
{- "id": "CdPg1ey4",
- "teams": [
- {
- "rank": 1,
- "id": "cat-lovers",
- "score": 842,
- "players": [
- {
- "user": {
- "name": "lizen69",
- "id": "lizen69"
}, - "score": 54
}, - {
- "user": {
- "name": "lizen249",
- "id": "lizen249"
}
}
]
}
]
}
Get all tournaments created by a given user.
Tournaments are sorted by reverse chronological order of start date (last starting first).
Tournaments are streamed as ndjson.
username required | string The user whose created tournaments to fetch |
status | integer Enum: 10 20 30 Include tournaments in the given status: "Created" (10), "Started" (20), "Finished" (30) You can add this parameter more than once to include tournaments in different statuses. Example: |
{- "id": "QITRjufu",
- "createdBy": "lichess",
- "system": "arena",
- "minutes": 57,
- "clock": {
- "limit": 0,
- "increment": 0
}, - "rated": true,
- "fullName": "U1700 SuperBlitz Arena",
- "nbPlayers": 154,
- "variant": {
- "key": "standard",
- "name": "string",
- "short": "string"
}, - "startsAt": 1522803600000,
- "finishesAt": 1522807200000,
- "status": 30,
- "perf": {
- "key": "blitz",
- "name": "Blitz",
- "position": 1,
- "icon": ")"
}, - "secondsToStart": 576,
- "hasMaxRating": true,
- "maxRating": {
- "perf": "ultraBullet",
- "rating": 1700
}, - "minRating": {
- "perf": "ultraBullet",
- "rating": 1700
}, - "minRatedGames": {
- "nb": 20,
- "perf": "ultraBullet"
}, - "onlyTitled": false,
- "teamMember": "coders",
- "private": true,
- "position": {
- "eco": "C41",
- "name": "Philidor Defense",
- "fen": "rnbqkbnr/ppp2ppp/3p4/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq -",
}, - "schedule": {
- "freq": "hourly",
- "speed": "superblitz"
}, - "teamBattle": {
- "teams": [
- "coders"
], - "nbLeaders": 3
}, - "winner": {
- "id": "lichess",
- "name": "lichess",
- "title": "NM"
}
}
Get all Arena tournaments relevant to a team.
Tournaments are sorted by reverse chronological order of start date (last starting first).
Tournaments are streamed as ndjson.
teamId required | string ID of the team |
max | integer >= 1 Default: 100 How many tournaments to download. |
{- "id": "QITRjufu",
- "createdBy": "lichess",
- "system": "arena",
- "minutes": 57,
- "clock": {
- "limit": 0,
- "increment": 0
}, - "rated": true,
- "fullName": "U1700 SuperBlitz Arena",
- "nbPlayers": 154,
- "variant": {
- "key": "standard",
- "name": "string",
- "short": "string"
}, - "startsAt": 1522803600000,
- "finishesAt": 1522807200000,
- "status": 30,
- "perf": {
- "key": "blitz",
- "name": "Blitz",
- "position": 1,
- "icon": ")"
}, - "secondsToStart": 576,
- "hasMaxRating": true,
- "maxRating": {
- "perf": "ultraBullet",
- "rating": 1700
}, - "minRating": {
- "perf": "ultraBullet",
- "rating": 1700
}, - "minRatedGames": {
- "nb": 20,
- "perf": "ultraBullet"
}, - "onlyTitled": false,
- "teamMember": "coders",
- "private": true,
- "position": {
- "eco": "C41",
- "name": "Philidor Defense",
- "fen": "rnbqkbnr/ppp2ppp/3p4/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq -",
}, - "schedule": {
- "freq": "hourly",
- "speed": "superblitz"
}, - "teamBattle": {
- "teams": [
- "coders"
], - "nbLeaders": 3
}, - "winner": {
- "id": "lichess",
- "name": "lichess",
- "title": "NM"
}
}
Access Swiss tournaments played on Lichess. Read more about Swiss tournaments..
Create a Swiss tournament for your team.
This endpoint mirrors the Swiss tournament form from your team pagee.
You can create up to 12 tournaments per day.
Additional restrictions:
teamId required | string ID of the team |
Parameters of the tournament
name | string [ 2 .. 30 ] characters The tournament name. Leave empty to get a random Grandmaster name |
clock.limit required | number Enum: 0 15 30 45 60 90 120 180 240 300 360 420 480 600 900 1200 1500 1800 2400 3000 3600 4200 4800 5400 6000 6600 7200 7800 8400 9000 9600 10200 10800 Clock initial time in seconds |
clock.increment required | integer [ 0 .. 120 ] Clock increment in seconds |
nbRounds required | integer [ 3 .. 100 ] Maximum number of rounds to play |
startsAt | integer Timestamp in milliseconds to start the tournament at a given date and time. By default, it starts 10 minutes after creation. |
roundInterval | integer Enum: -1 5 10 20 30 45 60 120 180 300 600 900 1200 1800 2700 3600 86400 172800 604800 99999999 How long to wait between each round, in seconds. Set to 99999999 to manually schedule each round from the tournament UI. If empty or -1, a sensible value is picked automatically. |
variant | string (VariantKey) Enum: "standard" "chess960" "crazyhouse" "antichess" "atomic" "horde" "kingOfTheHill" "racingKings" "threeCheck" "fromPosition" |
position | string (FromPositionFEN) Custom initial position (in FEN). Variant must be standard, fromPosition, or chess960 (if a valid 960 starting position), and the game cannot be rated. |
description | string Anything you want to tell players about the tournament |
rated | boolean Default: true Games are rated and impact players ratings |
password | string Make the tournament private and restrict access with a password. |
forbiddenPairings | string Usernames of players that must not play together. Two usernames per line, separated by a space. |
manualPairings | string Manual pairings for the next round. Two usernames per line, separated by a space. Example:
To give a bye (1 point) to a player instead of a pairing, add a line like so:
Missing players will be considered absent and get zero points. |
chatFor | number Default: 20 Who can read and write in the chat.
|
conditions.minRating.rating | integer Enum: 1000 1100 1200 1300 1400 1500 1600 1700 1800 1900 2000 2100 2200 2300 2400 2500 2600 Minimum rating to join. Leave empty to let everyone join the tournament. |
conditions.maxRating.rating | integer Enum: 2200 2100 2000 1900 1800 1700 1600 1500 1400 1300 1200 1100 1000 900 800 Maximum rating to join. Based on best rating reached in the last 7 days. Leave empty to let everyone join the tournament. |
conditions.nbRatedGame.nb | integer [ 0 .. 200 ] Minimum number of rated games required to join. |
conditions.playYourGames | boolean Default: false Only let players join if they have played their last swiss game. If they failed to show up in a recent swiss event, they won't be able to enter yours. This results in a better swiss experience for the players who actually show up. |
conditions.allowList | string Predefined list of usernames that are allowed to join, separated by commas.
If this list is non-empty, then usernames absent from this list will be forbidden to join.
Adding |
{- "rated": true,
- "clock": {
- "increment": 0,
- "limit": 300
}, - "createdBy": "thibault",
- "id": "ZmKWCOye",
- "name": "Wang",
- "nbOngoing": 0,
- "nbPlayers": 0,
- "nbRounds": 2,
- "nextRound": {
- "at": "2020-05-11T12:23:18.233-06:00",
- "in": 600
}, - "round": 0,
- "startsAt": "2020-05-11T12:23:18.233-06:00",
- "status": "created",
- "variant": "standard",
- "isRecentlyFinished": false,
- "password": true,
- "stats": {
- "absences": 1608,
- "averageRating": 1588,
- "blackWins": 42541,
- "byes": 12,
- "draws": 0,
- "games": 42689,
- "whiteWins": 42837
}
}
Get detailed info about a Swiss tournament.
id required | string The Swiss tournament ID. |
{- "rated": true,
- "clock": {
- "increment": 0,
- "limit": 300
}, - "createdBy": "thibault",
- "id": "ZmKWCOye",
- "name": "Wang",
- "nbOngoing": 0,
- "nbPlayers": 0,
- "nbRounds": 2,
- "nextRound": {
- "at": "2020-05-11T12:23:18.233-06:00",
- "in": 600
}, - "round": 0,
- "startsAt": "2020-05-11T12:23:18.233-06:00",
- "status": "created",
- "variant": "standard",
- "isRecentlyFinished": false,
- "password": true,
- "stats": {
- "absences": 1608,
- "averageRating": 1588,
- "blackWins": 42541,
- "byes": 12,
- "draws": 0,
- "games": 42689,
- "whiteWins": 42837
}
}
Update a Swiss tournament.
Be mindful not to make important changes to ongoing tournaments.
Additional restrictions:
id required | string Example: hL7vMrFQ The tournament ID. |
Parameters of the tournament
name | string [ 2 .. 30 ] characters The tournament name. Leave empty to get a random Grandmaster name |
clock.limit required | number Enum: 0 15 30 45 60 90 120 180 240 300 360 420 480 600 900 1200 1500 1800 2400 3000 3600 4200 4800 5400 6000 6600 7200 7800 8400 9000 9600 10200 10800 Clock initial time in seconds |
clock.increment required | integer [ 0 .. 120 ] Clock increment in seconds |
nbRounds required | integer [ 3 .. 100 ] Maximum number of rounds to play |
startsAt | integer Timestamp in milliseconds to start the tournament at a given date and time. By default, it starts 10 minutes after creation. |
roundInterval | integer Enum: -1 5 10 20 30 45 60 120 180 300 600 900 1200 1800 2700 3600 86400 172800 604800 99999999 How long to wait between each round, in seconds. Set to 99999999 to manually schedule each round from the tournament UI, or with the API. If empty or -1, a sensible value is picked automatically. |
variant | string (VariantKey) Enum: "standard" "chess960" "crazyhouse" "antichess" "atomic" "horde" "kingOfTheHill" "racingKings" "threeCheck" "fromPosition" |
description | string Anything you want to tell players about the tournament |
rated | boolean Default: true Games are rated and impact players ratings |
password | string Make the tournament private and restrict access with a password. |
forbiddenPairings | string Usernames of players that must not play together. Two usernames per line, separated by a space. |
manualPairings | string Manual pairings for the next round. Two usernames per line, separated by a space. Present players without a valid pairing will be given a bye, which is worth 1 point. Forfeited players will get 0 points. |
chatFor | number Default: 20 Who can read and write in the chat.
|
conditions.minRating.rating | integer Enum: 1000 1100 1200 1300 1400 1500 1600 1700 1800 1900 2000 2100 2200 2300 2400 2500 2600 Minimum rating to join. Leave empty to let everyone join the tournament. |
conditions.maxRating.rating | integer Enum: 2200 2100 2000 1900 1800 1700 1600 1500 1400 1300 1200 1100 1000 900 800 Maximum rating to join. Based on best rating reached in the last 7 days. Leave empty to let everyone join the tournament. |
conditions.nbRatedGame.nb | integer [ 0 .. 200 ] Minimum number of rated games required to join. |
conditions.playYourGames | boolean Default: false Only let players join if they have played their last swiss game. If they failed to show up in a recent swiss event, they won't be able to enter yours. This results in a better swiss experience for the players who actually show up. |
conditions.allowList | string Predefined list of usernames that are allowed to join, separated by commas.
If this list is non-empty, then usernames absent from this list will be forbidden to join.
Adding |
{- "rated": true,
- "clock": {
- "increment": 0,
- "limit": 300
}, - "createdBy": "thibault",
- "id": "ZmKWCOye",
- "name": "Wang",
- "nbOngoing": 0,
- "nbPlayers": 0,
- "nbRounds": 2,
- "nextRound": {
- "at": "2020-05-11T12:23:18.233-06:00",
- "in": 600
}, - "round": 0,
- "startsAt": "2020-05-11T12:23:18.233-06:00",
- "status": "created",
- "variant": "standard",
- "isRecentlyFinished": false,
- "password": true,
- "stats": {
- "absences": 1608,
- "averageRating": 1588,
- "blackWins": 42541,
- "byes": 12,
- "draws": 0,
- "games": 42689,
- "whiteWins": 42837
}
}
Manually schedule the next round date and time of a Swiss tournament.
This sets the roundInterval
field to 99999999
, i.e. manual scheduling.
All further rounds will need to be manually scheduled, unless the roundInterval
field is changed back to automatic scheduling.
id required | string Example: hL7vMrFQ The tournament ID. |
Parameters of the tournament
date | integer Timestamp in milliseconds to start the next round at a given date and time. |
{- "error": "This request is invalid because [...]"
}
Join a Swiss tournament, possibly with a password.
id required | string Example: hL7vMrFQ The tournament ID. |
You may need these depending on the tournament to join
password | string The tournament password, if one is required |
{- "ok": true
}
Leave a future Swiss tournament, or take a break on an ongoing Swiss tournament. It's possible to join again later. Points are preserved.
id required | string Example: hL7vMrFQ The tournament ID. |
{- "ok": true
}
Download a tournament in the Tournament Report File format, the FIDE standard.
Documentation: https://www.fide.com/FIDE/handbook/C04Annex2_TRF16.pdf
id required | string The tournament ID. |
Download games of a swiss tournament in PGN or ndjson format.
Games are sorted by reverse chronological order (last round first).
The game stream is throttled, depending on who is making the request:
id required | string The tournament ID. |
player | string Only the games played by a given player |
moves | boolean Default: true Include the PGN moves. |
pgnInJson | boolean Default: false Include the full PGN within the JSON response, in a |
tags | boolean Default: true Include the PGN tags. |
clocks | boolean Default: false Include clock status when available. Either as PGN comments: Or in a |
evals | boolean Default: false Include analysis evaluations and comments, when available. Either as PGN comments: Or in an |
accuracy | |
opening | boolean Default: false Include the opening name. Example: |
division | boolean Default: false Plies which mark the beginning of the middlegame and endgame. Only available in JSON |
Players of a swiss tournament, with their score and performance, sorted by rank (best first).
Players are streamed as ndjson.
If called on an ongoing tournament, results can be inconsistent due to ranking changes while the players are being streamed. Use on finished tournaments for guaranteed consistency.
id required | string The tournament ID. |
nb | integer >= 1 Max number of players to fetch |
{- "rank": 4,
- "points": 8.5,
- "tieBreak": 77,
- "rating": 2618,
- "username": "opperwezen",
- "title": "IM",
- "performance": 2423
}
Get all swiss tournaments of a team.
Tournaments are sorted by reverse chronological order of start date (last starting first).
Tournaments are streamed as ndjson.
teamId required | string Example: coders |
max | integer >= 1 Default: 100 How many tournaments to download. |
{- "rated": true,
- "clock": {
- "increment": 0,
- "limit": 300
}, - "createdBy": "thibault",
- "id": "ZmKWCOye",
- "name": "Wang",
- "nbOngoing": 0,
- "nbPlayers": 0,
- "nbRounds": 2,
- "nextRound": {
- "at": "2020-05-11T12:23:18.233-06:00",
- "in": 600
}, - "round": 0,
- "startsAt": "2020-05-11T12:23:18.233-06:00",
- "status": "created",
- "variant": "standard",
- "isRecentlyFinished": false,
- "password": true,
- "stats": {
- "absences": 1608,
- "averageRating": 1588,
- "blackWins": 42541,
- "byes": 12,
- "draws": 0,
- "games": 42689,
- "whiteWins": 42837
}
}
Access simuls played on Lichess. https://lichess.org/simul
Get recently created, started, finished, simuls.
Created and finished simul lists are not exhaustives, only those with strong enough host will be listed, the same filter is used to display simuls on https://lichess.org/simul.
When authenticated with OAuth2, the pending list will be populated with your created, but unstarted simuls.
{- "pending": [
- {
- "id": "pDGbxhUe",
- "name": "GM ChessWeeb",
- "fullName": "GM ChessWeeb simul",
- "host": {
- "id": "chessweeb",
- "name": "ChessWeeb",
- "rating": 1500,
- "title": "GM"
}, - "isCreated": false,
- "isFinished": true,
- "isRunning": false,
- "estimatedStartAt": 1620029815106,
- "startedAt": 1620029815106,
- "finishedAt": 1620029937283,
- "nbApplicants": 0,
- "nbPairings": 24,
- "text": "",
- "variants": [
- {
- "icon": "+",
- "key": "standard",
- "name": "Standard"
}
]
}
], - "created": [
- {
- "id": "pDGbxhUe",
- "name": "GM ChessWeeb",
- "fullName": "GM ChessWeeb simul",
- "host": {
- "id": "chessweeb",
- "name": "ChessWeeb",
- "rating": 1500,
- "title": "GM"
}, - "isCreated": false,
- "isFinished": true,
- "isRunning": false,
- "estimatedStartAt": 1620029815106,
- "startedAt": 1620029815106,
- "finishedAt": 1620029937283,
- "nbApplicants": 0,
- "nbPairings": 24,
- "text": "",
- "variants": [
- {
- "icon": "+",
- "key": "standard",
- "name": "Standard"
}
]
}
], - "started": [
- {
- "id": "pDGbxhUe",
- "name": "GM ChessWeeb",
- "fullName": "GM ChessWeeb simul",
- "host": {
- "id": "chessweeb",
- "name": "ChessWeeb",
- "rating": 1500,
- "title": "GM"
}, - "isCreated": false,
- "isFinished": true,
- "isRunning": false,
- "estimatedStartAt": 1620029815106,
- "startedAt": 1620029815106,
- "finishedAt": 1620029937283,
- "nbApplicants": 0,
- "nbPairings": 24,
- "text": "",
- "variants": [
- {
- "icon": "+",
- "key": "standard",
- "name": "Standard"
}
]
}
], - "finished": [
- {
- "id": "pDGbxhUe",
- "name": "GM ChessWeeb",
- "fullName": "GM ChessWeeb simul",
- "host": {
- "id": "chessweeb",
- "name": "ChessWeeb",
- "rating": 1500,
- "title": "GM"
}, - "isCreated": false,
- "isFinished": true,
- "isRunning": false,
- "estimatedStartAt": 1620029815106,
- "startedAt": 1620029815106,
- "finishedAt": 1620029937283,
- "nbApplicants": 0,
- "nbPairings": 24,
- "text": "",
- "variants": [
- {
- "icon": "+",
- "key": "standard",
- "name": "Standard"
}
]
}
]
}
Access Lichess studies. https://lichess.org/study
Download one study chapter in PGN format.
studyId required | string The study ID (8 characters). |
chapterId required | string The chapter ID (8 characters). |
clocks | boolean Default: true Include clock comments in the PGN moves, when available. Example: |
comments | boolean Default: true Include analysis and annotator comments in the PGN moves, when available. Example: |
variations | boolean Default: true Include non-mainline moves, when available. Example: |
source | boolean Default: false Add a Example: |
orientation | boolean Default: false Add a Example: |
Download all chapters of a study in PGN format.
studyId required | string The study ID (8 characters). |
clocks | boolean Default: true Include clock comments in the PGN moves, when available. Example: |
comments | boolean Default: true Include analysis and annotator comments in the PGN moves, when available. Example: |
variations | boolean Default: true Include non-mainline moves, when available. Example: |
source | boolean Default: false Add a Example: |
orientation | boolean Default: false Add a Example: |
Imports arbitrary PGN into an existing study. Creates a new chapter in the study.
If the PGN contains multiple games (separated by 2 or more newlines) then multiple chapters will be created within the study.
Note that a study can contain at most 64 chapters.
studyId required | string ID of the study |
Parameters of the import
name required | string [ 1 .. 100 ] characters Name of the new chapter. If multiple chapters are created, the names will be infered from the PGN tags. |
pgn required | string PGN to import. Can contain multiple games separated by 2 or more newlines. |
orientation | string Default: "white" Enum: "white" "black" Default board orientation. |
variant | string (VariantKey) Enum: "standard" "chess960" "crazyhouse" "antichess" "atomic" "horde" "kingOfTheHill" "racingKings" "threeCheck" "fromPosition" |
{- "chapters": [
- {
- "id": "WTvnkWAL",
- "name": "Game 2"
}
]
}
Download all chapters of all studies of a user in PGN format.
If authenticated, then all public, unlisted, and private studies are included.
If not, only public (non-unlisted) studies are included.
username required | string The user whose studies we export |
clocks | boolean Default: true Include clock comments in the PGN moves, when available. Example: |
comments | boolean Default: true Include analysis and annotator comments in the PGN moves, when available. Example: |
variations | boolean Default: true Include non-mainline moves, when available. Example: |
source | boolean Default: false Add a Example: |
orientation | boolean Default: false Add a Example: |
Get metadata (name and dates) of all studies of a user.
If authenticated, then all public, unlisted, and private studies are included.
If not, only public (non-unlisted) studies are included.
Studies are streamed as ndjson.
username required | string The user whose studies we list |
[- {
- "id": "WTvnkWAL",
- "name": "Guess the move",
- "createdAt": 1463756350225,
- "updatedAt": 1469965025205
}
]
Private messages with other players. https://lichess.org/inbox
Relay chess events on Lichess. Official broadcasts are maintained by Lichess, but you can create your own broadcasts to cover any live game or chess event. You will need to publish PGN on a public URL so that Lichess can pull updates from it. Alternatively, you can push PGN updates to Lichess using this API endpoint.
Broadcasts are organized in tournaments, which have several rounds, which have several games. You must first create a tournament, then you can add rounds to them.
Get all incoming, ongoing, and finished official broadcasts. The broadcasts are sorted by start date, most recent first.
Broadcasts are streamed as ndjson.
nb | integer >= 1 Default: 20 Max number of broadcasts to fetch |
[- {
- "tour": {
- "id": "QYiOYnl1",
- "name": "New in Chess Classic | Finals",
- "slug": "new-in-chess-classic--finals",
- "description": "Match for 1st 2nd and 3rd place.",
- "createdAt": 1525789431889
}, - "rounds": [
- {
- "id": "BueO56UJ",
- "name": "Finals Day 1",
- "slug": "finals-day-1",
- "createdAt": 1525789431889
}, - {
- "id": "yeGGfkfY",
- "name": "Finals Day 2",
- "slug": "finals-day-2",
- "createdAt": 1525789431889
}
]
}
]
Create a new broadcast tournament to relay external games. This endpoint accepts the same form data as the web form.
name required | string Name of the broadcast tournament. Length must be between 3 and 80 characters. Example: |
description required | string Short description of the broadcast tournament. Length must be between 3 and 400 characters. Example: |
autoLeaderboard required | boolean Compute and display a simple leaderboard based on game results |
markdown | string Optional long description of the broadcast. Markdown is supported. Length must be less than 20,000 characters. |
tier | integer Optional, for Lichess admins only, use to feature on /broadcast.
|
players | any Optional replace player names, ratings and titles. One line per player, formatted as such:
Example: DrNykterstein;Magnus Carlsen;2863 AnishGiri;Anish Giri;2764;GM |
{- "tour": {
- "id": "QYiOYnl1",
- "name": "New in Chess Classic | Finals",
- "slug": "new-in-chess-classic--finals",
- "description": "Match for 1st 2nd and 3rd place.",
- "createdAt": 1525789431889
}, - "rounds": [
- {
- "id": "BueO56UJ",
- "name": "Finals Day 1",
- "slug": "finals-day-1",
- "createdAt": 1525789431889
}, - {
- "id": "yeGGfkfY",
- "name": "Finals Day 2",
- "slug": "finals-day-2",
- "createdAt": 1525789431889
}
]
}
Get information about a broadcast tournament.
slug required | string The broadcast tournament slug. Only used for SEO, the slug can be safely replaced by |
broadcastTournamentId required | string The broadcast tournament ID (8 characters). |
{- "tour": {
- "id": "QYiOYnl1",
- "name": "New in Chess Classic | Finals",
- "slug": "new-in-chess-classic--finals",
- "description": "Match for 1st 2nd and 3rd place.",
- "createdAt": 1525789431889
}, - "rounds": [
- {
- "id": "BueO56UJ",
- "name": "Finals Day 1",
- "slug": "finals-day-1",
- "createdAt": 1525789431889
}, - {
- "id": "yeGGfkfY",
- "name": "Finals Day 2",
- "slug": "finals-day-2",
- "createdAt": 1525789431889
}
]
}
Update information about a broadcast tournament that you created. This endpoint accepts the same form data as the web form. All fields must be populated with data. Missing fields will override the broadcast with empty data.
broadcastTournamentId required | string The broadcast ID (8 characters). |
name required | string Name of the broadcast tournament. Length must be between 3 and 80 characters. Example: |
description required | string Short description of the broadcast tournament. Length must be between 3 and 400 characters. Example: |
autoLeaderboard required | boolean Compute and display a simple leaderboard based on game results |
markdown | string Optional long description of the broadcast. Markdown is supported. Length must be less than 20,000 characters. |
tier | integer Optional, for Lichess admins only, use to feature on /broadcast.
|
players | any Optional replace player names, ratings and titles. One line per player, formatted as such:
Example: DrNykterstein;Magnus Carlsen;2863 AnishGiri;Anish Giri;2764;GM |
{- "ok": true
}
Create a new broadcast round to relay external games. This endpoint accepts the same form data as the web form.
broadcastTournamentId required | string The broadcast tournament ID (8 characters). |
name required | string Name of the broadcast round. Length must be between 3 and 80 characters. Example: |
syncUrl | string URL that Lichess will poll to get updates about the games. It must be publicly accessible from the Internet. Example: If the syncUrl is missing, then the broadcast needs to be fed by pushing PGN to it. |
syncUrlRound | string Required if |
startsAt | integer >= 1356998400070 Timestamp in milliseconds of broadcast round start. Leave empty to manually start the broadcast round. Example: |
delay | integer [ 0 .. 1800 ] Delay in seconds for movements to appear on the broadcast. Leave it empty if you don't need it. Example: |
period | integer [ 2 .. 60 ] (Only for Admins) Waiting time for each poll. |
finished | boolean Default: false Mark whether the round has been completed. |
{- "round": {
- "id": "BueO56UJ",
- "name": "Finals Day 1",
- "slug": "finals-day-1",
- "createdAt": 1525789431889
}, - "tour": {
- "id": "QYiOYnl1",
- "name": "New in Chess Classic | Finals",
- "slug": "new-in-chess-classic--finals",
- "description": "Match for 1st 2nd and 3rd place.",
- "createdAt": 1525789431889
}, - "study": {
- "writeable": true
}, - "games": [
- {
- "id": "GRjidNTw",
- "name": "Martin Fargac - Vit Kostka",
- "ongoing": true,
- "res": "*",
}, - {
- "id": "81TcKCWT",
- "name": "Pavel Zabystrzan - Kilian Slovak",
- "res": "½-½",
}, - {
- "id": "xEfufedI",
- "name": "Roman Pilch - Bartolomej Buchta",
- "res": "1-0",
}
]
}
Get information about a broadcast round.
broadcastTournamentSlug required | string The broadcast tournament slug. Only used for SEO, the slug can be safely replaced by |
broadcastRoundSlug required | string The broadcast round slug. Only used for SEO, the slug can be safely replaced by |
broadcastRoundId required | string The broadcast Round ID (8 characters). |
{- "round": {
- "id": "BueO56UJ",
- "name": "Finals Day 1",
- "slug": "finals-day-1",
- "createdAt": 1525789431889
}, - "tour": {
- "id": "QYiOYnl1",
- "name": "New in Chess Classic | Finals",
- "slug": "new-in-chess-classic--finals",
- "description": "Match for 1st 2nd and 3rd place.",
- "createdAt": 1525789431889
}, - "study": {
- "writeable": true
}, - "games": [
- {
- "id": "GRjidNTw",
- "name": "Martin Fargac - Vit Kostka",
- "ongoing": true,
- "res": "*",
}, - {
- "id": "81TcKCWT",
- "name": "Pavel Zabystrzan - Kilian Slovak",
- "res": "½-½",
}, - {
- "id": "xEfufedI",
- "name": "Roman Pilch - Bartolomej Buchta",
- "res": "1-0",
}
]
}
Update information about a broadcast round that you created.
This endpoint accepts the same form data as the web form.
All fields must be populated with data. Missing fields will override the broadcast with empty data.
For instance, if you omit startDate
, then any pre-existing start date will be removed.
broadcastRoundId required | string The broadcast round ID (8 characters). |
name required | string Name of the broadcast round. Length must be between 3 and 80 characters. Example: |
syncUrl | string URL that Lichess will poll to get updates about the games. It must be publicly accessible from the Internet. Example: |
syncUrlRound | string Required if |
startsAt | integer >= 1356998400070 Timestamp in milliseconds of broadcast start. Leave empty to manually start the broadcast. Example: |
delay | integer [ 0 .. 1800 ] Delay in seconds for movements to appear on the broadcast. Leave it empty if you don't need it. Example: |
period | integer [ 2 .. 60 ] (Only for Admins) Waiting time for each poll. |
finished | boolean Default: false Mark whether the round has been completed. |
{- "ok": true
}
Update your broadcast with new PGN. Only for broadcast without a source URL.
broadcastRoundId required | string The broadcast round ID (8 characters). |
The PGN. It can contain up to 64 games, separated by a double new line.
{- "moves": 12
}
This streaming endpoint first sends all games of a broadcast tournament in PGN format.
Then, it waits for new moves to be played. As soon as it happens, the entire PGN of the game is sent to the stream.
The stream will also send PGNs when games are added to the tournament.
This is the best way to get updates about an ongoing tournament. Streaming means no polling, and no pollings means no latency, and minimum impact on the server.
broadcastRoundId required | string The broadcast round ID (8 characters). |
Download all games of a single round of a broadcast tournament in PGN format.
You could poll this endpoint to get updates about a tournament, but it would be slow, and very inneficient.
Instead, consider streaming the tournament to get a new PGN every time a game is updated, in real-time.
broadcastRoundId required | string The round ID (8 characters). |
Download all games of all rounds of a broadcast in PGN format.
If a study:read
OAuth token is provided,
the private rounds where the user is a contributor will be available.
You may want to download only the games of a single round instead.
broadcastTournamentId required | string The broadcast tournament ID (8 characters). |
Stream all broadcast rounds you are a member of.
Also includes broadcasts rounds you did not create, but were invited to.
Also includes broadcasts rounds where you're a non-writing member. See the writeable
flag in the response.
Rounds are ordered by rank, which is roughly chronological, most recent first, slightly pondered with popularity.
nb | integer >= 1 Example: nb=20 How many rounds to get |
{- "tour": {
- "description": "April 18th - 28th | 10-round Swiss | Classical time control",
- "id": "x7WskVz3",
- "name": "Moonway Chess Festival",
- "tier": "high",
- "slug": "moonway-chess-festival"
}, - "round": {
- "finished": true,
- "id": "LXfsdxuf",
- "name": "Round 5",
- "slug": "round-5",
- "startsAt": 1682168400000,
}, - "study": {
- "writeable": true
}
}
Access Lichess cloud evaluations database. https://lichess.org/analysis
Get the cached evaluation of a position, if available.
Opening positions have more chances of being available. There are about 15 million positions in the database.
Up to 5 variations may be available. Variants are supported.
Use this endpoint to fetch a few positions here and there. If you want to download a lot of positions, get the full list from our exported database.
fen required | string Example: fen=rnbqkbnr/ppp1pppp/8/3pP3/8/8/PPPP1PPP/RNBQKBNR b KQkq - 0 2 FEN of the position |
multiPv | number Default: 1 Number of variations |
variant | string (VariantKey) Default: "standard" Enum: "standard" "chess960" "crazyhouse" "antichess" "atomic" "horde" "kingOfTheHill" "racingKings" "threeCheck" "fromPosition" Example: variant=standard Variant |
{- "fen": "rnbqkbnr/ppp1pppp/8/3pP3/8/8/PPPP1PPP/RNBQKBNR b KQkq - 0 2",
- "knodes": 13683,
- "depth": 22,
- "pvs": [
- {
- "moves": "c8f5 d2d4 e7e6 g1f3 g8e7 c1e3 c7c5 d4c5 e7c6 b1c3",
- "cp": -13
}, - {
- "moves": "c7c5 c2c3 d5d4 g1f3 b8c6 c3d4 c6d4 b1c3 c8d7 f1d3",
- "cp": -1
}, - {
- "moves": "e7e6 d2d4 c7c5 c2c3 b8c6 g1f3 c8d7 b1a3 c5d4 c3d4",
- "cp": 24
}
]
}
This API is in alpha and subject to change.
Use or provide external engine analysis.
External engines can provide analysis on pages like the analysis board, running as a service outside of the browser, or even on a different machine.
Lists all external engines that have been registered for the user, and the credentials required to use them.
[- {
- "id": "eei_aTKImBJOnv6j",
- "name": "Stockfish 15",
- "clientSecret": "ees_mdF2hK0hlKGSPeC6",
- "userId": "thibault",
- "maxThreads": 8,
- "maxHash": 2048,
- "defaultDepth": 24,
- "variants": [
- "chess"
], - "providerData": "string"
}
]
Registers a new external engine for the user. It can then be selected and used on the analysis board.
After registering, the provider should start waiting for analyis requests.
A new external engine registration.
name required | string [ 3 .. 200 ] characters Display name of the engine. |
maxThreads required | integer [ 1 .. 65536 ] Maximum number of available threads. |
maxHash required | integer [ 1 .. 1048576 ] Maximum available hash table size, in MiB. |
defaultDepth required | integer [ 0 .. 246 ] Estimated depth of normal search. |
variants | Array of strings (UciVariant) Items Enum: "chess" "crazyhouse" "antichess" "atomic" "horde" "kingofthehill" "racingkings" "3check" Optional list of supported chess variants. |
providerSecret required | string [ 16 .. 1024 ] characters A random token that can be used to wait for analysis requests and provide analysis. The engine provider should securely generate a random string. The token will not be readable again, even by the user. The analysis provider can register multiple engines with the same token, even for different users, and wait for analysis requests from any of them. In this case, the request must not be made via CORS, so that the token is not revealed to any of the users. |
providerData | string Arbitrary data that the engine provider can use for identification or bookkeeping. Users can read this information, but updating it requires knowing
or changing the |
{- "name": "Stockfish 15",
- "maxThreads": 8,
- "maxHash": 2048,
- "defaultDepth": 24,
- "variants": [
- "chess"
], - "providerSecret": "Dee3uwieZei9ahpaici9bee2yahsai0K",
- "providerData": "string"
}
{- "id": "eei_aTKImBJOnv6j",
- "name": "Stockfish 15",
- "clientSecret": "ees_mdF2hK0hlKGSPeC6",
- "userId": "thibault",
- "maxThreads": 8,
- "maxHash": 2048,
- "defaultDepth": 24,
- "variants": [
- "chess"
], - "providerData": "string"
}
Get properties and credentials of an external engine.
id required | string Example: eei_aTKImBJOnv6j The external engine id. |
{- "id": "eei_aTKImBJOnv6j",
- "name": "Stockfish 15",
- "clientSecret": "ees_mdF2hK0hlKGSPeC6",
- "userId": "thibault",
- "maxThreads": 8,
- "maxHash": 2048,
- "defaultDepth": 24,
- "variants": [
- "chess"
], - "providerData": "string"
}
Updates the properties of an external engine.
id required | string Example: eei_aTKImBJOnv6j The external engine id. |
A modified engine registration.
name required | string [ 3 .. 200 ] characters Display name of the engine. |
maxThreads required | integer [ 1 .. 65536 ] Maximum number of available threads. |
maxHash required | integer [ 1 .. 1048576 ] Maximum available hash table size, in MiB. |
defaultDepth required | integer [ 0 .. 246 ] Estimated depth of normal search. |
variants | Array of strings (UciVariant) Items Enum: "chess" "crazyhouse" "antichess" "atomic" "horde" "kingofthehill" "racingkings" "3check" Optional list of supported chess variants. |
providerSecret required | string [ 16 .. 1024 ] characters A random token that can be used to wait for analysis requests and provide analysis. The engine provider should securely generate a random string. The token will not be readable again, even by the user. The analysis provider can register multiple engines with the same token, even for different users, and wait for analysis requests from any of them. In this case, the request must not be made via CORS, so that the token is not revealed to any of the users. |
providerData | string Arbitrary data that the engine provider can use for identification or bookkeeping. Users can read this information, but updating it requires knowing
or changing the |
{- "name": "Stockfish 15",
- "maxThreads": 8,
- "maxHash": 2048,
- "defaultDepth": 24,
- "variants": [
- "chess"
], - "providerSecret": "Dee3uwieZei9ahpaici9bee2yahsai0K",
- "providerData": "string"
}
{- "id": "eei_aTKImBJOnv6j",
- "name": "Stockfish 15",
- "clientSecret": "ees_mdF2hK0hlKGSPeC6",
- "userId": "thibault",
- "maxThreads": 8,
- "maxHash": 2048,
- "defaultDepth": 24,
- "variants": [
- "chess"
], - "providerData": "string"
}
Endpoint: https://engine.lichess.ovh/api/external-engine/{id}/analyse
Request analysis from an external engine.
Response content is streamed as newline delimited JSON. The properties are based on the UCI specification. Analysis stops when the client goes away, the requested limit is reached, or the provider goes away.
id required | string Example: eei_aTKImBJOnv6j The external engine id. |
Engine credentials and analysis request.
clientSecret required | string |
required | object (ExternalEngineWork) |
{- "clientSecret": "ees_mdF2hK0hlKGSPeC6",
- "work": {
- "sessionId": "abcd1234",
- "threads": 4,
- "hash": 128,
- "infinite": false,
- "multiPv": 1,
- "variant": "chess",
- "initialFen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
- "moves": [
- "e2e4",
- "g8f6"
]
}
}
{- "time": 6880,
- "depth": 25,
- "nodes": 7230340,
- "pvs": [
- {
- "depth": 25,
- "cp": 40,
- "mate": 0,
- "moves": [
- "e2e4",
- "c7c6",
- "g1f3",
- "d7d5",
- "d2d3",
- "d5e4"
]
}
]
}
Endpoint: https://engine.lichess.ovh/api/external-engine/work
Wait for an analysis requests to any of the external engines that
have been registered with the given secret
.
Uses long polling.
After acquiring a request, the provider should immediately start streaming the results.
Provider credentials.
providerSecret | string |
{- "providerSecret": "Dee3uwieZei9ahpaici9bee2yahsai0K"
}
{- "id": "aingoohiJee2sius",
- "work": {
- "sessionId": "abcd1234",
- "threads": 4,
- "hash": 128,
- "infinite": false,
- "multiPv": 1,
- "variant": "chess",
- "initialFen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
- "moves": [
- "e2e4",
- "g8f6"
]
}, - "engine": {
- "id": "eei_aTKImBJOnv6j",
- "name": "Stockfish 15",
- "clientSecret": "ees_mdF2hK0hlKGSPeC6",
- "userId": "thibault",
- "maxThreads": 8,
- "maxHash": 2048,
- "defaultDepth": 24,
- "variants": [
- "chess"
], - "providerData": "string"
}
}
Endpoint: https://engine.lichess.ovh/api/external-engine/work/{id}
Submit a stream of analysis as UCI output.
UCI_Chess960
mode.UCI_AnalyseMode
enabled if available.info
with at least:depth
multipv
(between 1 and 5)score
nodes
time
pv
The server may close the connection at any time, indicating that the requester has gone away and analysis should be stopped.
id required | string Example: aingoohiJee2sius |
Analysis results
info multipv 1 depth 20 seldepth 30 time 1373 nodes 1494341 score cp 47 hashfull 594 nps 1088376 tbhits 0 pv d2d4 d7d5 c2c4 e7e6 b1c3 f8b4 c4d5 e6d5 g1f3 g8f6 c1g5 h7h6 g5f6 d8f6 d1b3 c7c5 e2e3 b8c6 d4c5 e8g8 f1d3
Lookup positions from the Lichess opening explorer.
Runs https://github.com/niklasf/lila-openingexplorer.
The endpoint hostname is not lichess.org but explorer.lichess.ovh.
Endpoint: https://explorer.lichess.ovh/masters
Example: curl https://explorer.lichess.ovh/masters?play=d2d4,d7d5,c2c4,c7c6,c4d5
fen | string Example: fen=rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 FEN of the root position |
play | string Default: "" Example: play=e2e4,e7e5,c2c4,c7c6,c4e5 Comma separated sequence of legal moves in UCI notation.
Play additional moves starting from |
since | number Default: 1952 Include only games from this year or later |
until | number Include only games from this year or earlier |
moves | number Default: 12 Number of most common moves to display |
topGames | number <= 15 Default: 15 Number of top games to display |
{- "opening": {
- "eco": "D10",
- "name": "Slav Defense: Exchange Variation"
}, - "white": 1443,
- "draws": 3787,
- "black": 1156,
- "moves": [
- {
- "uci": "c6d5",
- "san": "cxd5",
- "averageRating": 2423,
- "white": 1443,
- "draws": 3787,
- "black": 1155,
- "game": null
}, - {
- "uci": "g8f6",
- "san": "Nf6",
- "averageRating": 2515,
- "white": 0,
- "draws": 0,
- "black": 1,
- "game": {
- "id": "1EErB5jc",
- "winner": "black",
- "white": {
- "name": "Drozdovskij, Yuri",
- "rating": 2509
}, - "black": {
- "name": "Dobrov, Vladimir",
- "rating": 2515
}, - "year": 2006,
- "month": "2006-01"
}
}
], - "topGames": [
- {
- "uci": "c6d5",
- "id": "kN6d9l2i",
- "winner": "black",
- "white": {
- "name": "Carlsen, M.",
- "rating": 2881
}, - "black": {
- "name": "Anand, V.",
- "rating": 2785
}, - "year": 2014,
- "month": "2014-06"
}, - {
- "uci": "c6d5",
- "id": "qeYPJL2y",
- "winner": "white",
- "white": {
- "name": "So, W.",
- "rating": 2778
}, - "black": {
- "name": "Carlsen, M.",
- "rating": 2843
}, - "year": 2018,
- "month": "2018-06"
}
], - "recentGames": [ ],
- "history": [
- {
- "month": "2017-04",
- "black": 413538,
- "draws": 38549,
- "white": 429805
}, - {
- "month": "2017-05",
- "black": 418542,
- "draws": 39171,
- "white": 434066
}
]
}
Endpoint: https://explorer.lichess.ovh/lichess
Games sampled from all Lichess players.
Example: curl https://explorer.lichess.ovh/lichess?variant=standard&speeds=blitz,rapid,classical&ratings=2200,2500&fen=rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR%20w%20KQkq%20-%200%201
variant | string (VariantKey) Default: "standard" Enum: "standard" "chess960" "crazyhouse" "antichess" "atomic" "horde" "kingOfTheHill" "racingKings" "threeCheck" "fromPosition" Example: variant=standard Variant |
fen | string Example: fen=rnbqkbnr/ppp1pppp/8/3pP3/8/8/PPPP1PPP/RNBQKBNR b KQkq - 0 2 FEN or EPD of the root position |
play | string Default: "" Example: play=e2e4,e7e5,c2c4,c7c6,c4e5 Comma separated sequence of legal moves in UCI notation.
Play additional moves starting from |
speeds | Array of strings (Speed) Items Enum: "ultraBullet" "bullet" "blitz" "rapid" "classical" "correspondence" Comma separated list of game speeds to filter by |
ratings | Array of numbers Items Enum: 0 1000 1200 1400 1600 1800 2000 2200 2500 Comma separated list of ratings groups to filter by.
Each group ranges from its value to the next higher
group in the enum ( |
since | string Default: "1952-01" Include only games from this month or later |
until | string Default: "3000-12" Include only games from this month or earlier |
moves | number Default: 12 Number of most common moves to display |
topGames | number <= 4 Default: 4 Number of top games to display |
recentGames | number <= 4 Default: 4 Number of recent games to display |
history | boolean Default: false Optionally retrieve history |
{- "opening": {
- "eco": "D10",
- "name": "Slav Defense: Exchange Variation"
}, - "white": 1443,
- "draws": 3787,
- "black": 1156,
- "moves": [
- {
- "uci": "c6d5",
- "san": "cxd5",
- "averageRating": 2423,
- "white": 1443,
- "draws": 3787,
- "black": 1155,
- "game": null
}, - {
- "uci": "g8f6",
- "san": "Nf6",
- "averageRating": 2515,
- "white": 0,
- "draws": 0,
- "black": 1,
- "game": {
- "id": "1EErB5jc",
- "winner": "black",
- "white": {
- "name": "Drozdovskij, Yuri",
- "rating": 2509
}, - "black": {
- "name": "Dobrov, Vladimir",
- "rating": 2515
}, - "year": 2006,
- "month": "2006-01"
}
}
], - "topGames": [
- {
- "uci": "c6d5",
- "id": "kN6d9l2i",
- "winner": "black",
- "white": {
- "name": "Carlsen, M.",
- "rating": 2881
}, - "black": {
- "name": "Anand, V.",
- "rating": 2785
}, - "year": 2014,
- "month": "2014-06"
}, - {
- "uci": "c6d5",
- "id": "qeYPJL2y",
- "winner": "white",
- "white": {
- "name": "So, W.",
- "rating": 2778
}, - "black": {
- "name": "Carlsen, M.",
- "rating": 2843
}, - "year": 2018,
- "month": "2018-06"
}
], - "recentGames": [ ],
- "history": [
- {
- "month": "2017-04",
- "black": 413538,
- "draws": 38549,
- "white": 429805
}, - {
- "month": "2017-05",
- "black": 418542,
- "draws": 39171,
- "white": 434066
}
]
}
Endpoint: https://explorer.lichess.ovh/player
Games of a Lichess player.
Responds with a stream of newline delimited JSON. Will start indexing on demand, immediately respond with the current results, and stream more updates until indexing is complete. The stream is throttled and deduplicated. Empty lines may be sent to avoid timeouts.
Will index new games at most once per minute, and revisit previously ongoing games at most once every day.
Example: curl https://explorer.lichess.ovh/player?player=revoof&color=white&play=d2d4,d7d5&recentGames=1
player | string Example: player=revoof Username or ID of the player |
variant | string (VariantKey) Default: "standard" Enum: "standard" "chess960" "crazyhouse" "antichess" "atomic" "horde" "kingOfTheHill" "racingKings" "threeCheck" "fromPosition" Example: variant=standard Variant |
fen | string Example: fen=rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 FEN of the root position |
play | string Default: "" Example: play=d2d4,d7d5 Comma separated sequence of legal moves in UCI notation.
Play additional moves starting from |
speeds | Array of strings (Speed) Items Enum: "ultraBullet" "bullet" "blitz" "rapid" "classical" "correspondence" Comma separated list of game speeds to look for |
modes | Array of strings Items Enum: "casual" "rated" Comma separated list of modes |
since | string Default: "1952-01" Include only games from this month or later |
until | string Default: "3000-12" Include only games from this month or earlier |
moves | number Number of most common moves to display |
recentGames | number <= 8 Default: 8 Number of recent games to display |
{- "white": 359,
- "draws": 23,
- "black": 273,
- "moves": [
- {
- "uci": "c2c4",
- "san": "c4",
- "averageOpponentRating": 1695,
- "performance": 1744,
- "white": 354,
- "draws": 23,
- "black": 266,
- "game": null
}, - {
- "uci": "c2c3",
- "san": "c3",
- "averageOpponentRating": 1796,
- "performance": 1796,
- "white": 2,
- "draws": 0,
- "black": 2,
- "game": null
}, - {
- "uci": "e2e4",
- "san": "e4",
- "averageOpponentRating": 1762,
- "performance": 1640,
- "white": 1,
- "draws": 0,
- "black": 2,
- "game": null
}, - {
- "uci": "g1f3",
- "san": "Nf3",
- "averageOpponentRating": 1496,
- "performance": 1374,
- "white": 1,
- "draws": 0,
- "black": 2,
- "game": null
}, - {
- "uci": "h2h3",
- "san": "h3",
- "averageOpponentRating": 1696,
- "performance": 2496,
- "white": 1,
- "draws": 0,
- "black": 0,
- "game": {
- "id": "zyI4GGKv",
- "winner": "white",
- "speed": "bullet",
- "mode": "rated",
- "black": {
- "name": "gocool99",
- "rating": 1696
}, - "white": {
- "name": "revoof",
- "rating": 1702
}, - "year": 2020,
- "month": "2020-07"
}
}, - {
- "uci": "h2h4",
- "san": "h4",
- "averageOpponentRating": 1674,
- "performance": 874,
- "white": 0,
- "draws": 0,
- "black": 1,
- "game": {
- "id": "9vA24xBn",
- "winner": "black",
- "speed": "bullet",
- "mode": "rated",
- "black": {
- "name": "MentalBlood",
- "rating": 1674
}, - "white": {
- "name": "revoof",
- "rating": 1657
}, - "year": 2020,
- "month": "2020-06"
}
}
], - "recentGames": [
- {
- "uci": "c2c4",
- "id": "BGLmUtv7",
- "winner": "white",
- "speed": "bullet",
- "mode": "rated",
- "black": {
- "name": "yigithanyiigit",
- "rating": 1227
}, - "white": {
- "name": "revoof",
- "rating": 1717
}, - "year": 2022,
- "month": "2022-03"
}
], - "opening": {
- "eco": "D00",
- "name": "Queen's Pawn Game"
}, - "queuePosition": 0
}
Lookup positions from the Lichess tablebase server.
The endpoint hostname is not lichess.org but tablebase.lichess.ovh.
Endpoint: https://tablebase.lichess.ovh
Example: curl http://tablebase.lichess.ovh/standard?fen=4k3/6KP/8/8/8/8/7p/8_w_-_-_0_1
fen required | string FEN of the position. Underscores allowed. |
{- "dtz": 1,
- "precise_dtz": 1,
- "dtm": 17,
- "checkmate": false,
- "stalemate": false,
- "variant_win": false,
- "variant_loss": false,
- "insufficient_material": false,
- "category": "win",
- "moves": [
- {
- "uci": "h7h8q",
- "san": "h8=Q+",
- "dtz": -2,
- "precise_dtz": -2,
- "dtm": -16,
- "zeroing": true,
- "checkmate": false,
- "stalemate": false,
- "variant_win": false,
- "variant_loss": false,
- "insufficient_material": false,
- "category": "loss"
}
]
}
Obtaining and revoking OAuth tokens.
Read about the Lichess API authentication methods and code examples.
OAuth2 authorization endpoint.
Start the OAuth2 Authorization Code Flow with PKCE by securely generating two random strings unique to each authorization request:
code_verifier
state
Store these in session storage. Make sure not to reveal code_verifier
to eavesdroppers. Do not show it in URLs, do not abuse state
to store
it, do not send it over insecure connections. However it is fine if
the user themselves can extract code_verifier
, which will always be
possible for fully client-side apps.
Then send the user to this endpoint. They will be prompted to grant
authorization and then be redirected back to the given redirect_uri
.
If the authorization failed, the following query string parameters will be appended to the redirection:
error
, in particular with value access_denied
if the user
cancelled authorizationerror_description
to aid debuggingstate
, exactly as passed in the state
parameterIf the authorization succeeded, the following query string parameters will be appended to the redirection:
code
, containing a fresh short-lived authorization codestate
, exactly as passed in the state
parameterNext, to defend against cross site request forgery, check that the
returned state
matches the state
you originally generated.
Finally, continue by using the authorization code to obtain an access token.
response_type required | string Must be |
client_id required | string Example: client_id=example.com Arbitrary identifier that uniquely identifies your application. |
redirect_uri required | string The absolute URL that the user should be redirected to with the authorization result. |
code_challenge_method required | string Must be |
code_challenge required | string Compute |
scope | string Space separated list of requested OAuth scopes, if any. |
username | string Hint that you want the user to log in with a specific Lichess username. |
state | string Arbitrary state that will be returned verbatim with the authorization result. |
OAuth2 token endpoint. Exchanges an authorization code for an access token.
grant_type | string Must be |
code | string The authorization code that was sent in the |
code_verifier | string A |
redirect_uri | string Must match the |
client_id | string Must match the |
{- "token_type": "Bearer",
- "access_token": "lio_pLwAbN7lFPklzY2m8lTOI1DGApS84u57",
- "expires_in": 31536000
}
For up to 1000 OAuth tokens,
returns their associated user ID and scopes,
or null
if the token is invalid.
The method is POST
so a longer list of tokens can be sent in the request body.
OAuth tokens separated by commas. Up to 1000.
lip_AvsS88TozFeSMEaoLN5c,lip_badToken
{- "lip_AvsS88TozFeSnZa1LN5c": {
- "scopes": "challenge:read,challenge:write",
- "userId": "thibault",
- "expires": 1358509698620
}, - "lip_badToken": null
}