Originally posted on my personal site
In April of 2022, we took our family to Disney World for the first time. We were excited, the kids were excited, and everything was looking up. I planned everything 6 months in advance booking lodging, plane tickets and a rental vehicle. Everything except Disney World tickets. My thinking was that in the unlikely event of a sale, I could save some hard-earned cash.
I felt like I had everything figured out.
I was the smartest person because I had thought of everything.
What I wasn't aware of though, was the new ✨park reservation system✨.
The Reservation System
If I had done a little more research, I would have found out that starting in 2020, as a response to the pandemic, Disney put a reservation system in place for their parks. Meaning that they now limit the amount of people in each park each day. When you buy your tickets, you also have to reserve your spot in the park you want to go to. This allows them to keep numbers down for their parks and probably also makes it a little easier to manage other things like staffing.
So, when I went to buy our tickets, I was surprised and disappointed to find out that the only park that wasn't completely booked for the 2 days we had scheduled, was EPCOT.
Don't get me wrong, EPCOT is a really cool! There's lots of great stuff there, but I knew our 4 young kids (and us two parents) would be disappointed with not being able to see the castle and other cool parts of the Magic Kingdom. After talking about it with my incredibly patient and forgiving partner, we decided to just go with the flow and do 2 days at EPCOT.
But I wasn't satisfied. I needed to right my wrongs. I started to wonder if I could put my skills to use get us into the Magic Kingdom.
Pondering
Disney has a page on their site that shows the reservation availability, which is what I used to find out that only EPCOT was available. When I was on the phone talking to a representative buying tickets, they mentioned that sometimes people cancel and you can grab that reservation. I asked how often that happens and they told me that it's rare, but if you watch that reservation availability page, you might get lucky.
Starting two weeks before our Disney World visit, I checked this page nearly every chance I got every single day. It became an all-consuming task. I really wanted to pick up that cancelled reservation before someone else snagged it. That's when I decided to automate the process.
Time For Some Recon
Looking at the calendar, I realized that when I clicked to the next month, it was probably grabbing data from their server to show what was available. Checking the Network tab in the inspector tools confirmed this.
The response is a JSON object with all the dates, and for each date, what parks had reservations available. Taking a look at the URL being used to fetch this data, I noticed it had very simple arguments.
https://disneyworld.disney.go.com/availability-calendar/api/calendar?segment=tickets&startDate=2022-05-01&endDate=2022-05-31
-
segment
- Can beticket
,resort
, orpassholder
. We wantticket
to get the ticket data. -
startDate
- The start date of the range of data you want. -
endDate
- The end date of the range of data you want.
Simple!
So if we want to look at what might be available in the third week of May (15th through 21st), we can use this URL:
https://disneyworld.disney.go.com/availability-calendar/api/calendar?segment=tickets&startDate=2022-05-15&endDate=2022-05-21
And we get the following data:
[
{
"date": "2022-05-15",
"availability": "full",
"parks": [
"80007944",
"80007823",
"80007998",
"80007838"
]
},
{
"date": "2022-05-16",
"availability": "partial",
"parks": [
"80007823"
]
},
{
"date": "2022-05-17",
"availability": "partial",
"parks": [
"80007823",
"80007838"
]
},
{
"date": "2022-05-18",
"availability": "partial",
"parks": [
"80007823"
]
},
{
"date": "2022-05-19",
"availability": "partial",
"parks": [
"80007823"
]
},
{
"date": "2022-05-20",
"availability": "partial",
"parks": [
"80007823",
"80007838"
]
},
{
"date": "2022-05-21",
"availability": "full",
"parks": [
"80007944",
"80007823",
"80007998",
"80007838"
]
}
]
The availability variable is pretty obvious. It just tells us if there is availability or not that day. It has three states - none, partial, and full. The parks array shows us what parks are available, but instead of names, we get some sort of ID for each park. This took a little work to figure out, but looking between the website and the JSON data, I was able to determine which ID represented what park.
80007823 = Animal Kingdom
80007838 = EPCOT
80007944 = Magic Kingdom
80007998 = Hollywood Studios
With all this information gathered, it was time to start putting it to use.
Let's Get Coding
First, I decided on a few tools to get this automation in place. I'm using the free tiers for all the services, so they didn't cost me a penny 💅
- Python - Usually my language (weapon) of choice, especially for automation.
- Requests - If you have ever used Python, you have probably used this library. It allows you to send and receive requests and responses using HTTP.
- Google Cloud Functions - Used to run our code on a schedule.
- Twilio Messaging - To send ourselves a text message alert if the Magic Kingdom becomes available!
Let's start with how we receive our data. Here we're using Requests. Here's our code, with comments to explain.
import requests
# Set our variables for the request we want to make
base_url = 'https://disneyworld.disney.go.com/availability-calendar/api/calendar'
start_date = '2022-05-15'
end_date = '2022-05-21'
# Add a header so that the request looks legit
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:98.0) Gecko/20100101 Firefox/98.0',
}
# Set our URL parameters to get the data we want
params = {
'segment': 'tickets',
'startDate': start_date,
'endDate': end_date,
}
# Using the above data, make our request, and get our response
response = requests.get(
base_url,
headers=headers,
params=params,
)
# Convert the data from a JSON string to a python dictionary
data = response.json()
That was fairly painless. Now that we have the data we need, let's use it.
# Map the IDs with the parks
parks = {
'80007823': 'Animal Kingdom',
'80007838': 'EPCOT',
'80007944': 'Magic Kingdom',
'80007998': 'Hollywood Studios',
}
# The park we're looking for
park_wanted = '80007944'
# An array of available dates
dates = []
# data is from the response in the code block above
for item in data:
# Check if there's availability
if item['availability'] != 'none':
# Check if the park we want is available
if park_wanted in item['parks']:
# Add the date to our available dates array
dates.append(item['date'])
I won't go into setting up Twilio, because they do a great job on-boarding their clients and explaining how to get started. Our code is pretty simple. We're just creating a Twilio client with our account information, crafting a text message, and sending it.
# Import the Twilio client
from twilio.rest import Client
account_sid = 'A*******' # Twilio account SID
auth_token = 'b*******' # Twilio auth token
twilio_phone_number = '+1**********' # Phone number Twilio account sends from
phone_number = '+1**********' # Our phone number
# Check if we found any available dates
if dates:
# Create our Twilio client
twilio_client = Client(account_sid, auth_token)
# Create and send our message
twilio_client.messages.create(
body=f"Reservations are now available for { parks[park_wanted] } on { [date for date in dates] }. Reserve now: https://disneyworld.disney.go.com/park-reservations/create-party",
from_=twilio_phone_number,
to=phone_number
)
Now we need to combine it all, and make it usable by Google Cloud Functions. We need to wrap the important parts in a function for Google Cloud Functions to call, and then we also need to return something at the end of that function. Here's our finished code.
import requests
from twilio.rest import Client
parks = {
'80007823': 'Animal Kingdom',
'80007838': 'EPCOT',
'80007944': 'Magic Kingdom',
'80007998': 'Hollywood Studios',
}
park_wanted = '80007944'
account_sid = 'A*******'
auth_token = 'b*******'
twilio_phone_number = '+1**********'
phone_number = '+1**********'
base_url = 'https://disneyworld.disney.go.com/availability-calendar/api/calendar'
start_date = '2022-05-15'
end_date = '2022-05-21'
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:98.0) Gecko/20100101 Firefox/98.0',
}
params = {
'segment': 'tickets',
'startDate': start_date,
'endDate': end_date,
}
def run(request):
response = requests.get(
base_url,
headers=headers,
params=params,
)
data = response.json()
dates = []
for item in data:
if item['availability'] != 'none' and park_wanted in item['parks']:
dates.append(item['date'])
if dates:
twilio_client = Client(account_sid, auth_token)
twilio_client.messages.create(
body=f"Reservations are now available for { parks[park_wanted] } on { [date for date in dates] }. Reserve now: https://disneyworld.disney.go.com/park-reservations/create-party",
from_=twilio_phone_number,
to=phone_number
)
return 'complete'
The last thing to do, is put this on Google Cloud Functions. There are plenty of articles on the internet about how to get going with Google Cloud Functions, so I won't get into that here.
And now we wait.
Waiting
We got on the plane, and I still hadn't gotten a text.
Two days later, we settled in at the resort, still no text.
The next day we arrived at EPCOT for our first day at Disney World with still no text.
Then It Happened
I don't think I'll ever forget the moment. We had just watched the EPCOT fireworks show feeling like we were on top of the world. My partner and I were walking side-by-side both pushing double strollers with our near-sleeping children surrounded by all the other families. We talked about all the things we missed that day that we would check out on our second day...
Then it dawned on me that I had gotten several notifications on my phone in the last couple minutes. I pulled my phone out of my pocket and shouted to my partner, "THE MAGIC KINGDOM IS OPEN!". We found a table, parked the strollers, frantically tried to cancel our second day EPCOT reservation, and then finally reserved our second day for Magic Kingdom.
We had done it.
Retrospective
After coming down from the adrenaline rush of the trip, I thought about if this could be made into a service for others to use. There were a couple problems I noticed as I did the thought experiment:
- I don't think there would be enough clients to warrant this as a service.
- If there were more than one customer trying to secure a specific park on a certain date, it would pit them against each other. That doesn't seem fair.
I've also learned lately that sometimes you can build something that's just for you. It doesn't need to be for everyone. I think that can make it special.
Top comments (0)