Cookbook¶
Three complete recipes you can copy, paste, and run. Each one uses real entity IDs from the live ThemeParks.wiki API.
Recipe 1 — Wait times in order (longest → shortest)¶
Pull the live data for Magic Kingdom, keep only the rides that are reporting a wait time, and print them sorted from longest to shortest queue.
from themeparks import ThemeParks, current_wait_time
MAGIC_KINGDOM = "75ea578a-adc8-4116-a54d-dccb60765ef9"
with ThemeParks() as tp:
live = tp.entity(MAGIC_KINGDOM).live()
waits = [
(entry.name, current_wait_time(entry))
for entry in live.liveData or []
]
waits = [(name, w) for name, w in waits if w is not None]
waits.sort(key=lambda pair: pair[1], reverse=True)
for name, wait in waits:
print(f"{wait:>3d} min {name}")
Sample output:
90 min Seven Dwarfs Mine Train
75 min TRON Lightcycle / Run
65 min Space Mountain
55 min Peter Pan's Flight
45 min Big Thunder Mountain Railroad
40 min Jungle Cruise
35 min Haunted Mansion
...
current_wait_time returns None for entities that don't have a STANDBY
queue right now (closed rides, shows, restaurants), which is why we filter
those out before sorting.
Recipe 2 — Schedule for the next 7 days¶
Use schedule.range(start, end) to pull every schedule entry for a 7-day
window. A single date can have multiple entries — regular operating hours,
EXTRA_HOURS (early entry / extended evening), and TICKETED_EVENT (after-hours
events). range() returns them all in chronological order.
from datetime import date, timedelta
from themeparks import ThemeParks
MAGIC_KINGDOM = "75ea578a-adc8-4116-a54d-dccb60765ef9"
with ThemeParks() as tp:
today = date.today()
entries = tp.entity(MAGIC_KINGDOM).schedule.range(today, today + timedelta(days=7))
for entry in entries:
if entry.type == "OPERATING":
print(f"{entry.date} {entry.openingTime} → {entry.closingTime} ({entry.type})")
else:
print(f"{entry.date} {entry.type}")
Sample output:
2026-04-15 2026-04-15T09:00:00-04:00 → 2026-04-15T22:00:00-04:00 (OPERATING)
2026-04-15 2026-04-15T17:00:00-04:00 → 2026-04-15T19:00:00-04:00 (TICKETED_EVENT)
2026-04-16 2026-04-16T09:00:00-04:00 → 2026-04-16T23:00:00-04:00 (OPERATING)
2026-04-17 2026-04-17T08:30:00-04:00 → 2026-04-17T09:00:00-04:00 (EXTRA_HOURS)
2026-04-17 2026-04-17T09:00:00-04:00 → 2026-04-17T22:00:00-04:00 (OPERATING)
...
Recipe 3 — All entity geo-locations, grouped by type¶
entity(destination_id).walk() enumerates every descendant of a destination
(parks, attractions, restaurants, hotels, shows). Group the ones with known
coordinates by entityType:
One API call. The
/childrenendpoint returns the entire descendant tree in a single response, so even for the largest destinations this is one HTTP request.
from collections import defaultdict
from themeparks import ThemeParks
WALT_DISNEY_WORLD = "e957da41-3552-4cf6-b636-5babc5cbc4e5"
by_type: dict[str, list[tuple[str, float, float]]] = defaultdict(list)
with ThemeParks() as tp:
for child in tp.entity(WALT_DISNEY_WORLD).walk():
loc = child.location
if loc is None or loc.latitude is None or loc.longitude is None:
continue
by_type[child.entityType.value].append((child.name, loc.latitude, loc.longitude))
for entity_type, items in sorted(by_type.items()):
print(f"\n{entity_type} ({len(items)})")
print("=" * 40)
for name, lat, lng in sorted(items):
print(f" {lat:>10.6f}, {lng:>11.6f} {name}")
entityType is a pydantic enum — call .value to get the string name.
Sample output:
ATTRACTION (78)
========================================
28.418250, -81.581417 Astro Orbiter
28.420278, -81.583944 Big Thunder Mountain Railroad
...
HOTEL (33)
========================================
28.371333, -81.555111 Disney's All-Star Movies Resort
...
PARK (4)
========================================
28.385233, -81.563867 Disney's Animal Kingdom Theme Park
...
RESTAURANT (218)
========================================
...
Async variant¶
The async client exposes the same walk() method as an async iterator. Use
async for inside an async def:
import asyncio
from collections import defaultdict
from themeparks import AsyncThemeParks
WALT_DISNEY_WORLD = "e957da41-3552-4cf6-b636-5babc5cbc4e5"
async def main() -> None:
by_type: dict[str, list[tuple[str, float, float]]] = defaultdict(list)
async with AsyncThemeParks() as tp:
async for child in tp.entity(WALT_DISNEY_WORLD).walk():
loc = child.location
if loc is None or loc.latitude is None or loc.longitude is None:
continue
by_type[child.entityType.value].append(
(child.name, loc.latitude, loc.longitude)
)
# ... same printing as above
asyncio.run(main())
Recipe 4 — See every HTTP request the SDK makes¶
The SDK is built on httpx, which has a built-in logger. Enable it before
constructing the client to see every outbound request and response status
in real time:
import logging
logging.basicConfig(level=logging.INFO)
logging.getLogger("httpx").setLevel(logging.DEBUG)
from themeparks import ThemeParks
with ThemeParks() as tp:
tp.destinations.list()
tp.entity("75ea578a-adc8-4116-a54d-dccb60765ef9").live()
Output:
INFO httpx HTTP Request: GET https://api.themeparks.wiki/v1/destinations "HTTP/1.1 200 OK"
INFO httpx HTTP Request: GET https://api.themeparks.wiki/v1/entity/75ea578a-adc8-4116-a54d-dccb60765ef9/live "HTTP/1.1 200 OK"
For raw byte-level traces (TLS handshake, header bytes, retries, connection
reuse) also enable the httpcore logger:
Tip: requests served from the in-memory cache do not appear in httpx
logs — they are returned before the transport is touched. While debugging,
pass cache=False to force every call to hit the network:
Recipe 5 — Read every queue variant, not just standby¶
An attraction can expose more than one queue type at the same time — a classic Disney ride often has STANDBY plus PAID_RETURN_TIME (Lightning Lane) plus SINGLE_RIDER. The full set of variants is:
| Variant | Use case |
|---|---|
STANDBY |
Regular wait line |
SINGLE_RIDER |
Single-rider line wait |
PAID_STANDBY |
Paid express line wait |
RETURN_TIME |
Virtual queue (free) |
PAID_RETURN_TIME |
Lightning Lane / paid return time + price |
BOARDING_GROUP |
Boarding-group rides (Rise of the Resistance, TRON) |
Print all populated queue variants for every attraction at Magic Kingdom:
from themeparks import ThemeParks
MAGIC_KINGDOM = "75ea578a-adc8-4116-a54d-dccb60765ef9"
with ThemeParks() as tp:
live = tp.entity(MAGIC_KINGDOM).live()
for entry in live.liveData or []:
if entry.queue is None:
continue
if entry.queue.STANDBY and entry.queue.STANDBY.waitTime is not None:
print(f"{entry.name:40s} STANDBY {entry.queue.STANDBY.waitTime} min")
if entry.queue.SINGLE_RIDER and entry.queue.SINGLE_RIDER.waitTime is not None:
print(f"{entry.name:40s} SINGLE_RIDER {entry.queue.SINGLE_RIDER.waitTime} min")
if entry.queue.PAID_RETURN_TIME:
prt = entry.queue.PAID_RETURN_TIME
price = prt.price.formatted if prt.price else "?"
print(f"{entry.name:40s} LIGHTNING LANE {price}, return {prt.returnStart} → {prt.returnEnd}")
if entry.queue.RETURN_TIME:
rt = entry.queue.RETURN_TIME
print(f"{entry.name:40s} VIRTUAL QUEUE {rt.returnStart} → {rt.returnEnd} ({rt.state})")
if entry.queue.BOARDING_GROUP:
bg = entry.queue.BOARDING_GROUP
print(
f"{entry.name:40s} BOARDING GROUP {bg.currentGroupStart}–{bg.currentGroupEnd}, "
f"~{bg.estimatedWait} min, status {bg.allocationStatus}"
)
if entry.queue.PAID_STANDBY and entry.queue.PAID_STANDBY.waitTime is not None:
print(f"{entry.name:40s} PAID_STANDBY {entry.queue.PAID_STANDBY.waitTime} min")
Sample output:
Big Thunder Mountain Railroad STANDBY 45 min
Big Thunder Mountain Railroad LIGHTNING LANE $15.00, return 2026-04-15T14:30:00-04:00 → 2026-04-15T15:30:00-04:00
Pirates of the Caribbean STANDBY 20 min
TRON Lightcycle / Run BOARDING GROUP 38–41, ~25 min, status AVAILABLE
TRON Lightcycle / Run LIGHTNING LANE $20.00, return 2026-04-15T15:00:00-04:00 → 2026-04-15T16:00:00-04:00
...
Generic alternative¶
If branching on every variant is too verbose, iter_queues(entry) flattens
all populated variants into one sequence of dicts:
from themeparks import ThemeParks, iter_queues
with ThemeParks() as tp:
live = tp.entity(MAGIC_KINGDOM).live()
for entry in live.liveData or []:
for q in iter_queues(entry):
# q is e.g. {"type": "STANDBY", "waitTime": 45}
# or {"type": "PAID_RETURN_TIME", "state": "AVAILABLE", "price": {...}, ...}
print(entry.name, q["type"], q)