Skip to main content

nytimes-games

PyPI Python Test License: MIT

An unofficial Python client for the New York Times Games APIs: Wordle, Connections, Strands, Spelling Bee, Letter Boxed and the Daily, Mini, Midi and Bonus crosswords, plus your own stats and game progress.

NYT doesn't publish documentation or an API spec for these endpoints. This package wraps them in one client with typed, validated Pydantic models, so you can build archives, stats dashboards, bots or your own games without reverse engineering NYT's APIs first. Optional extras add the nytg command line tool and a REST API.

nytg showing a Connections puzzle, a Strands board, a Mini crossword and Spelling Bee hints

Installation

pip install nytimes-games

The package installs as nytimes-games and is imported as nytgames. Python 3.10 or newer is required.

Quick start

from nytgames import NYTGamesClient

client = NYTGamesClient()

client.wordle("2025-06-12").solution
client.connections("2025-06-12").categories
client.crossword("mini")                  # today's Mini
client.crossword("daily", "1993-11-21")   # any Daily back to 1993

Your stats and game progress need your NYT session cookie:

client = NYTGamesClient(cookies="NYT-S=...")

stats = client.player_stats().stats
stats.wordle.calculatedStats.currentStreak
stats.connections.puzzles_won
stats.crossword_daily.dailyStats["monday"].avgTimeSeconds

What's available

Puzzles don't need cookies. Everything about you does.

Game Method Available from Cookies
Wordle wordle(date) 2021-06-19 No
Connections connections(date) 2023-06-12 No
Strands strands(date) 2024-03-04 No
Spelling Bee spelling_bee_puzzle(date) 2018-05-06 No
Letter Boxed letter_boxed(date) 2018-12-17 No
Crossword crossword(publish_type, date=None) Daily 1993-11-21, Mini 2014-08-21, Midi 2026-02-25, Bonus 1997 No
Crossword schedule crossword_oracle(publish_type) Current and next puzzle No
Puzzle list archive(game, date_start, date_end) IDs and dates for Wordle, Connections, Strands and the Daily, Mini and Midi No
Crossword list crossword_puzzles(publish_type, date_start=..., date_end=...) Daily, Mini and Bonus, with your progress when you have cookies Optional
Crossword progress crossword_game(puzzle_id, publish_type) Your saved game Yes
Wordle progress wordle_latest(puzzle_ids) Your saved games Yes
Spelling Bee progress spelling_bee_latest(puzzle_ids) Your saved games (up to 30 IDs) Yes
Stats player_stats() Every game you've played Yes

Dates are YYYY-MM-DD strings. publish_type is daily, mini, midi or bonus, and date=None returns today's puzzle. NYT usually serves the next day's puzzle a day early.

archive() is the quickest way to get puzzle IDs for a date range, for example to check your progress on a month of puzzles:

midis = client.archive("crossword_midi", "2026-09-01", "2026-09-30")
client.crossword_game([p.id for p in midis], "midi")   # up to 30 IDs per call

Spelling Bee extras:

from nytgames import spelling_bee_hints

puzzle = client.spelling_bee_puzzle("2026-10-03")
spelling_bee_hints(puzzle)      # Spelling Bee Forum style hints: counts, pairs, points
client.spelling_bee_puzzles()   # every puzzle on the game page (about two weeks)

Cookies

To get your NYT-S cookie, log in at nytimes.com, open your browser's developer tools, and find the NYT-S cookie for .nytimes.com (Application tab in Chrome, Storage tab in Firefox). Treat it like a password: it gives access to your NYT account.

cookies can be:

  • a Cookie header string: "NYT-S=...; nyt-a=..."
  • a dict: {"NYT-S": "..."}
  • a list of cookie objects with name and value keys, such as a JSON export from the Cookie-Editor browser extension

Errors

HTTP errors from NYT are raised as NYTGamesHTTPError, a subclass of requests.HTTPError:

Exception When
NYTGamesAuthenticationError 401 or 403, usually a missing or expired NYT-S cookie
NYTGamesNotFoundError 404, for example a date with no puzzle
NYTGamesHTTPError any other HTTP error
NYTGamesParseError an NYT page didn't contain the expected game data (a ValueError)
from nytgames import NYTGamesNotFoundError

try:
    client.wordle("1900-01-01")
except NYTGamesNotFoundError:
    print("No puzzle that day")

Models

Every method returns Pydantic models from nytgames.models. Fields NYT adds later are kept rather than rejected, so new NYT fields don't break your code. Use .model_dump() to get plain dicts, and by_alias=True to keep NYT's original keys, such as "Queen Bee" in the Spelling Bee ranks.

Command line

The optional cli extra installs nytg:

pipx install "nytimes-games[cli]"     # or: pip install "nytimes-games[cli]"
nytg wordle                      # today's Wordle, without the answer
nytg wordle yesterday --answers
nytg connections friday -a       # the groups, in their colors
nytg strands 2025-06-12
nytg bee --hints                 # Spelling Bee Forum style hints
nytg letter-boxed
nytg crossword mini              # the grid and clues
nytg crossword daily 1993-11-21 --answers

Answers are hidden unless you pass --answers, in every output format. Dates can be YYYY-MM-DD, today, yesterday, tomorrow or a weekday, and first for the first puzzle in nytg archive.

Your stats and history

Log in once with your NYT-S cookie (see Cookies):

nytg auth login                  # paste the cookie; it's checked, then saved
nytg auth status
nytg stats                       # every game at a glance
nytg stats crossword             # averages, bests and streaks by weekday
nytg today                       # which of today's games you've played
nytg history crossword --from 2026-01-01 -f csv > solves.csv
nytg history wordle --from monday
nytg history bee

Cookies are read from --cookies, then the NYT_COOKIES environment variable, then the active profile.

Archiving

nytg archive connections --from first --out puzzles/

saves each date as puzzles/connections/YYYY-MM-DD.json. Run it again to resume: saved dates are skipped. Games: wordle, connections, strands, spelling-bee, letter-boxed, crossword-daily, crossword-mini and crossword-midi.

Output formats

Every command takes --format (-f), like gcloud:

Format Output
table Tables and grids (the default)
json, yaml All the data
csv One row per item, nested fields as dotted columns
value(FIELD,...) Tab separated values for scripts, e.g. value(categories[0].title)
nytg wordle --answers -f "value(solution)"
nytg stats -f json | jq '.[] | select(.game == "Wordle")'

Profiles and settings

Settings are saved per profile in ~/.config/nytg/config.ini (readable only by you), similar to gcloud configurations:

nytg config set format json      # default output format for this profile
nytg config list
nytg --profile alice auth login  # a second NYT account
nytg config profiles activate alice
nytg config profiles list

--profile or NYTG_PROFILE picks a profile for one command. Run nytg --install-completion for shell completion.

Building your own command line

nytgames.cli.extension lets you build a command line with every nytg command plus your own, sharing its root options (--profile, --cookies, --format), output formats and error messages:

import typer
from nytgames.cli.extension import FormatOption, create_app, emit, get_client, run

app = create_app(name="mytool", help="My NYT tools.", version="1.0.0")
db = typer.Typer(help="Query my archive.")
app.add_typer(db, name="db")


@db.command("midis")
def midis(fmt: FormatOption = None) -> None:
    """September's Midi crosswords."""
    puzzles = get_client().archive("crossword_midi", "2026-09-01", "2026-09-30")
    emit([{"date": p.print_date, "by": p.byline} for p in puzzles], fmt)


def main() -> None:   # point your [project.scripts] entry here
    run(app)

Each create_app() call returns an independent app. emit(data, fmt, table) prints JSON-compatible data in the requested format, with an optional function that renders the table format. get_client() returns a client with the cookies nytg would use. The other modules in nytgames.cli are internal.

REST API

The optional api extra serves everything as a REST API with FastAPI, including interactive docs at /docs.

pip install "nytimes-games[api]"
uvicorn nytgames.api:app

To customize it, write your own main.py:

from nytgames.api import create_app

app = create_app(title="My NYT Games API")   # any FastAPI settings

Or mount the routes in an existing FastAPI app:

from fastapi import FastAPI
from nytgames.api import add_exception_handlers, router

app = FastAPI()
app.include_router(router, prefix="/nyt")
add_exception_handlers(app)   # NYT errors become 404s and 403s instead of 500s

By default each request is made with the cookies sent to the API:

curl -H "Cookie: NYT-S=..." http://localhost:8000/player/stats

To use your own cookies for every request instead, override the client:

from nytgames import NYTGamesClient
from nytgames.api import get_client

app.dependency_overrides[get_client] = lambda: NYTGamesClient(cookies="NYT-S=...")

Anyone who can reach that API can then see your stats and progress, so keep it private.

examples/api has a complete main.py and Dockerfile for running your own instance in a container.

Endpoints

Route NYT endpoint
GET /archive/{game}/{date_start}/{date_end} svc/games/v1/archive/{game}/{date_start}/{date_end}
GET /connections/{date} svc/connections/v2/{date}.json
GET /crosswords/daily/today svc/crosswords/v6/puzzle/daily.json
GET /crosswords/daily/{date} svc/crosswords/v6/puzzle/daily/{date}.json
GET /crosswords/mini/today svc/crosswords/v6/puzzle/mini.json
GET /crosswords/mini/{date} svc/crosswords/v6/puzzle/mini/{date}.json
GET /crosswords/midi/today svc/crosswords/v6/puzzle/midi.json
GET /crosswords/midi/{date} svc/crosswords/v6/puzzle/midi/{date}.json
GET /crosswords/bonus/{date} svc/crosswords/v6/puzzle/bonus/{date}.json
GET /crosswords/puzzles svc/crosswords/v3/puzzles.json
GET /crosswords/oracle/{publish_type} svc/crosswords/v2/oracle/{publish_type}.json
GET /crosswords/game/{game_id}?publish_type=daily svc/games/state/crossword_{publish_type}/latests
GET /letter-boxed/{date} svc/letter-boxed/v1/{date}.json
GET /player/stats svc/games/state/wordleV2/latests?puzzle_ids=0
GET /spelling-bee Scraped from puzzles/spelling-bee
GET /spelling-bee/latest svc/games/state/spelling_bee/latests
GET /spelling-bee/{date} svc/spelling-bee/v1/{date}.json
GET /spelling-bee/{date}/hints Computed from the puzzle above
GET /strands/{date} svc/strands/v2/{date}.json
GET /wordle/latest svc/games/state/wordleV2/latests
GET /wordle/{date} svc/wordle/v2/{date}.json

NYT errors are returned with NYT's status code, for example 404 for a date with no puzzle.

Contributing

NYT changes these APIs without notice, so bug reports with the failing date and error are very welcome. See CONTRIBUTING.md to set up a development environment.

License

MIT. This project is not affiliated with or endorsed by The New York Times. NYT puzzles are copyrighted by The New York Times; please respect their terms of service and don't republish puzzle content.

Metadata

Release files for nytimes-games 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nytimes-games 0.6.0
File Size Uploaded
nytimes_games-0.6.0.tar.gz 53.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nytimes-games 0.6.0
File Interpreter ABI Platform
nytimes_games-0.6.0-py3-none-any.whl Python 3 none any Details

Total release size: 99.0 kB

Release files / nytimes_games-0.6.0.tar.gz

Download URL nytimes_games-0.6.0.tar.gz
Size 53.8 kB
Tags Source
SHA-256 checksum
How to use checksums
3e0d3ddce6756e49b79af998451fdf79ef3bd26bd0321730a3bca29fb549195f
BLAKE2b-256 checksum
How to use checksums
9465b108527f19604e3007267c2b11e8f51e68c1646aaa02f5d26e30bf9046e3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release files / nytimes_games-0.6.0-py3-none-any.whl

Download URL nytimes_games-0.6.0-py3-none-any.whl
Size 45.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
75b3040d8e66f717329e7facca8fc7c6786cd93b702a5c56b729e925b9e1950b
BLAKE2b-256 checksum
How to use checksums
48f65e3bad7ea78bb8452f9352f217643881ed6680d400a4b6acd384e83e365a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release history Release notifications | RSS feed

0.11.5

2 release files

0.11.4

2 release files

0.11.3

2 release files

0.11.2

2 release files

0.11.1

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.7

2 release files

0.9.6

2 release files

0.9.5

2 release files

0.9.4

2 release files

0.9.3

2 release files

0.9.2

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.4

2 release files

0.8.3

2 release files

0.8.2

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.1

2 release files

This release

0.6.0 This release

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.2

2 release files

0.3.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page