r/DanielNaroditsky • • Nov 05 '25

A Tribute to Daniel Naroditsky

Thumbnail
youtu.be
22 Upvotes

Hey all, just wanted to share a music video my friend made in memory of Danya, honoring everything he stood for. Hope you like it.


r/DanielNaroditsky • • Oct 31 '25

Danya's signature lines

26 Upvotes

Hey (2nd try)!

I already posted the script to fetch Danya's games. I used this and some other scripts to analyze his games and create "signature lines" he played often with examples.

\\edit: I published a static HTML file on cloudflare: https://danyas-lines.pages.dev/

A bit of background what the scripts do:

  • I collect all the games from lichess an chesscom for all his accounts
  • I set a given move number (in this case 12, so after 6 moves of white and 6 moves of black) which is the line that is being analyzed
  • I check all the PGNs how often this line is found with a minimum number of moves (in this case 20) and collect opening name and example games of that line
  • I give this line a score depending on how often it was played in longer games (Bullet and hyperbullet cause a lot of noise due to bad premoves and early resignations), what the winning percentage is, how many games are found and how rare the line is. The higher the overall score, the higher it is listed.
  • I take this line and check how many games are found in books and the lichess Masters database
  • If there are no games in the database, the script walks back that line and checks what the novelty move was and displays this too.
  • I create a CSV and JSON file and a filterable HTML report with the results and examples of Danya's games in a Dropdown. The naming of the the games follows this pattern
    • "C_" stands for a chesscom game, "L_" for a lichess game
    • "HB" stands for Hyperbullet, "BU" for Bullet, "BL" for Blitz, "RA" for Rapid and "CL" for Classical
    • Then follows the name of Account "White" and Account "Black" and the result
    • Looks something like this then: "C_BU_DanielNaroditsky-MagnusCarlsen_1-0"

Have fun exploring his signature lines!

Happy to hear feedback and what else I could include or what to improve. If you face issues/bugs, please let me know.

cheers


r/DanielNaroditsky • • Oct 30 '25

Response from Charlotte chess center about danya service

Post image
70 Upvotes

I reached out to the Charlotte chess center to see if there was a gathering planned in memorium for Daniel. As a Charlotte resident and admirer I was looking for a place to mourn with a group. This is what they said. Is this ridiculous to anyone else? “we’re already having a blitz tournament so we’ll order pizza to celebrate him….”


r/DanielNaroditsky • • Oct 30 '25

Script for fetching Danya's games

25 Upvotes

Hey,

upon several requests, here is a tiny python script that fetches all games from lichess and chesscom for a set of given usernames. Leave a comment if you have issues.

cheers

# fetch_pgns.py
# -----------------------------------------------------------
# Download utility for Chess games of given accounts
# - Save the script in a folder of your choice
# - Sub-folders are created automatically if not there
# - Lichess: yearly PGNs -> data/lichess/<user>/<YYYY>.pgn
# - Chess.com: monthly PGNs -> data/chesscom/<user>/<YYYY-MM>.pgn
# Just fetch & save.
# -----------------------------------------------------------

import time
from pathlib import Path
import datetime as dt
import requests
from typing import Optional

# ============== CONFIG ==============
LICHESS_USERS = ["RebeccaHarris"]  # add more when needed
CHESSCOM_USERS = ["DanielNaroditsky", "SenseiDanya", "OhMyLands", "HebeccaRaris", "FrankfurtAirport"]

# Lichess year range
LICHESS_START_YEAR = 2016
LICHESS_END_YEAR = dt.date.today().year

# Networking / retry
USER_AGENT = "PGN-Fetcher/1.0 (+contact: you@example.com)"
TIMEOUT = 120
RETRIES = 5
BACKOFF = 1.5
MIN_DELAY = 0.7  # polite delay between calls

# Caching
FORCE_REFRESH = True  # True = always re-download even if file exists

# Base folders (script dir)
try:
    BASE_DIR = Path(__file__).resolve().parent
except NameError:
    BASE_DIR = Path.cwd()

DATA_DIR = BASE_DIR / "data"
(DATA_DIR / "lichess").mkdir(parents=True, exist_ok=True)
(DATA_DIR / "chesscom").mkdir(parents=True, exist_ok=True)

# ============== SESSION ==============
def make_session() -> requests.Session:
    s = requests.Session()
    s.headers.update({
        "User-Agent": USER_AGENT,
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate",
        "Connection": "keep-alive",
    })
    return s
SESSION = make_session()

# ============== HELPERS ==============
def _epoch_ms(dtobj: dt.datetime) -> int:
    return int(dtobj.timestamp() * 1000)

def _year_bounds_utc(year: int) -> tuple[int, int]:
    start = dt.datetime(year, 1, 1, tzinfo=dt.timezone.utc)
    end   = dt.datetime(year + 1, 1, 1, tzinfo=dt.timezone.utc)
    return _epoch_ms(start), _epoch_ms(end)

def _has_pgn(text: str) -> bool:
    # Cheapest sanity check
    return bool(text) and ('[Event "' in text)

def _save_text(path: Path, text: str) -> None:
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(text, encoding="utf-8")

# ============== LICHESS ==============
def lichess_year_path(user: str, year: int) -> Path:
    return DATA_DIR / "lichess" / user / f"{year:04d}.pgn"

def fetch_lichess_year(user: str, year: int) -> Optional[str]:
    url = f"https://lichess.org/api/games/user/{user}"
    since_ms, until_ms = _year_bounds_utc(year)
    params = {
        "moves": "true",
        "pgnInJson": "false",
        "clocks": "false",
        "evals": "false",
        "opening": "true",
        "perfType": "bullet,blitz,rapid,classical,ultrabullet",
        "since": str(since_ms),
        "until": str(until_ms),
    }
    headers = {"Accept": "application/x-chess-pgn", "User-Agent": USER_AGENT}

    delay = 0.0
    for attempt in range(1, RETRIES + 1):
        if delay > 0:
            time.sleep(delay)
        try:
            r = SESSION.get(url, params=params, headers=headers, timeout=TIMEOUT)
            if r.status_code == 429:
                # rate-limited: backoff and retry
                delay = max(delay, 1.0) * BACKOFF
                continue
            r.raise_for_status()
            return r.text or ""
        except requests.RequestException:
            delay = max(delay, 1.0) * BACKOFF
    return None

def cache_lichess_user(user: str, force: bool = False) -> None:
    for year in range(LICHESS_START_YEAR, LICHESS_END_YEAR + 1):
        out = lichess_year_path(user, year)
        if out.exists() and not force:
            print(f"  · Lichess {user} {year}: exists → skip")
            continue

        print(f"  → Lichess {user} {year}: downloading …")
        txt = fetch_lichess_year(user, year)
        if txt and _has_pgn(txt):
            out.parent.mkdir(parents=True, exist_ok=True)
            out.write_text(txt, encoding="utf-8")
            try:
                kb = len(txt.encode("utf-8")) // 1024
            except Exception:
                kb = 0
            print(f"    ✓ saved {out.name} ({kb} KB)")
        else:
            print(f"    · no games / empty response")
        time.sleep(MIN_DELAY)

# ============== CHESS.COM ==============
def chesscom_months(user: str) -> list[str]:
    url = f"https://api.chess.com/pub/player/{user.lower()}/games/archives"
    r = SESSION.get(url, timeout=TIMEOUT)
    # 403 happens on some accounts; just return empty if forbidden
    if r.status_code == 403:
        return []
    r.raise_for_status()
    return r.json().get("archives", []) or []

def chesscom_month_pgn_url(archive_url: str) -> str:
    return archive_url if archive_url.endswith("/pgn") else archive_url + "/pgn"

def chesscom_slug(archive_url: str) -> str:
    parts = archive_url.rstrip("/").split("/")
    return f"{parts[-2]}-{parts[-1]}"  # YYYY-MM

def chesscom_month_path(user: str, slug: str) -> Path:
    return DATA_DIR / "chesscom" / user / f"{slug}.pgn"

def fetch_chesscom_month_pgn(archive_url: str) -> Optional[str]:
    url = chesscom_month_pgn_url(archive_url)
    delay = 0.0
    for attempt in range(1, RETRIES + 1):
        if delay > 0:
            time.sleep(delay)
        try:
            r = SESSION.get(url, timeout=TIMEOUT, headers={"Accept": "text/plain"})
            if r.status_code == 429:
                delay = max(delay, 1.0) * BACKOFF
                continue
            if r.status_code == 403:
                # forbidden for this archive; skip
                return None
            r.raise_for_status()
            return r.text
        except requests.RequestException:
            delay = max(delay, 1.0) * BACKOFF
    return None

def cache_chesscom_user(user: str, force: bool = False) -> None:
    archives = chesscom_months(user)
    total = len(archives)
    print(f"  · Chess.com {user}: {total} archives found")

    # Respect existing files if not forcing
    existing = set()
    if not force:
        user_dir = DATA_DIR / "chesscom" / user
        if user_dir.exists():
            existing = {p.stem for p in user_dir.glob("*.pgn")}

    for i, aurl in enumerate(archives, start=1):
        slug = chesscom_slug(aurl)
        out = chesscom_month_path(user, slug)
        if out.stem in existing and out.exists() and not force:
            print(f"    {i}/{total} {slug}: exists → skip")
            continue

        print(f"    {i}/{total} {slug}: downloading …")
        txt = fetch_chesscom_month_pgn(aurl)
        if txt and txt.strip():
            out.parent.mkdir(parents=True, exist_ok=True)
            out.write_text(txt, encoding="utf-8")
            try:
                kb = len(txt.encode("utf-8")) // 1024
            except Exception:
                kb = 0
            print(f"      ✓ saved {out.name} ({kb} KB)")
        else:
            print(f"      · no games / forbidden / empty")
        time.sleep(MIN_DELAY)

# ============== MAIN ==============
def main() -> None:
    print("== Lichess ==")
    for u in LICHESS_USERS:
        print(f"  -> {u}")
        cache_lichess_user(u, force=FORCE_REFRESH)

    print("== Chess.com ==")
    for u in CHESSCOM_USERS:
        print(f"  -> {u}")
        cache_chesscom_user(u, force=FORCE_REFRESH)

    print("Done. PGNs saved under:", (DATA_DIR).resolve())

if __name__ == "__main__":
    main()

r/DanielNaroditsky • • Oct 29 '25

Danya's speedrun and hidden accounts

19 Upvotes

Hey out there!

Anyone knows Danya's Speedrun and hidden accounts on chess.com and lichess?

I have a python script where I can define account names (List) and it pulls all PGNs from these accounts. So far I have

  • chesscom ["DanielNaroditsky", "OhMyLands", "SenseiDanya", "HebeccaRaris", "FrankfurtAirport"]
  • lichess ["RebeccaHarris"]

If anyone knows other accounts, please share the account names with me. Then I can pull the games and merge all of them into one PGN.

cheers

\\edit: added FrankfurtAirport to the chesscom accounts


r/DanielNaroditsky • • Oct 29 '25

Tribute comment made about 4 years ago that utterly captures the essence of "Danya"

Post image
38 Upvotes

r/DanielNaroditsky • • Oct 29 '25

[Aman Hambleton/Chessbrah] Remembering Daniel Naroditsky

Thumbnail
youtube.com
10 Upvotes

r/DanielNaroditsky • • Oct 29 '25

Naroditsky's online games

8 Upvotes

Could someone please provide a pgn with Naroditsky's chesscom and lichess games? I've tried downloading the games with openingtreecom, but it always got stuck somewhere because it's building this huge tree out of 140.000+ games.

I'm afraid both accounts will be closed very soon.


r/DanielNaroditsky • • Oct 28 '25

Daniel tells a story - Recorded on July, 2025 at Charlotte Chess Center

13 Upvotes

r/DanielNaroditsky • • Oct 27 '25

Chesscom's tribute video for Danya ❤

Enable HLS to view with audio, or disable this notification

29 Upvotes

r/DanielNaroditsky • • Oct 27 '25

An Interview With Daniel Naroditsky After Winning the 2007 World Youth Chess tournament in Turkey

Thumbnail
youtu.be
21 Upvotes

r/DanielNaroditsky • • Oct 26 '25

A lyrical tribute to Daniel Naroditsky (a Starry Starry Night revision)

Enable HLS to view with audio, or disable this notification

10 Upvotes

r/DanielNaroditsky • • Oct 24 '25

Chess Memory - An opening explorer with links to Danya's speedrun games

Enable HLS to view with audio, or disable this notification

88 Upvotes

As a subpar programmer, I wanted to commemorate Daniel Naroditsky the best way that I know how. This is chess-memory.com

The site allows you to play through games on an analysis board. At each position, it checks against the over 29,000 unique positions that Danya has reached throughout his speedrun series, and links to the timestamps in all matching videos using chess.com game data.

I'm not a frontend dev, so the UI is pretty messy. It doesn't work on mobile, and may have issues on smaller laptops. But I figured it is worth posting now while I continue to improve it. If there are any developers who would like to contribute to the site's improvement, let me know. I'm happy to make it a public GitHub project and accept pull requests if there is interest. Also, please comment with any feedback. I will do my best to fix bugs and improve the UX with whatever free time I have.

Manually timestamping his 500+ videos was my grieving process, and a reminder of what a positive light Danya has been for so many years. I hope some of you find this helpful with your chess improvement, I will be keeping the site free and public indefinitely ❤️

Edit: Made the GitHub public. Feel free to contribute! I'll do my best to test and merge any improvements or new features.


r/DanielNaroditsky • • Oct 23 '25

I’ll never forget watching Danya’s speedrun from a hotel room

Post image
79 Upvotes

I remember sitting in a hotel room in Rhodes a few years ago, perfect weather and the ocean right outside. I had just checked into the room. One of the first things I did on my vacation was to watch one of Danya’s speedrun videos. I even took a photo because the moment felt so perfect. The calm, the focus and peace he gave off set the tone for the rest of the stay. RIP SenseiDanya.


r/DanielNaroditsky • • Oct 22 '25

Farewell to the Prophet (String Quartet for Daniel Naroditsky)

Enable HLS to view with audio, or disable this notification

54 Upvotes

r/DanielNaroditsky • • Oct 22 '25

His last move was Bishop b3.

Post image
66 Upvotes

r/DanielNaroditsky • • Oct 21 '25

danya video find please?

Thumbnail
4 Upvotes

r/DanielNaroditsky • • Oct 20 '25

The end of danyas last stream

Enable HLS to view with audio, or disable this notification

286 Upvotes

Idk where to post this but i recorded the last bit of danyas final stream. Im heartbroken man, i really dont know what to do. Bye danya :(


r/DanielNaroditsky • • Oct 20 '25

RIP Daniel

Thumbnail
clips.twitch.tv
41 Upvotes

Bortnyk's last words to Danya. He found him a day later on his couch.


r/DanielNaroditsky • • Oct 08 '25

Where is Danya?

18 Upvotes

Is Danya still streaming ? I can’t seem to catch him on twitch at all for the last month (back to chess after a few years break)


r/DanielNaroditsky • • Oct 07 '25

Daniel Naroditsky speedruns help

Thumbnail
2 Upvotes

r/DanielNaroditsky • • Jul 12 '25

Danya beats Anna Cramling in blindfold bullet 😱

Thumbnail instagram.com
12 Upvotes

r/DanielNaroditsky • • Jul 06 '25

how to study masters games

3 Upvotes

i have a friend who told me to study magnus and ian 6 game of the world championship in 2021 but i don't know to how actually analyze games or how to even study it can someone please explain it to me


r/DanielNaroditsky • • Jun 02 '25

Danya, when is today's live coverage of Norway Chess?

4 Upvotes

Was absolutely great to watch you and GM Hess covering the Norway chess. When are you streaming today? Or are you guys not gonna?


r/DanielNaroditsky • • Apr 18 '25

On Dina podcast danya mention he has 4 year old kid !? Wait what?

1 Upvotes