An open-source TypeScript library for fetching real-time theme park data — wait times, schedules, and entity metadata — from 82+ destinations worldwide.
This library powers the free API at ThemeParks.wiki.
License: MIT
Requirements: Node.js 24+, npm 11+
git clone https://github.com/ThemeParks/parksapi.git
cd parksapi
npm install
touch .env # Destination config (see Configuration)
npm run dev # Test all parksMost destinations need configuration values in .env, such as an app version, a client ID or a base URL. They aren't included in this repo. See Configuration.
import {getDestinationById} from '@themeparks/parksapi';
const dest = await getDestinationById('universalorlando');
const park = new dest.DestinationClass();
const entities = await park.getEntities(); // Rides, shows, restaurants
const liveData = await park.getLiveData(); // Wait times, statuses
const schedules = await park.getSchedules(); // Operating hoursTo fetch data from the ThemeParks.wiki API (rather than running this library directly):
npm run build # Compile TypeScript
npm run dev # Test all parks
npm run dev -- <id> # Test specific park (e.g. universalorlando)
npm run dev -- --list # List all available park IDs
npm test # Run unit tests
npm run test:coverage # Coverage report
npm run health # Health check all endpointsEvery command above also runs in a container, so nothing has to be installed on the host beyond Docker (or Podman):
make build # Build the dev image once
make park PARK=efteling
make test
make # Full list of targetsmake build builds the image — the TypeScript compile is make compile.
Most destinations need configuration in .env in the repo root; the container
creates an empty one on first run, and make park PARK=efteling is one of the
few that passes without any. Dependencies install into node_modules/ on first
run and reinstall when the lockfile changes (make deps forces it).
The container serves the API only. The React admin UI is a host-side build:
run npm run web:build on the host once, and web-ui/dist is visible in the
container through the bind mount.
git is not installed in the image — commit from the host, the tree is bind-mounted.
The default engine is Docker. On a Podman host, override COMPOSE (untested):
make COMPOSE="podman-compose --env-file /dev/null --podman-run-args=--userns=keep-id" park PARK=efteling82 destinations across Disney, Universal, Cedar Fair, Six Flags, Merlin, and many more.
Some parks are served through a parent destination rather than an id of their own — Cedar Point and Knott's Berry Farm arrive under the Six Flags controller, for instance — so they are entities in the output rather than rows here.
Run npm run dev -- --list for the same list with categories.
All destinations
| Destination | ID |
|---|---|
| Alton Towers | altontowers |
| Bellewaerde | bellewaerde |
| Blackpool Pleasure Beach | blackpoolpleasurebeach |
| Bobbejaanland | bobbejaanland |
| Busch Gardens Tampa | buschgardenstampa |
| Busch Gardens Williamsburg | buschgardenswilliamsburg |
| Chessington World Of Adventures | chessingtonworldofadventures |
| Chimelong | chimelong |
| Cotaland | cotaland |
| Disneyland Paris | disneylandparis |
| Djurs Sommerland | djurssommerland |
| Dollywood | dollywood |
| Efteling | efteling |
| Energylandia | energylandia |
| Europa Park | europapark |
| Everland | everland |
| Fantawild | fantawild |
| Flamingo Land | flamingoland |
| Fuji Q Highland | fujiqhighland |
| Futuroscope | futuroscope |
| Galveston Island Waterpark | galvestonislandwaterpark |
| Gardaland | gardaland |
| Genting Skyworlds | gentingskyworlds |
| Great Escape Parks | greatescapeparks |
| Hansa Park | hansapark |
| Heide Park | heidepark |
| Hersheypark | hersheypark |
| Kennywood | kennywood |
| Kentucky Kingdom | kentuckykingdom |
| Knoebels | knoebels |
| Legoland Billund | legolandbillund |
| Legoland California | legolandcalifornia |
| Legoland Deutschland | legolanddeutschland |
| Legoland Japan | legolandjapan |
| Legoland Korea | legolandkorea |
| Legoland New York | legolandnewyork |
| Legoland Orlando | legolandorlando |
| Legoland Windsor | legolandwindsor |
| Liseberg | liseberg |
| Lotte World | lotteworld |
| Michigans Adventure | michigansadventure |
| Mid America Parks | midamericaparks |
| Mirabilandia | mirabilandia |
| Movie Park Germany | movieparkgermany |
| Movieland | movieland |
| Nigloland | nigloland |
| Ocean Park Hong Kong | oceanparkhongkong |
| Paradise Country | paradisecountry |
| Parc Asterix | parcasterix |
| Parque De Atracciones Madrid | parquedeatraccionesmadrid |
| Parque Warner Madrid | parquewarnermadrid |
| Paultons Park | paultonspark |
| Peppa Pig Theme Park Florida | peppapigthemeparkflorida |
| Phantasialand | phantasialand |
| Plopsaland | plopsaland |
| Plopsaland Deutschland | plopsalanddeutschland |
| Port Aventura World | portaventuraworld |
| Qiddiya City | qiddiyacity |
| Sea World Gold Coast | seaworldgoldcoast |
| Seaworld Orlando | seaworldorlando |
| Seaworld San Antonio | seaworldsanantonio |
| Seaworld San Diego | seaworldsandiego |
| Sesame Place Philadelphia | sesameplacephiladelphia |
| Sesame Place San Diego | sesameplacesandiego |
| Shanghai Disneyland Resort | shanghaidisneylandresort |
| Silver Dollar City | silverdollarcity |
| Six Flags | sixflags |
| Thorpe Park | thorpepark |
| Tokyo Disney Resort | tokyodisneyresort |
| Toverland | toverland |
| Universal Orlando | universalorlando |
| Universal Singapore | universalsingapore |
| Universal Studios | universalstudios |
| Universal Studios Beijing | universalstudiosbeijing |
| Universal Studios Japan | universalstudiosjapan |
| Valleyfair | valleyfair |
| Walibi Belgium | walibibelgium |
| Walibi Holland | walibiholland |
| Walibi Rhone Alpes | walibirhonealpes |
| Warner Bros Movie World | warnerbrosmovieworld |
| Wet N Wild Gold Coast | wetnwildgoldcoast |
| Worlds Of Fun | worldsoffun |
Each destination produces entities of the following types:
- Destination — A resort or group of parks (e.g., Walt Disney World Resort)
- Park — A theme park within a destination (e.g., Magic Kingdom)
- Attraction — A ride, transport, or similar experience (e.g., Pirates of the Caribbean)
- Show — A performance or parade with scheduled show times
- Restaurant — A dining location
Environment variables follow the pattern {CLASSNAME}_{PROPERTY}:
UNIVERSALORLANDO_APIKEY=your-key-here
EFTELING_APPVERSION=5.0.0
Create a .env file in the project root. Some destinations share configuration via prefixes (e.g., ATTRACTIONSIO_BASEURL applies to all Attractions.io parks).
Run npm run dev -- <id> -v to see which config properties a destination expects.
The cache lifetime of any @http or @cache method can be set the same way, as {CLASSNAME}_{METHODNAME}_CACHESECONDS:
EUROPAPARK_FETCHSEASONS_CACHESECONDS=600 # poll the seasons every 10 minutes instead of 6 hours
EFTELING_FETCHWAITTIMES_CACHESECONDS=0 # never serve wait times from the cache
HTTP_TIMEOUT_MS sets the request timeout for the whole process. The default is 30 seconds:
HTTP_TIMEOUT_MS=10000 # give up on a request after 10 seconds
The library uses a decorator-based design with TypeScript:
@destinationController— Auto-registers destinations, applies config proxy@config— Property-level config injection from env vars@http— Queue-based HTTP with retry, caching, validation@inject— Event-based dependency injection (auth headers, response transforms)@cache— SQLite-backed caching with TTL
All parks extend the Destination base class using the Template Method Pattern — implement buildEntityList(), buildLiveData(), and buildSchedules().
Swapping the HTTP layer: setHttpTransport() puts a function between the @http queue and the network. It receives every attempt — the request as it is about to go out (after the injectors, with the default user-agent and accept-encoding, and with the body encoded as it is sent), who makes it (class, instance, method, arguments, retry count) and a send function — and returns a Response. Call send to record what the parks answer (read the body from response.clone(), and redact the secrets the request carries before storing it), or answer yourself to replay a recording or to test a destination without the network. Only an error from send, rethrown as is, is retried. An error the transport raises itself fails the request at once as an HttpTransportError. setHttpTransport(null) restores the default. A request served from the HTTP cache never reaches the transport.
setHttpCacheObserver() reports those cache hits instead: the request, its caller, the cached body and when it expires. The request carries the auth headers the injectors added and, behind a scraping proxy, the rewritten URL with the proxy's key and the forwarded headers, so redact it before storing it, as with the transport. In both hooks the caller's arguments can be credentials, since a sign-in method is called with them.
Three limits of both hooks: a result a park serves from its own cache (a @cache method, a CacheLib.wrap call) makes no HTTP request, so neither the transport nor the HTTP cache observer sees it. A recording of requests that carry today's date, as an argument or in the URL (calendars, schedules), only replays with the clock pinned to the time of the recording. And whatever a replay transport returns is cached like a network response, so a replay run needs its own CACHE_DB_PATH.
setMethodCacheObserver() reports what the first limit hides: every call a @cache method or CacheLib.wrap() serves from a stored result, with the cache key, its caller (class, instance, method, arguments) and when the entry expires. A miss runs the method and is not reported, nor is a call that waits for a concurrent miss of the same key. The cached value is left out, since for a sign-in method it is a token or credentials. The arguments and the key, built from the arguments by default and from config by some parks, can carry secrets, so redact them before storing anything.
See CLAUDE.md for full architecture documentation.
Contributions are welcome. To add a new destination:
- Create
src/parks/<name>/<name>.tsextendingDestination - Implement entity, live data, and schedule methods
- Test with
npm run dev -- <id> - Submit a PR
See CLAUDE.md and .claude/skills/implementing-parks.md for detailed implementation guidance.
General support is available for the ThemeParks.wiki API. This source code is self-service (sponsors get support benefits).