Skip to main content

atlantic-games

Test License: MIT

An unofficial Python client for The Atlantic's games: Bracket City, the Crossword, Caleb's Inferno and Rabbithole, plus the archives of Atlantic Trivia and Stacks, and your own saved games and stats.

The Atlantic doesn't publish documentation for these. This package wraps them in one client, sync and async, with typed Pydantic models. Optional extras add the atlg command line tool, an MCP server for AI agents, and a REST API. It's the sibling of nytimes-games and works the same way.

The crosswords are hosted by Amuse Labs' PuzzleMe, which does a great job of putting puzzles in front of more people on more sites. Thanks to them.

Installation

pip install atlantic-games

The package installs as atlantic-games and is imported as atlgames. Python 3.10 or newer is required.

Quick start

from atlgames import AtlanticGamesClient

client = AtlanticGamesClient()

client.bracket_city("2026-10-08").solved_text   # "Raytheon patents the microwave"
client.crossword("2026-10-10").entries()         # clues, answers, crossings
client.crossword(series="inferno")               # the latest Caleb's Inferno
client.rabbithole().questions                    # the latest Rabbithole chain

The async client has the same methods:

from atlgames import AsyncAtlanticGamesClient

async with AsyncAtlanticGamesClient() as client:
    puzzle = await client.bracket_city()

Your saved games need your Atlantic login cookie:

from atlgames.stats import bracket_city_stats

client = AtlanticGamesClient(cookies="atljwt6=...")

client.bracket_city_game("2026-10-11").data.totalKeystrokes
bracket_city_stats(client.bracket_city_games()).longest_streak

What's available

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

Puzzles

Game Methods Available Spoilers
Bracket City bracket_city(date=None), bracket_city_dates() 2025-01-01, daily solutions, solved_text
Crossword crossword(date=None, puzzle_id=None), crosswords(date_start, date_end, limit) 2018-09-24, daily the grid (box) and placedWords answers
Caleb's Inferno the same, with series="inferno" 2022 to 2026-06, monthly as for the Crossword
Rabbithole rabbithole(puzzle_id=None), rabbithole_puzzles(date_start, date_end) 2026-08-12, weekdays canonicalAnswer, validAnswers
Atlantic Trivia trivia(article), trivia_articles(limit) 2025-10-03 to 2026-08-14 (ended) answers, hints and explanations
Stacks stacks(date), stacks_puzzles() 2025-06-17 to 2026-08-24 (ended) solution
Games hub games(), game(slug)

Dates are YYYY-MM-DD strings (or datetime.date) in New York time, which is when the puzzles change. With no date you get the latest puzzle. Unpublished puzzles aren't available early.

Data Method What you get
Account client.account Your user ID, when your login expires and your subscription flags, read from the cookies (no request)
Bracket City bracket_city_game(date), bracket_city_games(date_start, date_end) Solved clues, keystrokes against the minimum, wrong guesses, peeks, whether you solved it on the day
Rabbithole rabbithole_game(puzzle), rabbithole_games(date_start, date_end) Each question's result and your score
Crossword crossword_play(puzzle_id, series) Your saved play from Amuse Labs: time, score, correct entries, checks and reveals
Any game game_state(slug, date, id), game_states(keys) The raw saved game, 25 per request
Stats atlgames.stats.bracket_city_stats(games), rabbithole_stats(games) Streaks, completion, keystroke efficiency, perfect and clean solves, scores

The Atlantic has no stats endpoint, so stats are computed from your saved games. Some things to know about saved games:

  • Old games may not be there yet. The mobile app keeps your history on the phone and only uploads a puzzle when you open it while logged in. Open old dates in the app to bring them into your account.
  • They're snapshots. The server keeps only the latest state of each game, and it can go backward: the app's "reset puzzle" button, replaying, or opening a date can replace a finished game with an empty one. Each result has fetched_at; keep your own copies if your history matters to you.
  • solvedOnPubDate was only recorded from about August 2025, so None means unknown, not late.

The library is read-only. It never writes saved games.

Puzzle structure

puzzle = client.bracket_city("2026-10-11")

puzzle.clues()          # every clue: its text, answer, depth and the clues inside it
puzzle.available()      # the clues you can solve now
puzzle.render(["your + my", "ghost's exclamation"])   # the text with those clues solved
puzzle.steps()          # an order that solves it, innermost first
puzzle.solved_text      # the final text the game shows
puzzle.caption_matches  # False for the ~1 in 30 puzzles whose puzzleSolution differs

crossword = client.crossword("2026-10-10")
crossword.grid()        # rows of letters, None for black squares
crossword.entries()     # "1-Across": clue, answer, (row, col) squares, crossings
crossword.squares()

question = client.rabbithole().questions[0]
question.accepts("mark zuckerburg")   # Rabbithole's fuzzy answer matching

client.stacks("2025-06-17").rows()    # the solved Stacks board

Crossword files

Export crosswords to the formats other crossword apps use:

from atlgames import formats

puzzle = client.crossword("2026-10-10")
open("atlantic.puz", "wb").write(formats.to_puz(puzzle))   # Across Lite
formats.to_ipuz(puzzle)                                     # ipuz, as a dict
formats.to_xml(puzzle)                                      # Crossword Compiler XML
formats.export(puzzle, "ipuz")                              # any format, as bytes
formats.fidelity(puzzle, "puz")                             # what the format approximates

Clue formatting such as italics is dropped. Puzzles a format can't represent raise AtlanticGamesExportError with the reasons. Exported files are for personal use: the puzzles are The Atlantic's.

Cookies

Log in at theatlantic.com, open your browser's developer tools, and copy the atljwt6 cookie for .theatlantic.com (Application tab in Chrome, Storage tab in Firefox). It's httpOnly, so scripts on the page can't read it. Treat it like a password. It lasts 30 days; the site renews it as you browse, so you'll need to copy a fresh one about once a month.

cookies can be a Cookie header string, a dict, a Cookie-Editor JSON export (as a list or a JSON string), or the bare atljwt6 token. Only atljwt6 is needed; atljwt adds your subscription flags to account.

Cookies are only ever sent to The Atlantic's API, never to Amuse Labs or the puzzle file servers, and they never appear in errors or logs.

Your crossword progress is stored by Amuse Labs under your Atlantic user ID. That ID is read from your own cookie; the client has no way to ask for anyone else's.

Errors

Exception When
AtlanticGamesNotFoundError No puzzle for that date or ID, or not published yet
AtlanticGamesAuthenticationError Your data was requested without a valid atljwt6 cookie
AtlanticGamesRateLimitError 429 after retrying; retry_after has the suggested wait
AtlanticGamesGraphQLError The Atlantic's API returned other errors
AtlanticGamesHTTPError Any other HTTP error (the base of the above)
AtlanticGamesParseError A page didn't have the expected data, e.g. Amuse Labs changed its format
AtlanticGamesExportError A crossword can't be saved in a file format

Failed connections, rate limits and server errors are retried 3 times with exponential backoff, honoring Retry-After. Adjust with AtlanticGamesClient(retries=5, backoff=1.0, timeout=60), or pass your own httpx.Client / httpx.AsyncClient as http_client.

Command line

The cli extra installs atlg:

pip install "atlantic-games[cli]"

atlg bracket-city              # today's puzzle, no spoilers
atlg bracket-city 2026-10-08 --steps -a
atlg crossword yesterday --save crossword.puz
atlg crossword --series inferno
atlg rabbithole -a
atlg trivia last
atlg stacks 2025-06-17 -a
atlg list crossword --from 2026-10-01
atlg play bracket-city         # play in the terminal (nothing is saved to your account)
atlg play rabbithole

Answers are hidden unless you pass --answers / -a. Every command takes --format json|yaml|csv|table|value(FIELD,...), and dates can be YYYY-MM-DD, today, yesterday, a weekday name, first or last.

Your stats and history

atlg auth login --from-file cookies.json   # a Cookie-Editor export, or paste atljwt6 when prompted
atlg auth status
atlg today
atlg stats
atlg history bracket-city --from 2026-01-01

Cookies are stored in ~/.config/atlg/config.ini (mode 0600), with profiles for more than one account (--profile, atlg config profiles). ATLANTIC_COOKIES overrides the stored login.

Archiving

atlg archive bracket-city --from first --to today -o archive
atlg archive crossword --from 2026-01-01 -o archive --as puz

Archives write one file per date with a manifest, and resume where they left off.

MCP server for AI agents

The mcp extra installs atlg-mcp, a local Model Context Protocol server, so agents can play along: ask for a Bracket City nudge, check a Rabbithole answer, or export today's crossword.

# Claude Code
claude mcp add atlantic-games -- uvx --from "atlantic-games[mcp]" atlg-mcp

For other clients, add a stdio server with the command uvx and the arguments --from atlantic-games[mcp] atlg-mcp.

Tools What they do
bracket_city, bracket_city_peek, check_bracket_city_answer The puzzle with the clues you can solve now, peeks, and answer checks
crossword, check_crossword_answer, crossword_archive Grids and entries with clues, lengths and crossings
rabbithole, check_rabbithole_answer, rabbithole_archive One question at a time, with hints and choices on request
trivia, check_trivia_answer, trivia_archive, stacks, games The Trivia and Stacks archives, and the games hub
account, bracket_city_history, bracket_city_stats, rabbithole_history, rabbithole_stats, crossword_progress Your data (need cookies)
export_crossword Save a crossword as .puz, .ipuz or .xml
  • Answers are hidden unless the agent asks for them, and the server tells agents to leave them hidden while you're solving.
  • Your data uses the same login as atlg (atlg auth login, or ATLANTIC_COOKIES in the server's environment).
  • Every tool is read-only except export_crossword, which only writes the file you ask for.

REST API

The api extra adds atlgames.api, a FastAPI app with every puzzle, your saved games and stats, and crossword downloads:

pip install "atlantic-games[api]"
uvicorn atlgames.api:app

Open /docs for the full list. A few routes:

Route Returns
GET /bracket-city/{date} A Bracket City puzzle
GET /crosswords/{daily|inferno}/{date} A crossword
GET /crosswords/{series}/{date}/download?format=puz A crossword file
GET /rabbithole/latest The latest Rabbithole
GET /bracket-city/stats Your stats (send your atljwt6 cookie)

Requests use the atljwt6 and atljwt cookies they're sent with; no other cookies are passed on. Mount atlgames.api.router in your own app, or start from examples/api for a Docker container.

How it works

The Atlantic's games come from four places, none of which need a login for puzzles:

  • Bracket City puzzles are JSON files on CloudFront.
  • Crosswords come from Amuse Labs' PuzzleMe pages. Their puzzle data is lightly scrambled; the client unscrambles it and, if Amuse Labs changes the scramble, reads the new one from their current JavaScript.
  • Rabbithole, Trivia, the games hub and your saved games come from The Atlantic's GraphQL API.
  • Stacks ended, and all its puzzles ship inside the game's own script.

docs/endpoints.md has the details: endpoints, schemas and quirks.

Contributing

See CONTRIBUTING.md. A daily live check catches upstream changes.

License

MIT. This project isn't affiliated with The Atlantic or Amuse Labs. The puzzles belong to The Atlantic and their constructors.

Metadata

Release files for atlantic-games 0.1.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 atlantic-games 0.1.0
File Size Uploaded
atlantic_games-0.1.0.tar.gz 115.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for atlantic-games 0.1.0
File Interpreter ABI Platform
atlantic_games-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 203.8 kB

Release files / atlantic_games-0.1.0.tar.gz

Download URL atlantic_games-0.1.0.tar.gz
Size 115.3 kB
Tags Source
SHA-256 checksum
How to use checksums
dbf23e9c98f5aa7afb68cfa8a58d43943446934a3dbc2350e23b2bff3e9d08be
BLAKE2b-256 checksum
How to use checksums
bb03056a2bb7bf9256c126d192b579cdc8b596bf5cfb07126226f26f5a888238
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 11, 2026.

Transparency log

Release files / atlantic_games-0.1.0-py3-none-any.whl

Download URL atlantic_games-0.1.0-py3-none-any.whl
Size 88.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7af578f94dd90b0c7080b4ff4432662ddb20e42f7143e5d9fa285c2a35ec392d
BLAKE2b-256 checksum
How to use checksums
eb703f6ee46551774981a105b0dfab178862b7c17b57e715cf2195f2dd4268d3
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 11, 2026.

Transparency log

Release history Release notifications | RSS feed

0.4.5

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

This release

0.1.0 This release

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