My partner recently needed to visit a very unwell family member overseas. But her current passport was about to expire, and we needed to renew it ASAP.
The UK Government website has a way to fast-track the process, but it’s near-impossible to actually secure a slot. The slots appear randomly throughout the day and disappear within a minute of being posted. In other words, it’s a game of Russian roulette with you constantly refreshing the page every half hour.

After about a day or two of trying, I figured this is exactly the kind of situation Python excels at.
The Goal
To automate checking for fast-track passport slots and notify us instantly with an email and an audible sound alert.
The Plan
Before doing something technical, I like to map out a workflow as it helps structure my approach. Here’s what it looked like:

Step 1: Setting Up
First, I imported these libraries:
- ‘requests’ and ‘BeautifulSoup’ for web scraping.
- ‘ctypes’ and ‘winsound’ to handle desktop notifications.
- ‘smtplib’ and ’email’ to fire off email notifications.
import requests
from bs4 import BeautifulSoup
import time
import ctypes
import winsound
from time import sleep
from random import randint
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
Step 2: Configuration
Next, I configured various parameters to control the script’s behaviour. This included a random sleep timer (to avoid being blocked by the website for looking like we’re trying to DDoS it with too many requests), the government page URL (so it knows where to find the slots), and the sound alert duration and frequency (to make sure we hear it!).
duration = 1000
freq = 440
sleepTimer = randint(240, 420)
url = "https://www.passportappointment.service.gov.uk/messages/AppointmentsAvailability.html"
Step 3: Email Setup
Setting up the email aspect was pretty straightforward. I stored the sender and recipient email addresses and created a simple message template that spams “PASSPORT SLOT AVAILABLE!” to our inboxes.
email_user = 'xxx@gmail.com'
email_password = 'xxx'
email_send = 'xxx@gmail.com'
subject = 'Passport Slot Available!'
msg = MIMEMultipart()
msg['From'] = email_user
msg['To'] = email_send
msg['Subject'] = subject
body = 'Fast-track passport slot available!'
msg.attach(MIMEText(body, 'plain'))
Step 4: Checking Slot Availability
The core function, availabilityChecker
, fetches the webpage, parses it, and looks for specific text indicating no available appointments.
If appointments are available, it triggers the email, audible alert and pop-up notification. In other words, there’s no reason we should miss it.
def availabilityChecker():
r = requests.get(url)
soup = BeautifulSoup(r.content, "html.parser")
if "Sorry, there are no available appointments" in soup.text:
print("No appointments available")
else:
text = msg.as_string()
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(email_user, email_password)
server.sendmail(email_user, email_send, text)
server.quit()
winsound.Beep(freq, duration)
ctypes.windll.user32.MessageBoxW(0, "Appointments are available, book now!", "AvailabilityChecker", 1)
The email aspect is all handled within the script, but you’ll need to provide the correct port number for your email provider in order to set up the SMTP client session correctly. This is just so the email actually goes to the correct server, otherwise your notification will get lost in the ether.

Step 5: Keeping it Running
To keep the script running, I set up an infinite loop to keep checking for available slots at random intervals between 4 to 7 minutes until I decide to turn it off.
while True:
availabilityChecker()
sleep(sleepTimer)
The Results
After manually trying for days with no luck, this script helped us secure a slot within 3 hours! It’s not the prettiest code, but it worked…
If you find yourself doing something repetitive and thinking “there’s got to be a better way,”: there probably is – and it probably involves python.