ThemeParks.wiki API

A free REST API for live theme park wait times, ride status, showtimes, opening hours and years of recorded history, covering hundreds of parks worldwide.

What the ThemeParks.wiki API does

The ThemeParks.wiki API returns live theme park wait times, ride status, showtimes, restaurant availability, opening hours and historical data for hundreds of parks worldwide. Responses are JSON. The base URL is https://api.themeparks.wiki.

The API is free to use, including in commercial projects. Live data, opening hours and the park directory need no API key. If your product shows the data to its users, display a visible "Powered by ThemeParks.wiki" credit. Paid plans remove that requirement. The Terms & Acceptable Use set out what is allowed: you may build any product on the data, but you may not pass it on as data for other software to consume.

Live wait times

One request returns every ride, show and restaurant in a park, with its current wait time and status.

curl https://api.themeparks.wiki/v1/entity/75ea578a-adc8-4116-a54d-dccb60765ef9/live

That example is Magic Kingdom Park at Walt Disney World Resort. Replace the id with any park, resort or single attraction.

Finding park and ride IDs

Every destination, park, attraction, show and restaurant is an entity with a UUID. Start at the destination list and walk down.

curl https://api.themeparks.wiki/v1/destinations

GET /v1/entity/{id}/children returns what is inside an entity. Asking about a DESTINATION returns every entity in that destination, and asking about a PARK returns every entity in that park. Both return the whole subtree rather than one level. Every other entity type returns its direct children only. Rebuild the hierarchy from each child's parentId.

GET /v1/entity/{id} returns one entity on its own. The id may be a UUID, a URL slug, or, for a destination, its upstream external id.

Park opening hours

GET /v1/entity/{id}/schedule returns opening hours for the next 30 days in the park's own timezone, including extra hours and ticketed events.

curl https://api.themeparks.wiki/v1/entity/75ea578a-adc8-4116-a54d-dccb60765ef9/schedule

For a specific month, including a past one, use GET /v1/entity/{id}/schedule/{year}/{month}. The month is two digits, so /2026/09 is valid and /2026/9 returns 400. Days the park has not published are absent from the response rather than marked closed.

Historical wait time data

The history endpoints return what wait times and ride status were, either as every recorded change through a day or as one summary row per day. Historical data is what the paid plans buy.

Both history endpoints answer a whole park in one request when given a park id, returning an entities array with one entry per entity of the park. Asking park by park rather than ride by ride is the difference between 124 requests and 15,128 for five years of one resort.

Dates are park-local calendar days. A request for 2026-09-15 means that date at the park, in the park's timezone.

opening is the state the requested range starts in. opening.time is the start of the range you asked for and opening.observedAt is when that state was last actually observed. Values are carried forward at any age, so a day with no recorded data still reports a state. Check observedAt before charting it.

How many days one call serves. There are four answers, not one.
CallDays per call
GET /history, one entity31 days
GET /history, a whole parkOne day. A park day is every change for a few hundred rides
GET /history/daily, one entity3,660 days (about ten years), never paged
GET /history/daily, a whole park31 days per page; next carries the rest
How far back history reaches, and the hourly history budget, per plan.
PlanReaches backHistory requests
No API key7 days60 an hour
Free30 days600 an hour
Pro400 days1,200 an hour
Businessthe full archive3,000 an hour
Enterprisethe full archiveunmetered

History requests are metered by a separate hourly budget, independent of the per-minute request limit. Exceeding it returns HTTP 429 with a HISTORY_RATE_LIMITED error body and a retryAfter value in seconds. A 429 is a rate limit, not an empty result: check the response status before reading the body. Requesting history deeper than your plan allows returns HTTP 403 with the earliest date you may request. Per-park coverage is published at themeparks.wiki/coverage.

How to download historical wait time data

Getting the archive into your own store is one loop over a paged endpoint. The official libraries do that loop; the steps below are what it has to get right either way.

Using a library

Install with pip install themeparks for Python or npm install themeparks for JavaScript. Installing either also puts a themeparks-backfill command on your path, and for the common job — get everything we hold into a file — that is the whole thing:

themeparks-backfill --list disney            # finding a park needs no key
export THEMEPARKS_API_KEY=tpw_your_key       # how far back it reaches is your plan
themeparks-backfill "magic kingdom" --format csv --out ./data

Set the key before the second command. Without one it still runs, on the seven days anonymous access allows, and exits successfully — so a key you meant to set and did not is a short file rather than an error.

It asks the API how far back your plan reaches and starts there, writes one file per park named for the park's id, and puts parkId, parkName, entityId, entityName and entityType on every row. If the hourly history budget runs out it records where it got to and exits 75, so a timer retries and the same command carries on. The CSV is byte-for-byte identical from either library.

To own the loop instead, each library exposes entity(id).history with three calls: span() for the date range available to you, days() for one summary row per park-local day, and changes() for every recorded change.

from themeparks import ThemeParks, APIError

with ThemeParks(api_key=YOUR_KEY) as tp:
    history = tp.entity(PARK_ID).history
    span = history.span()

    def write(first_day):
        for ref, row in history.days_with_entities(first_day, span.retrievable_through):
            store(ref, row)

    try:
        write(span.archive_from)
    except APIError as exc:
        # Your plan may not reach the archive's first day. The 403 names the day
        # you may start from, so start there rather than guessing.
        body = exc.body.get("error", {})
        if body.get("type") != "HISTORY_WINDOW_EXCEEDED":
            raise
        write(body["earliestAllowedDate"])

The equivalent in JavaScript is for await (const { entityId, row } of history.days({ from, to })). Both page automatically and yield rows as they arrive, so a resort's five years never has to fit in memory.

Three things to get right

Keeping a database current after the backfill

The archive is written two to three days behind live data, so a nightly job that asks only for yesterday will miss days that land late. Ask for the last seven days on every run and upsert on entity and date. It costs one request per park. A row for today is partial by design: operatingMinutes counts only the minutes already elapsed, so it grows through the day and is final once the day ends.

Absent days are not zero

A day with no data has no row at all, and the standby statistics are omitted rather than null when an entity published no numeric wait. That is deliberate: a row of zeroes would be a different claim, meaning observed and closed all day. Filling the gaps with zeroes before training on the data teaches a model that queues vanish on the days nobody was recording.

Running out of the hourly budget

History requests are metered hourly, separately from the per-minute limit, so a full backfill will exhaust the budget and the server may ask you to wait most of an hour. Both libraries refuse to sleep through a wait that long: past two minutes they raise BudgetExhaustedError, carrying the seconds the server asked for, so a backfill can record the last day it wrote and resume rather than appearing to hang. Re-read that last day on resume, because a page can end partway through a day.

Resume from the day the server's next URL starts on, never from the newest row you wrote: an entity that stopped reporting has no rows for the tail days of its page, so the newest row is earlier than the page covered and resuming there re-downloads days you already hold. themeparks-backfill does this for you.

Authentication

Live data, opening hours and the entity tree need no API key. An API key raises your request allowance and reaches further back into history. Generate one from your ThemeParks.wiki profile and send it in the x-api-key request header.

curl -H "x-api-key: YOUR_KEY" https://api.themeparks.wiki/v1/destinations

Keys are shown once when generated. The server stores only a one-way hash.

Rate limits

Endpoints

Every path is relative to https://api.themeparks.wiki.

EndpointReturns
/v1/destinationsEvery destination we cover, with its parks
/v1/entity/{id}One entity: a destination, park, attraction, restaurant or show
/v1/entity/{id}/childrenEverything inside an entity: a park's rides, a destination's parks
/v1/entity/{id}/liveWait times, status and showtimes as they are right now
/v1/entity/{id}/scheduleOpening hours for the next 30 days
/v1/entity/{id}/schedule/{year}/{month}Opening hours for one specific month
/v1/entity/{id}/historyHow wait times and status changed over a day, one row per change
/v1/entity/{id}/history/dailyOne row per day: operating minutes, and wait time min/median/mean/p90/max
/v1/entity/{id}/history/coverageHow far back history goes for this entity, field by field

Client libraries and specification

Frequently asked questions

Is the ThemeParks.wiki API free?

Yes. Live wait times, ride status, showtimes and opening hours are free to use, including in commercial products, and need no API key. Paid plans add deeper historical data, higher request limits and the websocket feed.

Do I need an API key for theme park wait times?

No. Live wait times require no API key. A free API key raises your request allowance and extends how far back you can read history, currently to 30 days from 7 days without one.

Which theme parks does the API cover?

Hundreds of parks worldwide, including Walt Disney World Resort, Disneyland Resort, Universal, Six Flags, Cedar Fair, Merlin and many independent operators. GET /v1/destinations returns the full current list.

How often is the wait time data updated?

Wait times are collected continuously and responses are cached for 60 seconds. Requesting live data more than once a minute per park returns the same response.

How far back does the historical data go?

It varies by park, and the earliest records date from 2021. GET /v1/entity/{id}/history/coverage reports exactly what is held for one entity, and themeparks.wiki/coverage publishes the same per park.

How do I download the full history for a park?

Install the official Python or JavaScript library (pip install themeparks, or npm install themeparks) and iterate entity(parkId).history.days() between the dates span() reports. Give it a park id rather than a ride id: one request then answers every entity in the park, which is 124 requests for five years of Disneyland Resort instead of 15,128. The library follows the paging links and handles the hourly history budget for you.

Why does my history backfill stop after 31 days?

A park daily request serves at most 31 park-local days per page and returns a next field holding an absolute URL for the following page. Follow next until it is null. Both official libraries do this automatically; a hand-written loop that reads only the first response gets one month of the archive and no error.

Can I republish or resell ThemeParks.wiki data?

No. You may build any product on the data, including a paid one, but you may not re-serve it as a data feed or API of your own, or let your users bulk-export it out of your product. Downloading it for your own use is fine.