# Stockfish Chess Engine: Best Move, Game Review, PGN to GIF (`jumblemog/stockfish-chess-engine`) Actor

Stockfish 17.1 as an API: best move, evaluation and top lines for any FEN, Lichess-style game review of PGN (accuracy, centipawn loss, blunders with the better move), and PNG/SVG boards, evaluation graphs, annotated PGN and GIF or MP4 replays. Illegal moves come back with the legal ones.

- **URL**: https://apify.com/jumblemog/stockfish-chess-engine.md
- **Developed by:** [Jumble Mog](https://apify.com/jumblemog) (community)
- **Categories:** Developer tools, AI, For creators
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Stockfish Chess Engine: Best Move, Game Review, PGN to GIF

**Stockfish 17.1 as an API, with game reviews and board images.** Send a chess position as FEN and get the **best move, the evaluation and the top lines**. Send games as PGN and get a **game review**: each side's **accuracy** and **average centipawn loss**, and every **inaccuracy, mistake and blunder with the move Stockfish preferred**, using Lichess's formulas. Positions and games can also be drawn as **PNG or SVG boards** with arrows and an evaluation bar, an **evaluation graph**, an **annotated PGN**, and a **GIF or MP4 replay**, square or vertical for Shorts, Reels and TikTok. A position or move that isn't legal comes back with the exact problem and the legal moves, so a person or an AI agent can fix it. Many positions and games per run, pay per use, and anything that can't be read is free.

![A PGN of Morphy's Opera Game and a FEN going in; the board image with Stockfish's mate-in-2 move, a frame of the vertical replay and the evaluation graph coming out; and the JSON results for the position, the game review and a game with an illegal move](https://api.apify.com/v2/key-value-stores/Km5b4PG3kYHdZSb1E/records/stockfish-chess-engine-example.png?signature=kL6JFSZEVlIe5CXMce7s)

### What it does

- **Analyses positions** with the official Stockfish 17.1: the best move in UCI and SAN notation, the evaluation in centipawns or mate in N (from White's side), White's win chance, the search depth, and up to 5 top lines of 10 moves each. It can also give the move Stockfish chooses when limited to a rating from 1320 to 3190 Elo, for practice opponents and bots.
- **Reviews games** move by move. Each half-move gets the evaluation after it, an accuracy from 0 to 100, and a verdict: book, best, good, inaccuracy, mistake or blunder. Inaccuracies, mistakes and blunders come with the better move and Stockfish's line, and a note when a forced mate was missed or allowed. Each side gets its accuracy, average centipawn loss and the number of inaccuracies, mistakes and blunders. Accuracy, win chances and the verdict thresholds follow the formulas Lichess publishes.
- **Names the opening** from the Lichess opening list (3,865 named positions with ECO codes), found by position, so transpositions count too.
- **Draws boards**: PNG images with coordinates, the last move, check, arrows, highlighted squares and an evaluation bar, and SVG images, in five color themes from 160 to 2048 pixels. Every mistake and blunder also gets an image of the position before it, with the move played in red and the better move in green.
- **Draws an evaluation graph** of each reviewed game, with its inaccuracies, mistakes and blunders marked.
- **Writes an annotated PGN**: an `[%eval]` on every move (as Lichess and ChessBase read them), `?!`, `?` and `??` marks, a comment naming the better move, and Stockfish's line as a variation.
- **Makes replays**: a looping GIF or an MP4 video of the game, move by move, with the players' names, the evaluation bar, a badge on each marked move and an arrow for the better one. Square, or 9:16 vertical with the title and each move written large, up to 1080×1920 for Shorts, Reels and TikTok.
- **Reads what you have**: PGN files with many games, comments, variations, FEN headers and Chess960; plain move lists in SAN (`1. e4 e5 2. Nf3`) or UCI (`e2e4 e7e5 g1f3`); and FEN, X-FEN or Shredder-FEN positions, with moves to play from them.
- **Errors you can act on**: `Move 3 ('Ke3') isn't legal for White in rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2. Legal moves: Ba6, Bb5, Bc4, …`, or `The position isn't legal: There is a pawn on the first or last rank.`
- **Repeatable results**: every search runs on one thread with a fixed node count, so the same position gets the same answer every run.
- **The file straight from the API**: the first file made (the first board image by default) is also the run's `OUTPUT`, so the run-sync endpoint answers with the image itself.

### Who it's for

- **AI agents and chatbots that talk about chess.** Language models can't calculate chess moves reliably. This gives them Stockfish's answer as JSON, with an image to show and a precise error when a move they suggest is illegal.
- **Chess apps, websites and bots** for Discord, Telegram or Twitch that need analysis, reviews or board images without hosting an engine.
- **Content creators** turning famous games or their own into Shorts, Reels and TikToks: vertical MP4 replays, GIFs, and images of the key mistakes.
- **Coaches, clubs and tournament organizers** reviewing a whole event at once from one PGN file.
- **Researchers and dataset builders** labeling positions and games with evaluations, best moves and mistakes.
- **Puzzle makers**: every mistake and blunder comes with the position, the better move and its line.

### How to use it

1. Paste a FEN into **Position (FEN)**, or one or more games into **Game (PGN)**. The example is Morphy's Opera Game of 1858.
2. Pick what to make: engine analysis for positions, a review for games, PNG or SVG images, the evaluation graph, an annotated PGN, and a GIF or MP4 replay. If you like, set the search size, review depth, board colors and animation shape.
3. Click **Start**. Each position and game appears in the **Output** tab with its results and links to its files. The **Moves** view lists every reviewed move with its verdict.

You can also run it through the [Apify API](https://docs.apify.com/api/v2), on a schedule, or from Make, n8n, Zapier and other integrations.

### Input

| Field | What it does |
| --- | --- |
| `fen` | One position in FEN (Chess960 X-FEN and Shredder-FEN work too). |
| `pgn` | One or more games in PGN, or a plain list of moves in SAN or UCI notation. |
| `pgnUrls` | Links to `.pgn` files: direct links, GitHub and GitLab file pages, Google Drive or Dropbox share links. |
| `pgnFiles` | PGN files uploaded in the input form. |
| `outputs` | Any of `analysis`, `review`, `png`, `svg`, `graph`, `pgn`, `gif`, `mp4`. Each applies where it fits. Empty: analysis and a PNG for positions; review, a PNG, the graph and an annotated PGN for games. |
| `positions` | More positions: FEN strings, or objects with `fen`, `moves` (played from the FEN, or from the start), `name`, `arrows` (such as `"g1f3:green"`) and `highlights` (such as `"f7"`). |
| `games` | More games: PGN strings, or objects with `pgn` or `url` and an optional `name`. |
| `analysisNodes` | Search size for each position, 10,000 to 3,000,000 nodes (default 1,000,000, about depth 20). |
| `multiPv` | Top lines per position, 1 to 5 (default 3). |
| `engineElo` | Also return the move Stockfish chooses at this rating, 1320 to 3190. |
| `reviewDepth` | `fast` (100,000 nodes per move), `standard` (300,000, the default) or `deep` (1,000,000). |
| `boardSize` | Board size in images, 160 to 2048 pixels (default 640). |
| `theme` | Board colors: `brown` (default), `green`, `blue`, `gray` or `purple`. |
| `orientation` | `auto` (default: the side to move at the bottom for positions, White for games), `white` or `black`. |
| `coordinates` | Write files and ranks on the board (default on). |
| `showBestMove` | Draw the best move as an arrow, and the better move on mistakes (default on). |
| `evalBar` | Draw the evaluation bar beside analysed positions and reviewed games (default on). |
| `animationLayout` | `square` (default) or `vertical` (9:16). |
| `animationSize` | Width of replays, 240 to 1080 pixels (default 512 square, 720 vertical). |
| `secondsPerMove` | How long each move stays on screen in replays, 0.2 to 5 seconds (default 1). |
| `maxPlies` | Most half-moves reviewed and drawn per game (default 400). |
| `maxGames` | Stop after this many games in total (default 100). |

Example: an AI agent asking for the best move and nothing else:

```json
{
  "fen": "r1bqkbnr/pppp1ppp/2n5/4p3/2B1P3/5N2/PPPP1PPP/RNBQK2R b KQkq - 3 3",
  "outputs": ["analysis"],
  "multiPv": 1
}
```

Example: a whole tournament file, reviewed at fast depth with a graph for each game:

```json
{
  "pgnUrls": ["https://example.com/club-championship.pgn"],
  "outputs": ["review", "graph", "pgn"],
  "reviewDepth": "fast",
  "maxGames": 500
}
```

Example: a vertical MP4 replay of a game for Shorts:

```json
{
  "pgn": "[White \"Adolf Anderssen\"]\n[Black \"Lionel Kieseritzky\"]\n\n1. e4 e5 2. f4 exf4 3. Bc4 Qh4+ ...",
  "outputs": ["review", "mp4"],
  "animationLayout": "vertical",
  "animationSize": 1080,
  "secondsPerMove": 1.5
}
```

### Output

Each position and each game becomes one dataset item, and its files are saved in the run's key-value store. This is the position from the picture, the Opera Game just before Morphy's queen sacrifice:

```json
{
  "index": 1,
  "type": "position",
  "name": "morphy-queen-sacrifice",
  "status": "ok",
  "fen": "4kb1r/p2n1ppp/4q3/4p1B1/4P3/1Q6/PPP2PPP/2KR4 w k - 0 16",
  "sideToMove": "white",
  "legalMoves": 46,
  "gameState": "ongoing",
  "opening": null,
  "evaluation": {"cp": null, "mate": 2, "whiteWinChance": 97.5, "depth": 20, "seldepth": 4, "nodes": 1000070},
  "bestMove": {"uci": "b3b8", "san": "Qb8+"},
  "lines": [
    {"rank": 1, "move": "Qb8+", "cp": null, "mate": 2, "whiteWinChance": 97.5,
     "line": "16. Qb8+ Nxb8 17. Rd8#", "lineUci": ["b3b8", "d7b8", "d1d8"]},
    {"rank": 2, "move": "Qb7", "cp": 338, "mate": null, "whiteWinChance": 77.6,
     "line": "16. Qb7 f6 17. Qc8+ Ke7 18. Be3 g6 19. Qc7 Ke8 20. Kb1 h5", "lineUci": ["b3b7", "f7f6", "..."]},
    {"rank": 3, "move": "Qc3", "cp": 303, "mate": null, "whiteWinChance": 75.3,
     "line": "16. Qc3 f6 17. Qc8+ Ke7 18. Be3 g6 19. Qc7 Ke8 20. Bxa7 Rg8", "lineUci": ["b3c3", "f7f6", "..."]}
  ],
  "eloMove": null,
  "imageUrl": "https://api.apify.com/v2/key-value-stores/<store>/records/001-morphy-queen-sacrifice.png?signature=...",
  "svgUrl": null,
  "error": null,
  "warnings": [],
  "processingSeconds": 2.06
}
```

- `cp` is in centipawns from White's side (100 is about a pawn); `mate` is the number of moves to mate, negative when Black mates. `whiteWinChance` turns either into White's chance from 0 to 100 with Lichess's model.
- `eloMove` is `{"elo", "uci", "san"}` when `engineElo` is set. Stockfish's rating limit picks among good moves at random, so it can differ between runs.

The Opera Game itself, reviewed at standard depth (the `moves` list is cut to two of its 33 entries here):

```json
{
  "index": 2,
  "type": "game",
  "status": "ok",
  "white": "Paul Morphy",
  "black": "Duke Karl / Count Isouard",
  "result": "1-0",
  "event": "Paris Opera",
  "date": "1858.??.??",
  "variant": "standard",
  "opening": {"eco": "C41", "name": "Philidor Defense"},
  "plies": 33,
  "finalFen": "1n1Rkb1r/p4ppp/4q3/4p1B1/4P3/8/PPP2PPP/2K5 b k - 1 17",
  "gameState": "checkmate",
  "summary": {
    "white": {"accuracy": 98.5, "averageCentipawnLoss": 5, "inaccuracies": 0, "mistakes": 0, "blunders": 0},
    "black": {"accuracy": 82.8, "averageCentipawnLoss": 61, "inaccuracies": 3, "mistakes": 1, "blunders": 0}
  },
  "moves": [
    {"ply": 1, "moveNumber": 1, "color": "white", "san": "e4", "uci": "e2e4",
     "fen": "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1",
     "evaluation": {"cp": 39, "mate": null, "whiteWinChance": 53.6}, "classification": "book", "accuracy": 100},
    {"ply": 12, "moveNumber": 6, "color": "black", "san": "Nf6", "uci": "g8f6",
     "fen": "rn1qkb1r/ppp2ppp/5n2/4p3/2B1P3/5Q2/PPP2PPP/RNB1K2R w KQkq - 2 7",
     "evaluation": {"cp": 258, "mate": null, "whiteWinChance": 72.1}, "classification": "mistake", "accuracy": 64,
     "bestMove": {"uci": "d8f6", "san": "Qf6",
                  "line": "6...Qf6 7. Qb3 Nd7 8. Qxb7 Rb8 9. Qa6 Qxa6 10. Bxa6 Nc5 11. Bd3", "lineUci": ["d8f6", "..."]}}
  ],
  "keyMoments": [
    {"ply": 12, "moveNumber": 6, "color": "black", "san": "Nf6", "classification": "mistake",
     "bestMove": {"uci": "d8f6", "san": "Qf6", "line": "6...Qf6 7. Qb3 Nd7 ...", "lineUci": ["d8f6", "..."]},
     "evaluationAfter": {"cp": 258, "mate": null, "whiteWinChance": 72.1}, "note": null,
     "imageUrl": "https://api.apify.com/v2/key-value-stores/<store>/records/002-Paul-Morphy-vs-Duke-Karl-Count-Isouard-move-012.png?signature=..."}
  ],
  "imageUrl": "https://api.apify.com/v2/key-value-stores/<store>/records/002-Paul-Morphy-vs-Duke-Karl-Count-Isouard-final.png?signature=...",
  "graphUrl": "https://api.apify.com/v2/key-value-stores/<store>/records/002-Paul-Morphy-vs-Duke-Karl-Count-Isouard-graph.png?signature=...",
  "gifUrl": "https://api.apify.com/v2/key-value-stores/<store>/records/002-Paul-Morphy-vs-Duke-Karl-Count-Isouard.gif?signature=...",
  "mp4Url": null,
  "pgnUrl": "https://api.apify.com/v2/key-value-stores/<store>/records/002-Paul-Morphy-vs-Duke-Karl-Count-Isouard.pgn?signature=...",
  "error": null,
  "warnings": [],
  "processingSeconds": 9.05
}
```

- `classification` is `book` while the game follows a named opening, `best` when the move is Stockfish's choice, and otherwise `good`, `inaccuracy`, `mistake` or `blunder` by how much the move lowered the mover's winning chances (0.1, 0.2 and 0.3 on Lichess's scale from −1 to 1).
- `keyMoments` lists up to 12 mistakes and blunders with an image of each.
- Game items also carry `whiteElo`, `blackElo`, `site`, `round`, `startFen` (for games that don't start from the usual position), `svgUrl` and `sourceUrl`.

When a game has a move that isn't legal, the item says where and what was possible, and isn't billed:

```json
{
  "index": 3,
  "type": "game",
  "name": "typo",
  "status": "failed",
  "error": "The game can't be read past move 4 for White: Qxf7 isn't a legal move. The 6 half-moves before it are fine. The position there is r1bq1bnr/ppppkppp/2n5/1B2p3/4P3/5N2/PPPP1PPP/RNBQK2R w KQ - 4 4, where the legal moves are Ba4, Ba6, Bc4, Bd3, Be2, Bf1, Bxc6, Ke2, Kf1, Na3, Nc3, Nd4, Ng1, Ng5, Nh4, Nxe5, O-O, Qe2, Rf1, Rg1, a3, a4, b3, b4, c3, c4, d3, d4, g3, g4, h3, h4."
}
```

Download your files within your plan's data retention period, or copy them to your own storage, because run storage expires.

### Pricing

You pay per use, at the prices shown on this page:

- **Position**: each position analysed or drawn.
- **Game**: each game read and drawn (board image, graph, annotated PGN), whatever files you pick.
- **Half-move reviewed**: each half-move Stockfish reviews, on top of the game. Fast depth counts each half-move once, standard 3 times and deep 10 times, because deeper reviews search more. A 40-move game (80 half-moves) at the standard depth counts 240.
- **Half-move animated**: each half-move drawn into a GIF or MP4 replay, on top of the game; a GIF and an MP4 of the same game count twice.

Positions and games that can't be read are never charged. If you set a maximum cost per run, the Actor stops before a position or game that wouldn't fit.

### Speed

Measured on Apify with the default 4 GB of memory:

- One position at the default 1,000,000 nodes with 3 lines: 2.0 seconds, including starting the engine.
- 8 positions in one run: 1.3 to 2.1 seconds each, analysed four at a time; 11 seconds for the whole run.
- The Opera Game (33 half-moves) reviewed at standard depth, with its board image, an image of its mistake, the graph, the annotated PGN and a GIF replay: 8.3 seconds.
- Kasparov vs Topalov, Wijk aan Zee 1999 (87 half-moves), reviewed at standard depth: 38 seconds. Reviewed at fast depth with a 1080×1920 GIF and MP4 replay: 26 seconds.

A run uses one copy of Stockfish per GB of memory, up to 8, side by side. Runs with more memory get more CPU, so long games and big batches finish sooner, and starting a run adds a few seconds, so send many positions or games in one run when you can.

### Tips and limits

- **Variants**: standard chess and Chess960. Other variants (crazyhouse, atomic, and so on) aren't supported.
- **Lichess and Chess.com links aren't downloaded**, because their robots.txt asks automated tools to stay off game pages and exports. Copy the PGN from the game's share or export menu into `pgn`, or upload the file.
- **Accuracy** uses Lichess's formula, from the win chances before and after each move. A move that matches Stockfish's choice always counts as 100% accurate, so a short search that sees further on the next move doesn't mark the engine's own move down.
- **Review depth**: standard is enough to find the mistakes in most games. Use deep for close endgames and sharp tactics; fast for large batches.
- **Opening names and book moves** come from the Lichess opening list. A move counts as `book` while the position is in the list.
- PGN files can be up to 50 MB. Games longer than `maxPlies` half-moves are reviewed and drawn up to that point, with a warning.

### For AI agents and developers

This Actor works with the [Apify MCP server](https://mcp.apify.com), so AI agents can call it as a tool: pass a position in `fen` (with `"outputs": ["analysis"]` for JSON only), or games in `pgn`, and read `bestMove`, `evaluation` and `lines`, or `summary` and `moves`, from the dataset item. If `status` is `failed`, `error` says what to fix and lists the legal moves. For a direct API call that waits for the result:

```bash
curl -X POST "https://api.apify.com/v2/acts/jumblemog~stockfish-chess-engine/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"fen": "r1bqkbnr/pppp1ppp/2n5/4p3/2B1P3/5N2/PPPP1PPP/RNBQK2R b KQkq - 3 3", "outputs": ["analysis"]}'
```

To get the board image itself as the response, call `run-sync` instead. It returns the run's `OUTPUT`, the first file made (or the first result as JSON when no file was asked for):

```bash
curl -X POST "https://api.apify.com/v2/acts/jumblemog~stockfish-chess-engine/run-sync?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"fen": "4kb1r/p2n1ppp/4q3/4p1B1/4P3/1Q6/PPP2PPP/2KR4 w k - 0 16", "outputs": ["analysis", "png"]}' \
  -o position.png
```

### Credits

Positions are analysed by [Stockfish](https://stockfishchess.org) 17.1 (GPL-3.0), the official release, run unmodified as a separate program; its source code is at [github.com/official-stockfish/Stockfish](https://github.com/official-stockfish/Stockfish). This Actor isn't made by or affiliated with the Stockfish project. Chess rules, PGN and SVG boards come from [python-chess](https://github.com/niklasf/python-chess) (GPL-3.0), the pieces are Colin M.L. Burnett's set (GPL, BSD and GFDL), opening names are from the [Lichess opening list](https://github.com/lichess-org/chess-openings) (CC0), and images and replays are made with [Pillow](https://python-pillow.org) (MIT-CMU), [librsvg](https://gitlab.gnome.org/GNOME/librsvg) (LGPL-2.1), [FFmpeg](https://ffmpeg.org) (GPL) and the DejaVu fonts. The accuracy and win-chance formulas are the ones [Lichess](https://lichess.org) publishes.

# Actor input Schema

## `fen` (type: `string`):

A chess position in FEN, such as r1bqkbnr/pppp1ppp/2n5/4p3/2B1P3/5N2/PPPP1PPP/RNBQK2R b KQkq - 3 3. Stockfish 17.1 finds the best move, the evaluation (centipawns or mate in N, and White's win chance) and the top lines, and the position is drawn as a PNG board. Chess960 positions (X-FEN or Shredder-FEN) work too. A position that can't happen comes back with the reason, such as a pawn on the back rank.

## `pgn` (type: `string`):

One or more games in PGN, as exported by any chess site or program, or just the moves: 1. e4 e5 2. Nf3 Nc6, or in UCI notation e2e4 e7e5 g1f3. Each game is reviewed move by move as on Lichess: each side's accuracy and average centipawn loss, and every inaccuracy, mistake and blunder with the move Stockfish preferred. A move that isn't legal comes back with its move number and the legal moves at that point.

## `pgnUrls` (type: `array`):

Links to .pgn files, such as tournament downloads, GitHub file pages, or Google Drive and Dropbox share links. A file can hold many games (see maxGames). Links to Lichess and Chess.com aren't downloaded, because their robots.txt asks automated tools not to; copy the PGN from the game's share menu into Game (PGN) instead.

## `pgnFiles` (type: `array`):

Upload .pgn files from your computer, or pick files you already stored in an Apify key-value store.

## `outputs` (type: `array`):

Each output applies where it fits: analysis to positions, review, graph, pgn, gif and mp4 to games, and images to both. Empty: analysis and a PNG for positions; review, a PNG, the graph and an annotated PGN for games. Without analysis or review, positions and games are only drawn and nothing is analysed.

## `positions` (type: `array`):

Many positions at once. Each entry is a FEN string, or an object: {"fen": "...", "moves": "e4 e5 Nf3", "name": "after 3 moves", "arrows": \["g1f3:green", "d8h4:red"], "highlights": \["f7"]}. moves (SAN or UCI, as text or a list) are played from the fen, or from the starting position when fen is left out. Arrows are from-to squares with an optional color (green, red, blue or yellow).

## `games` (type: `array`):

Many games at once. Each entry is PGN text, or an object: {"pgn": "1. e4 e5 ...", "name": "club-round-3"} or {"url": "https://example.com/games.pgn", "name": "club"}.

## `analysisNodes` (type: `integer`):

How many positions Stockfish searches for each position you send. The default 1,000,000 takes about 1.5 seconds and reaches about depth 20 (deeper in endgames), far beyond any human player; 3,000,000 searches about three levels deeper; 100,000 takes a tenth of a second. Each search runs on one thread with a fixed node count, so the same position gets the same answer every run.

## `multiPv` (type: `integer`):

How many of the best moves to return for each position, each with its evaluation and the line that follows.

## `engineElo` (type: `integer`):

Also return the move Stockfish chooses when limited to this rating (UCI_Elo, 1320 to 3190), for practice opponents, bots and puzzles. Leave empty for full strength only.

## `reviewDepth` (type: `string`):

How hard Stockfish looks at each move of a game. Standard matches a typical online game review; deep is for close games and long endgames.

## `boardSize` (type: `integer`):

Width and height of the board in PNG and SVG images; the evaluation bar adds a narrow strip on the left.

## `theme` (type: `string`):

The colors of the light and dark squares.

## `orientation` (type: `string`):

Which side is at the bottom of the board. With auto, images of mistakes and blunders show the board from the side that moved.

## `coordinates` (type: `boolean`):

Write files a to h and ranks 1 to 8 along the board's edges.

## `showBestMove` (type: `boolean`):

Draw Stockfish's move as a green arrow on analysed positions, and the better move on mistakes in game images and animations.

## `evalBar` (type: `boolean`):

Draw a bar beside the board that fills with White's win chance, with the score, on analysed positions and reviewed games.

## `animationLayout` (type: `string`):

The shape of the GIF and MP4 game replays.

## `animationSize` (type: `integer`):

Width of the GIF and MP4 replays. Empty: 512 for square and 720 for vertical. Use 1080 for full-HD vertical video.

## `secondsPerMove` (type: `number`):

How long each move stays on screen in the replays. The final position is held three times as long.

## `maxPlies` (type: `integer`):

Only this many half-moves of each game are reviewed and drawn (400 half-moves is a 200-move game); the result says when a game was cut short.

## `maxGames` (type: `integer`):

Stop after this many games in total, across every PGN text, file and link. Useful with files that hold thousands of games.

## Actor input object example

```json
{
  "pgn": "[Event \"Paris Opera\"]\n[Site \"Paris FRA\"]\n[Date \"1858.??.??\"]\n[White \"Paul Morphy\"]\n[Black \"Duke Karl / Count Isouard\"]\n[Result \"1-0\"]\n\n1. e4 e5 2. Nf3 d6 3. d4 Bg4 4. dxe5 Bxf3 5. Qxf3 dxe5 6. Bc4 Nf6 7. Qb3 Qe7 8. Nc3 c6 9. Bg5 b5 10. Nxb5 cxb5 11. Bxb5+ Nbd7 12. O-O-O Rd8 13. Rxd7 Rxd7 14. Rd1 Qe6 15. Bxd7+ Nxd7 16. Qb8+ Nxb8 17. Rd8# 1-0\n",
  "outputs": [
    "analysis",
    "review",
    "png",
    "graph",
    "pgn",
    "gif"
  ],
  "positions": [
    "6k1/5ppp/8/8/8/8/5PPP/R5K1 w - - 0 1",
    {
      "moves": "e4 e5 Qh5 Nc6 Bc4 Nf6",
      "name": "scholar-mate-threat",
      "arrows": [
        "h5f7:red"
      ]
    }
  ],
  "games": [
    "1. d4 d5 2. c4 e6 3. Nc3 Nf6",
    {
      "pgn": "1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6",
      "name": "najdorf"
    }
  ],
  "analysisNodes": 1000000,
  "multiPv": 3,
  "reviewDepth": "standard",
  "boardSize": 640,
  "theme": "brown",
  "orientation": "auto",
  "coordinates": true,
  "showBestMove": true,
  "evalBar": true,
  "animationLayout": "square",
  "secondsPerMove": 1,
  "maxPlies": 400,
  "maxGames": 100
}
```

# Actor output Schema

## `results` (type: `string`):

One item per position or game: best move, evaluation and lines, or the game review with accuracy and blunders, and links to the files.

## `moves` (type: `string`):

One row per half-move of every reviewed game, with its verdict, accuracy, evaluation and the better move.

## `files` (type: `string`):

The board images, graphs, annotated PGN files and replays saved in the run's key-value store.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "pgn": `[Event "Paris Opera"]
[Site "Paris FRA"]
[Date "1858.??.??"]
[White "Paul Morphy"]
[Black "Duke Karl / Count Isouard"]
[Result "1-0"]

1. e4 e5 2. Nf3 d6 3. d4 Bg4 4. dxe5 Bxf3 5. Qxf3 dxe5 6. Bc4 Nf6 7. Qb3 Qe7 8. Nc3 c6 9. Bg5 b5 10. Nxb5 cxb5 11. Bxb5+ Nbd7 12. O-O-O Rd8 13. Rxd7 Rxd7 14. Rd1 Qe6 15. Bxd7+ Nxd7 16. Qb8+ Nxb8 17. Rd8# 1-0`,
    "outputs": [
        "analysis",
        "review",
        "png",
        "graph",
        "pgn",
        "gif"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("jumblemog/stockfish-chess-engine").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "pgn": """[Event \"Paris Opera\"]
[Site \"Paris FRA\"]
[Date \"1858.??.??\"]
[White \"Paul Morphy\"]
[Black \"Duke Karl / Count Isouard\"]
[Result \"1-0\"]

1. e4 e5 2. Nf3 d6 3. d4 Bg4 4. dxe5 Bxf3 5. Qxf3 dxe5 6. Bc4 Nf6 7. Qb3 Qe7 8. Nc3 c6 9. Bg5 b5 10. Nxb5 cxb5 11. Bxb5+ Nbd7 12. O-O-O Rd8 13. Rxd7 Rxd7 14. Rd1 Qe6 15. Bxd7+ Nxd7 16. Qb8+ Nxb8 17. Rd8# 1-0
""",
    "outputs": [
        "analysis",
        "review",
        "png",
        "graph",
        "pgn",
        "gif",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("jumblemog/stockfish-chess-engine").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "pgn": "[Event \\"Paris Opera\\"]\\n[Site \\"Paris FRA\\"]\\n[Date \\"1858.??.??\\"]\\n[White \\"Paul Morphy\\"]\\n[Black \\"Duke Karl / Count Isouard\\"]\\n[Result \\"1-0\\"]\\n\\n1. e4 e5 2. Nf3 d6 3. d4 Bg4 4. dxe5 Bxf3 5. Qxf3 dxe5 6. Bc4 Nf6 7. Qb3 Qe7 8. Nc3 c6 9. Bg5 b5 10. Nxb5 cxb5 11. Bxb5+ Nbd7 12. O-O-O Rd8 13. Rxd7 Rxd7 14. Rd1 Qe6 15. Bxd7+ Nxd7 16. Qb8+ Nxb8 17. Rd8# 1-0\\n",
  "outputs": [
    "analysis",
    "review",
    "png",
    "graph",
    "pgn",
    "gif"
  ]
}' |
apify call jumblemog/stockfish-chess-engine --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jumblemog/stockfish-chess-engine"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/OUzUR4bhSrSgbEWm8/builds/tO5UeckSsHHLuzeK2/openapi.json
