Chess.com Player Scraper — Profile & Ratings
Pricing
Pay per event
Chess.com Player Scraper — Profile & Ratings
Get Chess.com player profiles, per-game-type ratings and optional recent games in one call. Feed a list of usernames and get combined rows as clean JSON, CSV or Excel — no manual API stitching.
Pricing
Pay per event
Rating
0.0
(0)
Developer
DevilScrapes
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
🎯 What this scrapes
Chess.com's own Published-Data API splits one player across three or four separate endpoints — profile, per-game-type stats, and (if you want them) a whole month of games. This Actor calls all of them for you and hands back one row per username: profile fields, every rating record the player has (blitz, bullet, rapid, daily, tactics, puzzle rush, FIDE), and an optional recent-games slice, combined and normalised into one clean object.
🔥 What we handle for you
- 🛡️ We rotate real-browser fingerprints on every request so the target sees a browser, not a script.
- 🔁 We retry with exponential backoff on rate limits and server errors, honoring
Retry-After. - 🌐 We route requests through Apify Proxy and give you a one-click escalation to residential if you ever see blocks.
- 🧱 One bad or renamed username never crashes the run — it's skipped and named in the run summary.
- 🧊 Every row is Pydantic-validated: stable field names, ISO-8601 timestamps, no half-parsed JSON.
- 💰 You pay only for usernames actually processed. No data → no charge beyond the small warm-up fee.
💡 Use cases
- Chess streamers and content creators tracking their own rating history and follower counts.
- Coaches monitoring a roster of students' rating progress across game types.
- Chess analytics and stats sites building leaderboards or rating-trend charts.
- Tournament organisers vetting player ratings and activity before seeding a bracket.
⚙️ How to use it
- Click Try for free at the top of the page.
- Paste in the Chess.com usernames you want — the demo run ships with three real accounts prefilled.
- Toggle Include recent games on if you also want the latest month of games (heavier, priced the same).
- Click Start. Output streams into the run's dataset.
- Export from Storage → Dataset as JSON, CSV, or Excel — or fetch via the API.
📥 Input
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
usernames | array | yes | — | Chess.com usernames, 1-25 chars each, case-insensitive, deduplicated. One row per username. |
includeGames | boolean | no | false | Also fetch the player's most recent month of games. Off by default — this is the heaviest, most egress-expensive call. |
gamesMonth | string | no | — | Optional YYYY-MM month. Only used when includeGames is on; leave empty to use the most recent month available. |
maxItems | integer | no | 100 | Stop after this many usernames. Each username processed is one billed result row. |
proxyConfiguration | object | no | {"useApifyProxy": true} | Standard Apify proxy pool. Switch to Residential only if you see repeated blocks. |
Example input
{"usernames": ["hikaru", "magnuscarlsen", "fabianocaruana"],"includeGames": false,"maxItems": 100,"proxyConfiguration": {"useApifyProxy": true}}
📤 Output
Every row is one dataset item — one username, fully combined.
| Field | Type | Notes |
|---|---|---|
username | string | Normalised (lowercased) username, as requested. |
player_id | integer | Chess.com internal player id. |
profile_url | string | Public profile URL on chess.com. |
followers | integer | Follower count. |
country_code | string | Two-letter country code. |
last_online / joined | string | ISO-8601 UTC timestamps. |
is_streamer / verified / league | mixed | Account flags and league name. |
stats_chess_blitz, stats_chess_bullet, stats_chess_rapid, … | object | null | One rating record per game type the player has played; null if never played. |
games_month_fetched | string | YYYY-MM actually fetched; null unless includeGames was on. |
recent_games | array | Populated only when includeGames is on. |
scraped_at | string | ISO-8601 UTC timestamp at fetch time. |
Example output
{"username": "hikaru","player_id": 15448422,"profile_url": "https://www.chess.com/member/hikaru","followers": 1250000,"country_code": "US","league": "Legend","stats_chess_blitz": {"last_rating": 3320,"best_rating": 3378,"wins": 9800,"losses": 3100,"draws": 450},"games_month_fetched": null,"recent_games": [],"scraped_at": "2026-09-04T06:20:00Z"}
💰 Pricing
Pay-Per-Event — you pay only when these events fire:
| Event | USD | What it is |
|---|---|---|
actor-start | $0.20 | One-off warm-up charge per run |
result | $0.002 | Per username processed (profile + stats + optional games) |
Example: 1 000 usernames at the rates above ≈ $2.20. No subscription, no minimum, no card to start — Apify gives every new account $5 of free credit.
🚧 Limitations
- Games fetch caps at one month per username per run — full multi-month backfill isn't in scope.
- Requests are throttled to stay courteous to a free public API, so a large
includeGamesrun takes real time. - Club, tournament, and leaderboard data are out of scope — this Actor is player-focused only.
❓ FAQ
Do I need an API key?
No. Chess.com's Published-Data API is public and keyless, so a run needs no credentials from you.
What happens if a username doesn't exist?
It's skipped, logged, and named in the run's status message. The run still finishes successfully — a batch of unknown usernames is a completed check, not a failure.
A username I know is real still came back skipped — why?
Two different things can produce a skip, and both are treated the same way: the username genuinely doesn't exist (renamed/deleted account), or Chess.com's own API returns a not-found response for one specific sub-endpoint on an otherwise-valid account — rare, but it happens on their side independent of anything we send. Either way we skip that one username, name it in the run's status message, and keep going — it never blocks the rest of your list.
Why is includeGames off by default?
Fetching a full month of games (with PGN move text) is the heaviest call this Actor makes. Leaving it off keeps a plain profile+ratings run fast and cheap; turn it on when you actually need the games.
💬 Your feedback
Spotted a bug, hit a weird edge case, or need a new field? Open an issue on the Actor's Issues tab on Apify Console — we ship fixes weekly and we read every report.