How to Scrape Chess.com Players, Games & Leaderboards
Pull Chess.com game PGN, ratings, openings, GM/IM rosters and leaderboards at scale via the official Published-Data API — no API key, thousands of rows per run.
Building a chess research dataset by hand is miserable: you’re clicking through monthly game archives, copying PGN one game at a time, and reconciling usernames against titles across dozens of pages. Chess.com actually publishes all of this through a real, documented, keyless API — but wiring up the pagination, rate-limit handling and the five different endpoint shapes into a single clean dataset is the part nobody wants to write twice. This guide covers how the Chess.com Published-Data API is structured, what you can pull from it, and how to turn a month of a GM’s games or an entire titled-player roster into thousands of structured rows in one run.
What’s worth extracting
The actor runs against five distinct modes, and the fields you get depend on which one you use. There are two main record shapes.
Game records (from playerGames):
pgn— the full PGN game notation, which is the load-bearing field for any position or move analysis.eco— the ECO opening code (e.g.B92), andopening, the opening name parsed from the PGN.timeClass(rapid / blitz / bullet / daily) andtimeControl(the exact string, e.g.180+2).whiteUsername/whiteRating/whiteResultand the black equivalents — who played, their rating at game time, and the outcome (win, resigned, timeout, draw…).rated(true/false),endTime(ISO 8601), and the gameurl.
Player/profile records (from titledPlayers, playerProfile, countryPlayers, leaderboards):
username,name,title(GM, IM, FM…),country(2-letter code),url,avatar.followers,joined(ISO 8601),status(premium, basic…).- Ratings per format:
ratingRapid,ratingBlitz,ratingBullet,ratingChess960. - In leaderboards mode, additionally
rankandscore.
Every row also carries a mode field so you can filter a mixed dataset. That’s 30+ fields across the two shapes.
How the source actually works
The engine talks directly to the official Chess.com Published-Data API at api.chess.com/pub — the same public JSON API Chess.com explicitly provides for third-party use. There is no API key, no OAuth, and no HTML scraping involved. The five modes map to different endpoint families:
playerGames— the monthly game archive. You give one or more usernames and a list of months inYYYY/MMformat; each month is a single API call per player and can return dozens to hundreds of games.titledPlayers— the roster of all players holding a given title (GM, WGM, IM, WIM, FM, WFM, NM, WNM, CM, WCM), then their full profiles.countryPlayers— every registered player under an ISO 3166-1 alpha-2 country code (this can be enormous).leaderboards— current global rankings across time controls.playerProfile— profile plus stats for specific usernames.
Two operational details from the README matter. Chess.com’s guidelines ask for a descriptive User-Agent on every request, which the actor sends. And it runs player lookups in concurrent batches of 10 with automatic retry on 429 responses, which is what keeps throughput high while staying inside the roughly 1 request/second/IP that Chess.com expects.
A monthly-games run for two players:
{
"mode": "playerGames",
"usernames": ["magnuscarlsen", "hikaru"],
"months": ["2024/01", "2024/02", "2024/03"],
"maxResults": 5000
}
Leave months empty and it defaults to last month automatically.
▶ Open the Chess.com Scraper on Apify — one run yields a month of a GM’s games with full PGN, ECO and ratings, or every titled player on the platform. Keyless, straight from Chess.com’s own Published-Data API. Export to JSON, CSV or Excel.
The access reality
The Published-Data API is genuinely open, which removes the usual anti-bot headache — but there are real limits to design around:
- Rate limit is ~1 request/second per IP. The actor’s 10-way concurrency plus 429 retry handles this, but it’s why very large sweeps take time rather than finishing instantly.
- Country modes are huge. India, for instance, has hundreds of thousands of registered members. Always set
maxResultsoncountryPlayersor you’ll kick off a very long run. - Monthly archives are the pagination unit. You don’t page through games — you request whole months. One API call per player per month. Specifying tighter month ranges is the single biggest lever on run time.
- The current month is incomplete. Past-month archives are complete and stable; the current month’s archive grows as games are played and updates with a short delay, so expect the very latest games to be missing.
- You can’t filter time control at the API level. A monthly archive returns all games for that month. If you only want blitz, filter on
timeClassafter the fact (dataset filters or pandas).
Example output
A game row and a profile row, both tagged with mode:
{
"mode": "playerGames",
"url": "https://www.chess.com/game/live/98765432",
"timeClass": "bullet",
"timeControl": "60",
"rated": "true",
"endTime": "2024-06-01T14:33:00.000Z",
"whiteUsername": "hikaru",
"whiteRating": "3295",
"whiteResult": "win",
"blackUsername": "opponent123",
"blackRating": "2800",
"blackResult": "timeout",
"eco": "C20",
"opening": "King's Pawn Game"
}
{
"mode": "titledPlayers",
"username": "magnuscarlsen",
"name": "Magnus Carlsen",
"title": "GM",
"country": "NO",
"followers": "82000",
"ratingRapid": "3000",
"ratingBlitz": "3197",
"ratingBullet": "3100"
}
Typical use cases
- Opening analysis pipelines — download all Grandmaster games in a given month and filter by
ecoto study a specific line (e.g. every Sicilian Najdorf) across thousands of games. - Titled-player databases — build a searchable table of all active GMs with their rapid/blitz/bullet ratings and country affiliations.
- Leaderboard tracking — snapshot global leaderboards on a schedule to chart daily or weekly rating movement.
- National skill studies — pull a country’s player pool to study the distribution of chess skill within a nation.
- ML training data — feed PGN, openings and rating pairs into models for position evaluation or rating prediction.
- Coaching and study material — bulk-import a GM’s game collection for a training platform.
Build-it-yourself vs. managed actor
The API is keyless, so the temptation to build it yourself is real. But the work isn’t the first fetch — it’s the five endpoint shapes normalized into two clean record schemas, the YYYY/MM archive enumeration, the 10-way concurrency with 429 backoff, parsing eco and opening out of raw PGN, and gracefully handling players with no games in a given month (the actor logs a warning and continues rather than crashing the run).
On cost, this is pay-per-result: a fraction of a cent per row plus a tiny per-run start fee. A titledPlayers GM sweep is a couple thousand profiles; a year of one prolific player’s games is 1,000–3,000 games. You’re paying cents-to-low-dollars for datasets that would take hours to assemble by hand — with no proxy subscription, since the API is public and the actor runs fine on Apify’s shared proxies.
Common pitfalls
- Don’t run
countryPlayersuncapped. Popular countries have six-figure member counts. Always setmaxResults, or usetitledPlayersif you actually want strong players rather than everyone. - Current-month games lag. If your analysis needs completeness, target past months. The live month is still filling in.
- PGN needs a parser. The
pgnfield is raw notation. Use a real chess library (python-chess, chess.js) to extract moves, positions and evaluations — don’t try to regex it. - Missing fields are
null, not errors. Unrated players have no title, privacy settings can hide a name, and a player who’s never played a format has no rating there. The actor returnsnullfor these; handle them downstream. - Time-control filtering is your job. The archive gives you everything for a month; slice by
timeClassyourself. - Combine modes for depth. Run
titledPlayersfirst to collect usernames, then feed those intoplayerGames— that’s the intended two-step for a deep game corpus.
Wrapping up
Chess.com did the hard part by publishing a real keyless API. The remaining work is turning five endpoint shapes, monthly archive pagination and PGN parsing into one clean, deduplicated dataset — which is exactly what this actor packages. Point it at a title, a country, a leaderboard or a set of usernames and you have a structured chess dataset in one run.
▶ Run the Chess.com Scraper on Apify — thousands of games with PGN, ECO and ratings, or full GM/IM rosters and live leaderboards, straight from the official Published-Data API. No API key, no login. Export to JSON, CSV or Excel, and start on Apify’s free monthly credit.
Related guides
How to Build a Deep-Research Retrieval Layer for AI Agents
Give an agent a topic and get ranked web sources, full-page Markdown, and recent news with citations — keyless multi-source retrieval for RAG and grounding.
How to Extract Structured Data from Any URL in 2026
Turn any web page into clean JSON without an LLM: parse schema.org JSON-LD, OpenGraph, tables, prices and contacts deterministically — no API key, no browser.
How to Add Live Web Search to AI Agents (No API Key)
Give your LLM fresh, citable search results without a Tavily or SerpAPI key. How live SERP extraction works: ranked results plus Markdown page content for RAG.