Batch PGN Validator
Drop a PGN file with many games. Get one row per game, the exact move that failed, and a clean file containing only the games that pass.
Games
Runs entirely in your browser. The file is never sent anywhere and is discarded when you close the tab.
How the batch check works
A PGN file is plain text. Each game starts with a block of tag pairs such as [Event "..."] and [White "..."], then a blank line, then the movetext. Games are separated by a blank line before the next tag block. The parser here uses that structure rather than a single regular expression, so a file with mixed line endings, missing blank lines, or no tags at all still splits into games.
For each game the tool builds a board from the starting position or from the FEN tag if one is present. It strips comments in braces, semicolon comments, NAG annotations, and variations. What remains is a token list of moves and a result. Every move is parsed as Standard Algebraic Notation and matched against the legal moves in the current position. A match applies the move. No match is an error. More than one match is an ambiguity.
The legal move generator enforces the rules that matter for import: pins, check evasion, castling through attacked squares, en passant, and promotion. This is the part that catches the errors a text-only checker misses. A file can be syntactically perfect and still contain a move that cannot be played, and that move is what breaks a Lichess study import or a Chessable upload later.
Games with no moves are marked empty rather than valid. Games missing Event, Site, Date, Round, White, Black, or Result are marked as warnings, because the moves may still be legal but many importers reject the file. The result token in the movetext is compared with the Result tag, and a disagreement is reported.
What the report tells you
| Column | Meaning |
|---|---|
| # | Game index in the file, starting at 1. Use it to find the game in a text editor. |
| White / Black | The tag values, or ? when the tag is missing. |
| Result | The movetext result token, not the tag, because the token is what the moves actually lead to. |
| Plies | Half-moves validated. A 40-move game shows 80. |
| Status | Valid, error, empty, or warning. A warning means the moves are legal but a required tag is missing. |
| First error | Move number, side to move, the token that failed, and the reason. |
| Legal alternatives | Coordinate moves that were legal in that position, such as N g1-f3, so you can see what the move probably should have been. |
The summary row counts games, valid games, games with errors, empty games, games with tag warnings, and total plies. That last number is useful for spotting a file that claims to be a database but actually contains mostly empty headers.
Common failures and what they mean
| Report says | Cause | Fix |
|---|---|---|
| Illegal move at 14... Qxe5 | The queen cannot reach e5, or the move leaves the king in check. | Compare with the source. A common cause is a missing capture or a move typed one square off. |
| Ambiguous move at 22. Nd2 | Two knights can reach d2 and the file or rank is missing. | Add the disambiguation, such as Nbd2 or N1d2. |
| Castling through check at 9. O-O | A piece attacks f1 or g1, or the king is in check. | The move is illegal. Check the previous move for a capture that was missed. |
| Promotion missing at 45. e8 | A pawn reached the last rank without =Q or the piece letter. | Write e8=Q or e8Q. |
| Result mismatch | The movetext ends in 1-0 but the Result tag says 0-1. | One of them is wrong. The moves usually show which. |
| Missing tags | Event, Site, Date, Round, White, Black, or Result is absent. | Add the seven tag roster. Lichess and Chessable both require it. |
| Empty game | Tags but no moves. | Remove it, or export the game again from the source database. |
When you would use this
You bought or downloaded an opening repertoire and it will not import into Lichess study. The file has hundreds of lines and the error message does not say which one. Loading it here gives you a per-game row and the exact move that fails.
You are merging several PGN databases and want to know which files are clean before combining them. A batch report takes seconds and tells you whether the problem is one bad game or a broken exporter.
You are preparing a PGN for Chessable. Its importer is sensitive to malformed notation and missing tags. Running the file through a validator first saves a round trip through a failed upload.
You maintain a puzzle collection and need to confirm that every position is legal. The board-based check catches a puzzle that starts from an impossible position or contains a move that cannot be played.
You are writing a script that consumes PGN and want a reference for which errors are common and what they look like. The error CSV gives you labelled examples to test the parser against.
What this does and does not handle
It handles:
- Splitting a file into games by tag structure, with or without blank lines between games.
- Standard Algebraic Notation, including disambiguation, capture, check, mate, and promotion in both
=QandQforms. - Castling written as
O-O,O-O-O,0-0, or0-0-0. - Games that start from a FEN tag, including SetUp.
- Full legality: pins, check, en passant, castling through attacked squares.
- Per-game status, first error, and legal alternatives.
- Valid-only PGN export and an error CSV export.
It does not handle:
- Variations. They are stripped before validation. A legal main line passes even if a branch contains an error.
- Comments as content. They are removed. The validator does not check whether a comment is well formed.
- Engine analysis or move quality. A legal blunder is valid.
- Chess960 or other variants. The board assumes standard chess. A variant tag is reported but the rules are not changed.
- Null moves written as
--orZ0. They are reported as errors rather than skipped. - Files above the browser tab's memory limit. Very large databases may need splitting first.
- Rewriting annotations or preserving comments in the valid-only export. The export keeps headers and main-line moves, not comments.
Questions
How do I validate a PGN file with multiple games?
Paste the file or drop it into the box and click Validate games. The tool splits the file into individual games, plays every move on a real board, and reports each game separately. A file with 500 games produces 500 rows, each marked valid, error, or empty. Nothing is uploaded.
What does the batch validator check?
It checks that each game has parseable tag pairs, that every move in the main line is legal and unambiguous, and that the movetext result agrees with the Result tag. It also flags games with no moves and games missing the seven required tags. It does not run an engine and does not judge move quality.
Why does my PGN pass in one program but fail here?
Programs disagree about how strict to be. Some accept an illegal move and truncate the game, some accept a result token that contradicts the Result tag, and some ignore missing tags. This validator is strict on move legality because an illegal move will break most importers later. The report names the exact move number, the side, and the token that failed, so you can see which rule the other program was ignoring.
What counts as an illegal move?
Any move that cannot be played in the position, such as moving a piece through another piece, leaving your own king in check, castling through an attacked square, or a pawn capture with no piece on the target square. Ambiguous notation, where two pieces of the same type could reach the destination and the file or rank is missing, is reported separately.
Does it validate variations and comments?
It strips comments and variations before validating the main line. Variations are not played out, because a repertoire file with nested branches needs a different data model and a per-branch report. A game whose main line is legal passes even if a variation contains an error. The page says so in the limitations section rather than pretending otherwise.
Can I download only the games that passed?
Yes. The Download valid PGN button writes a new file containing only the games with no errors, with the seven tag roster filled in and the movetext re-flowed to 80 columns. The original file is never modified, and you can keep the error CSV alongside it as a list of what needs fixing.
How do I find which game has the error in a large file?
The results table lists every game in order with its index, White, Black, Result, ply count, status, and the first error. Sort by status or scan the red rows. Each error row shows the move number, the side to move, the exact token that failed, and the legal alternatives in that position.
What are the seven tag roster tags?
Event, Site, Date, Round, White, Black, and Result, in that order. The PGN specification requires them, and Lichess study import and Chessable import both reject files that omit them. Games missing these tags are marked as warnings rather than errors, because the moves may still be valid.
Does it handle PGN files that start from a FEN position?
Yes. If a game has a FEN tag, the board starts from that position instead of the initial array, and the SetUp tag is respected. This covers endgame studies, puzzle collections, and games that begin from a custom position.
Why are some games marked empty?
A game with tags but no moves, or with only a result token and no moves, is marked empty. These appear in databases exported from tools that write a header for a game that was never finished. They are not errors, but they will clutter an import and are worth removing before you load the file anywhere.
Is there a file size limit?
The practical limit is the browser tab's memory. A PGN of tens of megabytes and thousands of games usually validates on a desktop browser. Very large databases of hundreds of megabytes may be slow, because the whole file is read and every game is played out. Splitting the file by date or event first is the workaround.
Is my PGN uploaded to a server?
No. The page reads the file with the browser File API and validates the games with JavaScript. There is no network request during validation or export. You can confirm this by switching the browser to offline mode after the page loads and validating a file.
How is this different from scanchess PGN validator?
The scanchess validator is built around one pasted game. It plays that game out, shows the first problem, and gives you a cleaned single-game PGN. This page is built around a file of many games. It produces a per-game report, summary counts, a filtered valid-only PGN, and an error CSV, which is what you need when you are checking a database rather than one game.
Can I export the error list as a spreadsheet?
Yes. The Download error CSV button writes one row per game with the game index, players, result, ply count, status, and the first error including move number, token, and legal alternatives. It is UTF-8 with a byte order mark, so Excel opens it on a double-click without an import step.