Skip to main content

PGN Parser is for parsing .pgn chess files

Project description

PGN Parser

A Python library for parsing pgn files into a python friendly format.

The parser is built using canopy, the rest is Python.

The PGN spec is based on (and thanks to) the spec at



Make sure you have python 3 installed.

pip install pgn_parser

Then import like so:

from pgn_parser import pgn, parser


The tests are written using pytest and behave, these must be installed first:

pip install pytest behave

For running unit tests:


For running behavioural tests:


Building pip distributables

make build


Parsing a pgn file

To parse a pgn, you just give the string to the parser.parse along with the Actions() which the parser uses to create python structures.

>>> from pgn_parser import parser, pgn

>>> game = parser.parse("1. e4 e5", actions=pgn.Actions())
>>> print(game.move(1))
1. e4 e5
>>> print(game.move(1).black.san)


After parsing a game, it will be structured into the following classes which are nested in eachother:

Game: Container for the whole game To get a specific move (5 here) from a game


To retrieve the Movetext


To access the TagPairs


To access the final score


Movetext: The container of all the moves, e.g "1. c4 c5 2. e4 e5" It is just a list so can be iterated over to retrieve the moves. Be warned, Movetext[0] will be the first move parsed, whether 1. or 31. so use Game.move() if you want a movenumber

Move: A move is a move number, optionally a white Ply and or a black Ply

Ply: Is the unit of moving, in standard algebraic notation (SAN), e.g. the black ply from "1.e4 e5" is e5

TagPairs: An ordered dictionary of all TagPair objects. These are ordered so it keeps the order read in, but will change to seven tag roster order if printed/stringified.


To store meta data about a game you do so in TagPairs

The header of a pgn file

["Site" ""]

Is represented like so in python

game.tag_pairs["Site"] == ""


Each move has a move number and two ply's, white and black. Each ply can be anything from empty to having comments, variations and nags.

moves = "1. e4 $1 {a comment} (1.d5)"

Is represented like so:

m1 = game.move(1)

assert m1.white.san == "e4"
assert m1.white.comment == "a comment"
assert m1.white.nags[0] == "$1"
assert m1.white.variations[0].move(1).white.san == "d5"

If a ply is empty, then its san will be represented "".


No support for RAV style variations No support for multiple games in one parse, must be single games Doesn't attempt to parse turn times as this is not in the original spec and I am not sure what to support.


  • Brett Bates - Initial work - github


This project is licensed under the MIT License - see the file for details

Project details

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pgn-parser-1.1.0.tar.gz (12.5 kB view hashes)

Uploaded source

Built Distribution

pgn_parser-1.1.0-py3-none-any.whl (12.2 kB view hashes)

Uploaded py3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page