Send a Go position, get back win rate, score lead and the engine's best moves. Runs the KataGo CPU build.
Base URL: https://your-server
curl -X POST https://your-server/v1/analyze \
-H "Authorization: Bearer $KATAGO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"moves": [["B","Q16"],["W","D4"]], "komi": 7.5, "maxVisits": 100}'
import os, requests
resp = requests.post(
"https://your-server/v1/analyze",
headers={"Authorization": f"Bearer {os.environ['KATAGO_API_KEY']}"},
json={"moves": [["B", "Q16"], ["W", "D4"]], "komi": 7.5, "maxVisits": 100},
timeout=130,
)
resp.raise_for_status()
result = resp.json()["results"][0]
print(result["rootInfo"]["winrate"], result["moveInfos"][0]["move"])
const resp = await fetch("https://your-server/v1/analyze", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KATAGO_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ moves: [["B","Q16"],["W","D4"]], komi: 7.5, maxVisits: 100 }),
});
const { results } = await resp.json();
console.log(results[0].rootInfo.winrate, results[0].moveInfos[0].move);
Every call to /v1/analyze needs an API key in the Authorization header:
Authorization: Bearer kg_XXXXXXXXXXXXXXXXXXXXXXXX
Keys are issued by the server operator. Keep yours secret; if it leaks, ask the operator to revoke it and issue a new one.
Requests without a valid key return 401.
POST/v1/analyze
The body is a JSON object describing the game. Only moves is usually needed; everything else has a default.
| Field | Type | Default | Description |
|---|---|---|---|
moves | array | [] | Moves played so far, in order, as ["B"|"W", coord]. Coordinates are GTP style ("D4", columns A–T skipping I) or "pass". |
initialStones | array | [] | Stones on the board before move 1, e.g. handicap: [["B","D4"],["B","Q16"]]. |
initialPlayer | string | — | "B" or "W"; who moves first when moves is empty. |
rules | string | "chinese" | chinese, japanese, korean, aga, tromp-taylor, new-zealand… |
komi | number | 7.5 | Komi, in half-point steps. |
boardXSize, boardYSize | int | 19 | Board size, 2–19. |
maxVisits | int | 200 | Search effort, 1–1000. More visits means stronger but slower (CPU: roughly 50–150 visits/sec). |
analyzeTurns | int[] | final position | Analyze several points in the game at once, e.g. [0, 10, 20] (max 50). One result per turn. |
includeOwnership | bool | false | Add a per-point territory estimate (−1 white … +1 black), row-major from the top-left. |
includePolicy | bool | false | Add the raw neural-net move probabilities. |
avoidMoves / allowMoves | array | — | Restrict the search. Same format as KataGo's analysis engine. |
A successful call returns 200 with one entry in results per analyzed turn:
{
"results": [
{
"turnNumber": 2,
"rootInfo": {
"currentPlayer": "B",
"winrate": 0.374, // for Black, 0–1
"scoreLead": -0.94, // points Black is ahead (negative = White leads)
"visits": 100
},
"moveInfos": [
{ "move": "C3", "winrate": 0.381, "scoreLead": -0.80, "visits": 41, "order": 0,
"pv": ["C3", "D3", "C4"] },
{ "move": "Q4", "winrate": 0.372, "scoreLead": -1.02, "visits": 30, "order": 1, "pv": ["..."] }
]
}
]
}
moveInfos is sorted by order (0 = engine's top choice). pv is the expected continuation.
Win rate and score are from Black's perspective (the default reportAnalysisWinratesAs = BLACK).
| Status | Meaning |
|---|---|
400 | Invalid JSON, unsupported field, or KataGo rejected the position (e.g. illegal move). Body: {"error": "..."} |
401 | Missing or invalid API key. |
413 | Body larger than 64 KB. |
429 | More than 2 requests in flight for your key. Wait for one to finish. |
504 | Analysis took longer than 120 s. Lower maxVisits or analyze fewer turns. |
This server runs on a CPU, so requests are processed a few at a time. Set your HTTP client timeout to at least 130 s.
GET/health
No key needed. Returns {"status": "ok", "maxVisits": 1000} when the engine is running, 503 otherwise.
Your key is only sent to this server and is not stored.