Have you ever thought about comparing two chess accounts to find out if they belong to the same player?
I bet you have.
The first thing that comes to my mind is comparing the ECO codes (or the first moves sequence) they play.
This can be easily done with tools like Chessbase, OpeningTree, or even Lichess itself.
However, even though this approach is visual and somewhat quantitative, it still requires a lot of manual work - and a lot of brain processing - to determine what is actually going on.
Not long ago, I indexed my own PGN games into Elasticsearch to draw some statistics from them and decide where I should focus my study.
That meant my first goal had already been achieved: I knew how to ingest PGN data and extract useful information from it.
So naturally, the next step was: what else can I do with this?
I decided to take it one step further and experiment with two accounts that I already knew belonged to the same player.
This gave me a concrete baseline to validate my ideas.
At that point, I was already downloading PGN data and ingesting it into Elasticsearch.
Now I needed a way to compare players.
I came up with a simple idea:
What if each player had an "opening fingerprint"?
To build this, I:
Then I stored those vectors in Elasticsearch.
And that’s where the fun began.
Once each player is represented as a vector, comparing them becomes a similarity problem.
Using vector similarity (cosine similarity in this case), I can ask:
“Which players have similar opening fingerprints?”
Instead of manually comparing opening trees, the system ranks players by similarity automatically.
After validating the idea with known accounts, it was time to scale.
I upgraded the code to:
This removed a lot of friction, whilst making the whole process much more fun to explore.
At a high level, the system works like this:
PGN games (Lichess / Chess.com)
↓
ECO extraction
↓
Opening histograms (white / black)
↓
Vector representation
↓
Stored in Elasticsearch
↓
Vector similarity comparison
↓
Ranking similar accounts
↓
(Optional) clustering similar pairs
The system also keeps track of profile status, so accounts with:
are handled explicitly and not reprocessed unnecessarily.
The similarity score reflects how similar two accounts are in terms of their opening choices.
A high score means:
“These accounts play similar openings.”
It does not mean:
“These accounts belong to the same person.”
This is an experimental tool designed for exploration.
Opening similarity is just one signal. Two completely different players might:
So, even though the tool can highlight interesting similarities, it should never be used as proof of identity.
The current version focuses mostly on opening choices.
It does not yet analyze:
These are natural next steps.
Elasticsearch is used to:
It turns a manual, error-prone process into something automated and scalable.
This project started as a curiosity.
It turned into a tool.
And now… it's a playground for ideas.