Validate chess algebraic notation
Nbd2+ is correctly written: a knight from the b-file goes to d2 and gives check. Type one move to confirm it follows standard algebraic notation and see the piece, the destination square, any capture, check or promotion. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Notation
- Nbd2+
- Move type
- piece
- Piece
- N
- Destination
- d2
- Origin file
- b
This chess algebraic notation validator checks whether one move follows the syntax of Standard Algebraic Notation, commonly called SAN. It recognizes pawn and piece moves, captures, origin disambiguation, promotion, castling, check, and checkmate markers. The check is deliberately syntactic: it does not need a board position and does not claim that the move is legal in a particular game. Use it to catch malformed move strings before storing, importing, displaying, or processing chess data.
What the validator recognizes
Standard Algebraic Notation compresses a chess move into a small, structured string. A piece move starts with one of the uppercase letters K, Q, R, B, or N, followed by optional origin disambiguation, an optional capture marker, and a destination square such as e4 or h8. Pawn moves omit a piece letter: e4 is a quiet pawn move, while exd5 records a pawn from the e-file capturing on d5.
Promotions append an equals sign and Q, R, B, or N, as in e8=Q or fxg8=N. The validator also accepts O-O and O-O-O for king-side and queen-side castling. A final plus sign marks check, and a final hash marks checkmate.
Letters are case-sensitive because SAN assigns distinct meanings to uppercase piece letters and lowercase board files. The returned object identifies the parsed move category, destination, capture status, check or mate status, and any disambiguation or promotion fields that were present. Optional details are omitted when the notation does not contain them.
Syntax checking is not move legality
This tool answers a focused question: does the string have the shape of one SAN move? It does not receive a board, move history, side to move, castling rights, or en passant state, so it cannot decide whether a piece can actually reach the named square. For example, Nf3 is syntactically valid even if a supplied game position would have no knight capable of moving to f3.
Likewise, a check marker is accepted in the correct final position without proving that the opponent's king is attacked. This separation is useful in import pipelines because syntax errors and chess-rule errors require different feedback. A missing destination rank, lowercase piece letter, misplaced capture marker, invalid file, or unsupported suffix can be rejected immediately without reconstructing a game.
After this validator succeeds, a board-aware chess engine can perform the separate legality test if your workflow needs it. Treat the valid field as confirmation of notation structure only, never as evidence that a recorded game position permits the move.
What you can do with it
Clean an imported move column
Reject malformed SAN strings before they enter a chess database or downstream game parser.
Validate form input
Give immediate, consistent feedback when a player or editor submits one move as text.
Preflight generated chess content
Check the syntax of moves produced by lessons, puzzles, reports, or other deterministic tooling.
FAQ
Does a valid result mean the move is legal?
No. It confirms SAN syntax only. Board legality requires a position, move history, and chess rules engine.
Which piece letters are accepted?
K, Q, R, B, and N are accepted in uppercase. Pawns have no leading letter in SAN.
Are captures, checks, and checkmates supported?
Yes. Use x for a capture, + for check, and # for checkmate in their standard SAN positions.
Does it recognize castling and promotion?
Yes. It accepts O-O, O-O-O, and pawn promotions using =Q, =R, =B, or =N.
Does it trim spaces around a move?
No. Surrounding whitespace is treated as malformed input so data-cleaning problems remain visible.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/game/chess-algebraic-validate \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"notation":"Nbd2+"}'const res = await fetch("https://api.kit.forhosting.com/game/chess-algebraic-validate", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"notation": "Nbd2+"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/game/chess-algebraic-validate",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"notation": "Nbd2+"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/game/chess-algebraic-validate", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"notation":"Nbd2+"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"notation":"Nbd2+"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/game/chess-algebraic-validate", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"notation": "Nbd2+"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "game.chess_algebraic_validate",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
Using the result in applications and data pipelines
Send exactly one notation string in the notation field. Surrounding whitespace is rejected rather than silently removed, which helps reveal dirty data in database columns and line-oriented imports. A successful response preserves the original string and supplies stable fields that software can inspect without parsing SAN again. Piece moves report the SAN piece letter and destination; pawn moves report P as the piece. The move_type distinguishes pawn, piece, and castle forms. Capture is always a Boolean, while origin_file, origin_rank, promotion, and castling side appear only when appropriate. Check and mate are separate Boolean values. A malformed value produces an invalid_input error instead of a result with valid set to false, matching workflows where invalid notation should stop ingestion or trigger field-level feedback. The implementation is deterministic, uses no network calls, and returns the same result in the browser and API. Interactive use is free on the page; automated API validation costs $0.002 per request.
Technical questions
What does API validation cost?
Each API request costs $0.002. The browser version on this page is free.