user18749: 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.

user32763: 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.

user26335: 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.

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.


user30545: 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

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

Install pgnhelper from command line.


pip install pgnhelper -U


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.

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.
Code
ruylopez.py
"""Show player names and number of games on the given opening name.

requirements:
  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:
    print(o)

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,
                   data[p]['data'][opening_name]['w'],
                   data[p]['data'][opening_name]['b'],
                   data[p]['data'][opening_name]['total']])

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

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

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

Output
Sicilian defence
English opening
Ruy Lopez
QGD
Sicilian, Chekhover variation
Giuoco Pianissimo
Gruenfeld
Sicilian
Catalan
Nimzo-Indian
Catalan opening
Petrov
Reti
Four knights game
Four knights
English
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:
    print(o)

Results are printed in console due to:
print(mydf)

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.

18749: <p>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.</p>
<p>I know that chess.com and 365chess has this feature, but they only provide 3 to 5 players per opening.</p>
 32763: <p>You could use <code>pgn-extract -e3 pgn-file-name</code> 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 &quot;simple&quot; 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.)</p>
<p>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.)</p>
<p>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.</p>
 26335: <p>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 <a href="https://www.365chess.com/opening.php?m=4&amp;n=74&amp;ms=e4.e5.d4&amp;ns=3.5.74" rel="nofollow noreferrer">Chess365 functionality</a> you reference.</p>
<p><strong>Option 1: ChessGames.com General Search</strong><br />
<a href="https://www.chessgames.com/" rel="nofollow noreferrer">ChessGames.com</a> allows searches by ECO code or opening.   For example, <a href="https://www.chessgames.com/perl/chess.pl?yearcomp=exactly&amp;year=2021&amp;playercomp=either&amp;pid=&amp;player=&amp;pid2=&amp;player2=&amp;movescomp=exactly&amp;moves=&amp;opening=C45&amp;eco=&amp;result=" rel="nofollow noreferrer">here are the results</a> for games in the <a href="https://en.wikipedia.org/wiki/Scotch_Game" rel="nofollow noreferrer">Scotch</a> (ECOs C45–45) restricted to the year 2021. You can further restrict games by result (White wins, Black wins, draw, or &quot;no draw&quot;). You can parse the results easily enough.</p>
<p><strong>Option 2: ChessGames.com Opening Explorer</strong><br />
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 (<a href="https://en.wikipedia.org/wiki/Berlin_Defence_(chess)" rel="nofollow noreferrer">Berlin Defense</a> is 65–67) gives the following.</p>
<p><a href="https://i.stack.imgur.com/eTO3f.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/eTO3f.png" alt="Results from search" /></a></p>
<p><strong>Option 3: ChessTempo.com Opening Explorer</strong><br />
<a href="https://chesstempo.com/" rel="nofollow noreferrer">ChessTempo.com</a> has an <a href="https://old.chesstempo.com/game-database.html" rel="nofollow noreferrer">opening explorer</a> with some added filters including specifying a rating range. Again, you'd have to parse the results, but it seems relevant.</p>
<p>For example, I asked for all games with position after <strong>1. e4 c5 2. Nc3 Nc6 3. f4</strong> (<a href="https://en.wikipedia.org/wiki/Sicilian_Defence#Grand_Prix_Attack" rel="nofollow noreferrer">Grand Prix Attack</a>) with both players rated 2700+.  It returns the following.</p>
<p><a href="https://i.stack.imgur.com/64KFI.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/64KFI.png" alt="Search results from ChessTempo" /></a></p>
 30545: <p>I had created a python package called <a href="https://pypi.org/project/pgnhelper/" rel="noreferrer">pgnhelper</a> with <a href="https://pgnhelper.readthedocs.io/en/latest/index.html" rel="noreferrer">documentation</a> which can be used to see what you would like to find.</p>
<p>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.</p>
<h3>Typical setup for windows 10</h3>
<ol>
<li><p>Intall python 3.7 or later from <a href="https://www.python.org/downloads/" rel="noreferrer">https://www.python.org/downloads/</a></p>
</li>
<li><p>Install pgnhelper from command line.</p>
</li>
</ol>
<pre><code>pip install pgnhelper -U
</code></pre>
<ol start="3">
<li>Save the code below to ruylopez.py.</li>
</ol>
<p>3.1 Download candidates games from <a href="https://theweekinchess.com/assets/files/pgn/wchcand22.pgn" rel="noreferrer">https://theweekinchess.com/assets/files/pgn/wchcand22.pgn</a></p>
<p>3.2. Place the pgn file and ruylopez.py in the same directory.</p>
<ol start="4">
<li>Execute ruylopez.py from command line like an example below.</li>
</ol>
<pre><code>PS F:\pgnhelpter_test&gt; python ruylopez.py
</code></pre>
<p>The ruylopez.py and wchcand22.pgn are in F:\pgnhelpter_test path where <code>pgnhelpter_test</code> is the folder or directory name.</p>
<h3>Code</h3>
<p><code>ruylopez.py</code></p>
<pre><code>&quot;&quot;&quot;Show player names and number of games on the given opening name.

requirements:
  pip install pgnhelper -U
&quot;&quot;&quot;


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(&quot;sample.csv&quot;, index=False)

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

data = {}
for p in players:
    data1 = {}
    for o in openings:
        dfw = df.loc[(df.Opening == o) &amp; (df.White == p)]
        dfb = df.loc[(df.Opening == o) &amp; (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,
                   data[p]['data'][opening_name]['w'],
                   data[p]['data'][opening_name]['b'],
                   data[p]['data'][opening_name]['total']])

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

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

mydf.to_csv(&quot;ruylopez.csv&quot;, index=False)  # Save to csv file
</code></pre>
<h3>Output</h3>
<pre><code>Sicilian defence
English opening
Ruy Lopez
QGD
Sicilian, Chekhover variation
Giuoco Pianissimo
Gruenfeld
Sicilian
Catalan
Nimzo-Indian
Catalan opening
Petrov
Reti
Four knights game
Four knights
English
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
</code></pre>
<p>The code can be revised to show a column of score percentage. Can also be revised to show by ECO code.</p>
<p>Opening names in the game are printed in console due to:</p>
<pre><code>openings = df.Opening.unique()
for o in openings:
    print(o)
</code></pre>
<p>Results are printed in console due to:</p>
<pre><code>print(mydf)
</code></pre>
<p>csv file will be saved due to:</p>
<p><code>mydf.to_csv(&quot;ruylopez.csv&quot;, index=False)  # Save to csv file</code></p>
<p>You can change the opening name in  the code by changing below code:</p>
<pre><code>opening_name = 'Ruy Lopez'
</code></pre>
<p>You can use different pgn file but be sure the game has Opening tag like below.</p>
<pre><code>[Event &quot;FIDE Candidates 2022&quot;]
[Site &quot;Madrid ESP&quot;]
[Date &quot;2022.06.17&quot;]
[Round &quot;1.3&quot;]
[White &quot;Caruana, Fabiano&quot;]
[Black &quot;Nakamura, Hikaru&quot;]
[Result &quot;1-0&quot;]
[WhiteTitle &quot;GM&quot;]
[BlackTitle &quot;GM&quot;]
[WhiteElo &quot;2783&quot;]
[BlackElo &quot;2760&quot;]
[ECO &quot;C65&quot;]
[Opening &quot;Ruy Lopez&quot;]
[Variation &quot;Berlin defence&quot;]
[WhiteFideId &quot;2020009&quot;]
[BlackFideId &quot;2016192&quot;]
[EventDate &quot;2022.06.17&quot;]

1. e4 e5 2. Nf3 Nc6 ...
</code></pre>
<p>There must be <code>Opening</code> tag.</p>
<pre><code>[Opening &quot;Ruy Lopez&quot;]
</code></pre>
<h3>Add eco</h3>
<p>If the game in your pgn file has no Opening tag, you can use pgnhelper to add a tag.</p>
<p>Example from command line:</p>
<pre><code>pgnhelper addeco --inpgnfn candidates_zurich_1953.pgn --outpgnfn eco_candidates_zurich_1953.pgn --inecopgnfn eco.pgn
</code></pre>
<p>See also the guide at <a href="https://pgnhelper.readthedocs.io/en/latest/usage.html" rel="noreferrer">https://pgnhelper.readthedocs.io/en/latest/usage.html</a>.</p>
<p>The file <code>eco.pgn</code> is needed, you can <a href="https://github.com/fsmosca/pgnhelper/tree/main/eco" rel="noreferrer">download</a> it from github.</p>
<p>For example you can download pgn files from <a href="https://theweekinchess.com/" rel="noreferrer">weekinchess,</a> or from <a href="https://www.pgnmentor.com/files.html#events" rel="noreferrer">pgnmentor.</a></p>
