I'll stream position analysis to You

without exhausting your CPU.

Up to 80 MNPS Stockfish Logo Stockfish 17 NNUE calculation power @32 vCores / 128 GB DDR5


Request:

POST https://chess-api.com/v1

WEBSOCKET wss://chess-api.com/v1

// Post FEN position:
{
    fen: '8/1P1R4/n1r2B2/3Pp3/1k4P1/6K1/Bppr1P2/2q5 w - - 0 1',
}

// ... or text input with the list of moves:
{
    input: '<div ...',
}

// You can also provide custom options:
{
    fen: '8/1P1R4/n1r2B2/3Pp3/1k4P1/6K1/Bppr1P2/2q5 w - - 0 1',
    variants: 1, // max: 5, default: 1,
    depth: 12, // max: 18, default: 12,
    maxThinkingTime: 50, // max: 100, default: 50 (ms),
    searchmoves: '', // evaluate specific moves only, ex. 'd2d4 e2e4',
}
                    

âť—Greater depth and more thinking time is available for project supporters.

Response:

{
    text: "Move b7 → b8 (b8=Q+): [-11.62]. Black is winning. Depth 12.",
    eval: -11.62,
    move: "b7b8q",
    fen: "8/1P1R4/n1r2B2/3Pp3/1k4P1/6K1/Bppr1P2/2q5 w - - 0 1",
    depth: 12,
    winChance: 1.3672836783305158,
    continuationArr: (5) ['a6c5', 'b7b8q', 'c6b6', 'b8b6', 'b4a3'],
    mate: null,
    centipawns: "-1162",
    
    san: "b8=Q+",
    lan: "b7b8q",
    turn: "w",
    color: "w",
    piece: "p",
    flags: "np",
    isCapture: false,
    isCastling: false,
    isPromotion: true,
    
    from: "b7",
    to: "b8",
    fromNumeric: "27",
    toNumeric: "28",

    taskId: "0k1pkg83g",
    time: 10677,
    type: "move"
},
...
                    

Easy as 🦆:



You can try following scripts directly in your browser's console.


POST request

Performing a POST request is a simple way to receive the evaluation. However, it is less reactive than WS since server needs to "get" to the requested depth until it sends back the response.


// 1. Create a handy function for sending requests:
async function postChessApi(data = {}) {
    const response = await fetch("https://chess-api.com/v1", {
        method: "POST",
        headers: {
            "Content-Type": "application/json"
        },
        body: JSON.stringify(data),
    });
    return response.json();
}

// 2. Execute:
postChessApi({ fen: "8/1P1R4/n1r2B2/3Pp3/1k4P1/6K1/Bppr1P2/2q5 w - - 0 1" }).then((data) => {
    console.log(data);
});

// 3. You can provide text/html input to parse:
postChessApi({ input: document.querySelector('.moves-list').outerHTML }).then((data) => {
    console.log(data);
});
				

WebSockets

WebSocket connetion allows you to receive moves in progressive manner.


// 1. Open WebSocket connection:
ws = new WebSocket('wss://chess-api.com/v1');

// 2. Register callback to Log every incomming message in the console:
ws.onmessage = (event) => {
    const chessApiMessage = JSON.parse(event.data);
    console.log(chessApiMessage);
};

// 3. After connection is estabilished, send me a message:
ws.send(JSON.stringify({ 
    fen: '8/1P1R4/n1r2B2/3Pp3/1k4P1/6K1/Bppr1P2/2q5 w - - 0 1',
    variants: 3
}));

// 4. You can also ask me to figure out position myself by sending text or HTML with moves list. My parsers will try to do their best.
ws.send(JSON.stringify({ 
    input: `<div ...`,
    variants: 3
}));




Response fields:


.type

Response types can be categorized as "move," "bestmove," or "info." Messages of type "move" are delivered progressively, indicating that the engine has identified a promising move at a given depth. The final message, denoted as "bestmove," represents the optimal move proposed among those identified. Additionally, "info" messages may include supplementary details such as status updates or error notifications.

type: 'bestmove'

.eval

Position evaluation. Negative value means that black is winning.

eval: -14.54

.depth

The depth at which the move was discovered is significant, as higher depths typically correlate with greater accuracy. For context, a depth of 12 corresponds to approximately 2350 FIDE elo, akin to the level of International Masters like Eric Rosen or Levy Rozman. A depth of 18 equates to around 2750 FIDE elo, reflective of the skill level of Grandmaster Hikaru Nakamura. Furthermore, a depth of 20 corresponds to approximately 2850 FIDE elo, indicative of the caliber of Grandmaster Magnus Carlsen.

depth: 12

.text

Textual description of data.

text: 'Move b7 → b8 (b8=Q+): [-10.97]. Black is winning.'

.winChance

Winning chance: value 50 (50%) means that position is equal. Over 50 - white is winning. Below 50 - black is winning. This is calculated using Lichess formula (Win% = 50 + 50 * (2 / (1 + exp(-0.00368208 * centipawns)) - 1)). Values are similar to what evaluation bar shows on most of chess websites.

winChance: 52.3321234425677

.mate

Forced mate sequence detected (number shows how many moves have to be played to mate opponent's king). Negative numbers concern black pieces.

mate: -12

.san

Short algebraic notation of move.

san: 'b8=R+'

.continuationArr

Array of next moves to be played in suggested variant.

["a6b8","d7b7","b4c5","d5c6"]

.from / .to / .fromNumeric / .toNumeric

Move coordinations on the board. Might be handy to easily highlight moves on the board, draw arrows etc.

from: "b7", to: "b8", fromNumeric: "27", toNumeric: "28"

.captured

Information about captured piece (if any). Letters stands for piece name (r - rook, n - knight, q - queen an so on)

captured: 'r'

.turn

Current player's turn. Values: 'w' or 'b'.

turn: 'w'

.piece

Piece type (r - rook, n - knight, q - queen an so on)

piece: 'p'

.taskId

Task (calculation) identifier. This can be set by attaching "taskId" field in your message. May be used to pair responses with request. Generate with random function like Math.rand().

taskId: '18lplzhja'

.promotion

If move is promotion, piece symbol will be here (r / n / b / q)

promotion: 'q'

.isCastling

True or false - whether move is castling.

castling: true

.isCapture

Whether move is capture. True or false.

capture: true

.flags

Contains one or more of the string values: n - a non-capture / b - a pawn push of two squares / e - an en passant capture / c - a standard capture / p - a promotion / k - kingside castling / q - queenside castling.

flags: k

About the project

Chess-API gives an easy remote access to the calculation power of Stockfish 17 Chess Engine.

It was made to help people creating cool chess learning tools, browser extensions and more.

You can easily integrate it with your front-end JavaScript using Fetch API or WebSockets.


Created by ChrisC (feel free to contact me @twitter).

Chess API wouldn't be done without those wonderful libraries:

https://github.com/official-stockfish/Stockfish

https://github.com/jhlywa/chess.js/