Is there a convenient way to search for players by their opening? For example if I input 'Ruy Lopez' then it gives me a list of chess players, sorted by how many times they played Ruy Lopez in tournament.

I know that chess.com and 365chess has this feature, but they only provide 3 to 5 players per opening.


3 Answers 3


I had created a python package called pgnhelper with documentation which can be used to see what you would like to find.

Do not use a big pgn file as it will take more time. This is more useful for examining stats of a tournament. 5 or so tournament pgn files can be combined. Player names should be consistent.

Typical setup for windows 10

  1. Intall python 3.7 or later from https://www.python.org/downloads/

  2. Install pgnhelper from command line.

pip install pgnhelper -U
  1. Save the code below to ruylopez.py.

3.1 Download candidates games from https://theweekinchess.com/assets/files/pgn/wchcand22.pgn

3.2. Place the pgn file and ruylopez.py in the same directory.

  1. Execute ruylopez.py from command line like an example below.
PS F:\pgnhelpter_test> python ruylopez.py

The ruylopez.py and wchcand22.pgn are in F:\pgnhelpter_test path where pgnhelpter_test is the folder or directory name.



"""Show player names and number of games on the given opening name.

  pip install pgnhelper -U

import pgnhelper
import pandas as pd

# opening_name = 'Nimzo-Indian'
opening_name = 'Ruy Lopez'

pgnfn = 'wchcand22.pgn'
# https://theweekinchess.com/assets/files/pgn/wchcand22.pgn

df, players, israting = pgnhelper.record.get_pgn_data(pgnfn)

# print(df)
# df.to_csv("sample.csv", index=False)

openings = df.Opening.unique()
for o in openings:

data = {}
for p in players:
    data1 = {}
    for o in openings:
        dfw = df.loc[(df.Opening == o) & (df.White == p)]
        dfb = df.loc[(df.Opening == o) & (df.Black == p)]
        wcnt = len(dfw)
        bcnt = len(dfb)
        total = wcnt + bcnt
        data1.update({o: {'w': wcnt, 'b': bcnt, 'total': total}})

    data.update({p: {'data': data1}})

mydata = []
for p in players:
    mydata.append([opening_name, p,

mydf = pd.DataFrame(
    columns=['Opening', 'Player', 'Wgames', 'Bgames', 'Total'])

mydf = mydf.sort_values(by=['Total', 'Wgames'], ascending=[False, False])

mydf.to_csv("ruylopez.csv", index=False)  # Save to csv file


Sicilian defence
English opening
Ruy Lopez
Sicilian, Chekhover variation
Giuoco Pianissimo
Catalan opening
Four knights game
Four knights
Giuoco Piano
QGD semi-Slav
     Opening               Player  Wgames  Bgames  Total
2  Ruy Lopez     Nakamura, Hikaru       2       4      6
7  Ruy Lopez     Rapport, Richard       4       1      5
0  Ruy Lopez     Caruana, Fabiano       3       2      5
1  Ruy Lopez    Radjabov, Teimour       1       3      4
3  Ruy Lopez    Firouzja, Alireza       1       1      2
6  Ruy Lopez          Ding, Liren       0       2      2
4  Ruy Lopez  Nepomniachtchi, Ian       1       0      1
5  Ruy Lopez  Duda, Jan-Krzysztof       1       0      1

The code can be revised to show a column of score percentage. Can also be revised to show by ECO code.

Opening names in the game are printed in console due to:

openings = df.Opening.unique()
for o in openings:

Results are printed in console due to:


csv file will be saved due to:

mydf.to_csv("ruylopez.csv", index=False) # Save to csv file

You can change the opening name in the code by changing below code:

opening_name = 'Ruy Lopez'

You can use different pgn file but be sure the game has Opening tag like below.

[Event "FIDE Candidates 2022"]
[Site "Madrid ESP"]
[Date "2022.06.17"]
[Round "1.3"]
[White "Caruana, Fabiano"]
[Black "Nakamura, Hikaru"]
[Result "1-0"]
[WhiteTitle "GM"]
[BlackTitle "GM"]
[WhiteElo "2783"]
[BlackElo "2760"]
[ECO "C65"]
[Opening "Ruy Lopez"]
[Variation "Berlin defence"]
[WhiteFideId "2020009"]
[BlackFideId "2016192"]
[EventDate "2022.06.17"]

1. e4 e5 2. Nf3 Nc6 ...

There must be Opening tag.

[Opening "Ruy Lopez"]

Add eco

If the game in your pgn file has no Opening tag, you can use pgnhelper to add a tag.

Example from command line:

pgnhelper addeco --inpgnfn candidates_zurich_1953.pgn --outpgnfn eco_candidates_zurich_1953.pgn --inecopgnfn eco.pgn

See also the guide at https://pgnhelper.readthedocs.io/en/latest/usage.html.

The file eco.pgn is needed, you can download it from github.

For example you can download pgn files from weekinchess, or from pgnmentor.

  • This is excellent. Great job breaking it down into accessible steps. (+1) Commented Aug 7, 2022 at 17:17
  • Have you tried running with pypy? If most of your computation is pure python it could speed things up. But if it's pandas than you won't get any benefit.
    – qwr
    Commented Aug 8, 2022 at 18:23
  • I have not yet tried it with pypy. Will try it and compare the speed at some point when I have time.
    – ferdy
    Commented Aug 8, 2022 at 23:40

I'm not sure any of these solutions below provide exactly what you're looking for, but I think enough functionality is there to assist you in your goal. Though the second option is very similar to the Chess365 functionality you reference.

Option 1: ChessGames.com General Search
ChessGames.com allows searches by ECO code or opening. For example, here are the results for games in the Scotch (ECOs C45–45) restricted to the year 2021. You can further restrict games by result (White wins, Black wins, draw, or "no draw"). You can parse the results easily enough.

Option 2: ChessGames.com Opening Explorer
ChessGames.com also has an opening explorer that will list around 6 practitioners of that opening ECO code (3 with the White pieces, and 3 with Black). For example, searching ECO code 65 (Berlin Defense is 65–67) gives the following.

Results from search

Option 3: ChessTempo.com Opening Explorer
ChessTempo.com has an opening explorer with some added filters including specifying a rating range. Again, you'd have to parse the results, but it seems relevant.

For example, I asked for all games with position after 1. e4 c5 2. Nc3 Nc6 3. f4 (Grand Prix Attack) with both players rated 2700+. It returns the following.

Search results from ChessTempo

  • Basically what I want is like your option 2, but with a longer list of players Commented Jul 18, 2022 at 6:22

You could use pgn-extract -e3 pgn-file-name to split the pgn file by ECO codes of games, e.g., you will get files C60.pgn to C99.pgn for Ruy Lopez. You can then combine C60.pgn to C99.pgn to get a single Ruy Lopez file. You may also be able to export from scid vs pc games in a range of ECO codes. You can then simply browse the file in scid vs pc. Or extract games of a specific player (again using pgn-extract) and you will see how many games are extracted. Otherwise, you can use a "simple" bash (e.g., grep/sort/wc commands)/awk/sed/perl/python script to get player frequencies in a pgn file. (Sorry, I cannot write such a script quickly, but similar scripts may be available already.)

If you are more interested in a specific player, then extract first by player name and then get the statistics of their openings. (By the way, pgn-extract can add opening codes in a pgn file of they don't already exist.)

Or in scid vs pc filter games containing a given position, say, the position after 1. e4 e5 2. Nf3 Nc6 3. Bb5, and browse the filtered list.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.