{"id":1,"date":"2022-06-18T13:52:47","date_gmt":"2022-06-18T13:52:47","guid":{"rendered":"https:\/\/ghothi.co.uk\/?p=1"},"modified":"2025-05-25T16:22:28","modified_gmt":"2025-05-25T16:22:28","slug":"hello-world","status":"publish","type":"post","link":"https:\/\/ghothi.co.uk\/?p=1","title":{"rendered":"Automating Passport Appointment Checks"},"content":{"rendered":"\n<p>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.<\/p>\n\n\n\n<p>The UK Government website has a way to fast-track the process, but it&#8217;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&#8217;s a game of Russian roulette with you constantly refreshing the page every half hour.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img fetchpriority=\"high\" decoding=\"async\" width=\"768\" height=\"583\" src=\"https:\/\/ghothi.co.uk\/wp-content\/uploads\/2022\/06\/Passport-urgently.png\" alt=\"\" class=\"wp-image-149\" srcset=\"https:\/\/ghothi.co.uk\/wp-content\/uploads\/2022\/06\/Passport-urgently.png 768w, https:\/\/ghothi.co.uk\/wp-content\/uploads\/2022\/06\/Passport-urgently-300x228.png 300w, https:\/\/ghothi.co.uk\/wp-content\/uploads\/2022\/06\/Passport-urgently-500x380.png 500w, https:\/\/ghothi.co.uk\/wp-content\/uploads\/2022\/06\/Passport-urgently-150x114.png 150w, https:\/\/ghothi.co.uk\/wp-content\/uploads\/2022\/06\/Passport-urgently-400x304.png 400w, https:\/\/ghothi.co.uk\/wp-content\/uploads\/2022\/06\/Passport-urgently-200x152.png 200w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/><\/figure>\n\n\n\n<p>After about a day or two of trying, I figured this is exactly the kind of situation Python excels at.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Goal<\/h2>\n\n\n\n<p>To automate checking for fast-track passport slots and notify us instantly with an email and an audible sound alert.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Plan<\/h2>\n\n\n\n<p>Before doing something technical, I like to map out a workflow as it helps structure my approach. Here&#8217;s what it looked like:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" width=\"804\" height=\"1024\" src=\"https:\/\/ghothi.co.uk\/wp-content\/uploads\/2024\/05\/passport-checker_GH-804x1024.png\" alt=\"\" class=\"wp-image-26\" srcset=\"https:\/\/ghothi.co.uk\/wp-content\/uploads\/2024\/05\/passport-checker_GH-804x1024.png 804w, https:\/\/ghothi.co.uk\/wp-content\/uploads\/2024\/05\/passport-checker_GH-236x300.png 236w, https:\/\/ghothi.co.uk\/wp-content\/uploads\/2024\/05\/passport-checker_GH-768x978.png 768w, https:\/\/ghothi.co.uk\/wp-content\/uploads\/2024\/05\/passport-checker_GH-500x637.png 500w, https:\/\/ghothi.co.uk\/wp-content\/uploads\/2024\/05\/passport-checker_GH-150x191.png 150w, https:\/\/ghothi.co.uk\/wp-content\/uploads\/2024\/05\/passport-checker_GH-400x509.png 400w, https:\/\/ghothi.co.uk\/wp-content\/uploads\/2024\/05\/passport-checker_GH-800x1019.png 800w, https:\/\/ghothi.co.uk\/wp-content\/uploads\/2024\/05\/passport-checker_GH-200x255.png 200w, https:\/\/ghothi.co.uk\/wp-content\/uploads\/2024\/05\/passport-checker_GH.png 893w\" sizes=\"(max-width: 804px) 100vw, 804px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Step 1: Setting Up<\/h4>\n\n\n\n<p>First, I imported these libraries:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>&#8216;requests&#8217; and &#8216;BeautifulSoup&#8217; for web scraping.<\/li>\n\n\n\n<li>&#8216;ctypes&#8217; and &#8216;winsound&#8217; to handle desktop notifications.<\/li>\n\n\n\n<li>&#8216;smtplib&#8217; and &#8217;email&#8217; to fire off email notifications.<\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"import requests\nfrom bs4 import BeautifulSoup\nimport time\nimport ctypes\nimport winsound\nfrom time import sleep\nfrom random import randint\nimport smtplib\nfrom email.mime.text import MIMEText\nfrom email.mime.multipart import MIMEMultipart\nfrom email.mime.base import MIMEBase\nfrom email import encoders\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #81A1C1\">import<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">requests<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">from<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">bs4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">import<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">BeautifulSoup<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">import<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">time<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">import<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">ctypes<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">import<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">winsound<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">from<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">time<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">import<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">sleep<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">from<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">random<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">import<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">randint<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">import<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">smtplib<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">from<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">email<\/span><span style=\"color: #D8DEE9FF\">.<\/span><span style=\"color: #8FBCBB\">mime<\/span><span style=\"color: #D8DEE9FF\">.<\/span><span style=\"color: #8FBCBB\">text<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">import<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">MIMEText<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">from<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">email<\/span><span style=\"color: #D8DEE9FF\">.<\/span><span style=\"color: #8FBCBB\">mime<\/span><span style=\"color: #D8DEE9FF\">.<\/span><span style=\"color: #8FBCBB\">multipart<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">import<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">MIMEMultipart<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">from<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">email<\/span><span style=\"color: #D8DEE9FF\">.<\/span><span style=\"color: #8FBCBB\">mime<\/span><span style=\"color: #D8DEE9FF\">.<\/span><span style=\"color: #8FBCBB\">base<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">import<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">MIMEBase<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">from<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">email<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">import<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">encoders<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Step 2: Configuration<\/h4>\n\n\n\n<p>Next, I configured various parameters to control the script&#8217;s behaviour. This included a random sleep timer (to avoid being blocked by the website for looking like we&#8217;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!).<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"duration = 1000\nfreq = 440\nsleepTimer = randint(240, 420)\nurl = &quot;https:\/\/www.passportappointment.service.gov.uk\/messages\/AppointmentsAvailability.html&quot;\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">duration<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1000<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">freq<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">440<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">sleepTimer<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">randint<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">240<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">420<\/span><span style=\"color: #D8DEE9FF\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">url<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">https:\/\/www.passportappointment.service.gov.uk\/messages\/AppointmentsAvailability.html<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Step 3: Email Setup<\/h4>\n\n\n\n<p>Setting up the email aspect was pretty straightforward. I stored the sender and recipient email addresses and created a simple message template that spams &#8220;PASSPORT SLOT AVAILABLE!&#8221; to our inboxes.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"email_user = 'xxx@gmail.com'\nemail_password = 'xxx'\nemail_send = 'xxx@gmail.com'\nsubject = 'Passport Slot Available!'\nmsg = MIMEMultipart()\nmsg['From'] = email_user\nmsg['To'] = email_send\nmsg['Subject'] = subject\nbody = 'Fast-track passport slot available!'\nmsg.attach(MIMEText(body, 'plain'))\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">email_user<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">xxx@gmail.com<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">email_password<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">xxx<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">email_send<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">xxx@gmail.com<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">subject<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">Passport Slot Available!<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">msg<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">MIMEMultipart<\/span><span style=\"color: #D8DEE9FF\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">msg<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">From<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">email_user<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">msg<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">To<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">email_send<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">msg<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">Subject<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">subject<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">body<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">Fast-track passport slot available!<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">msg<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">attach<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #88C0D0\">MIMEText<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">body<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">plain<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\">))<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Step 4: Checking Slot Availability<\/h4>\n\n\n\n<p>The core function, <code>availabilityChecker<\/code>, fetches the webpage, parses it, and looks for specific text indicating no available appointments.<\/p>\n\n\n\n<p>If appointments are available, it triggers the email, audible alert and pop-up notification. In other words, there&#8217;s no reason we should miss it.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"def availabilityChecker():\n    r = requests.get(url)\n    soup = BeautifulSoup(r.content, &quot;html.parser&quot;)\n    if &quot;Sorry, there are no available appointments&quot; in soup.text:\n        print(&quot;No appointments available&quot;)\n    else:\n        text = msg.as_string()\n        server = smtplib.SMTP('smtp.gmail.com', 587)\n        server.starttls()\n        server.login(email_user, email_password)\n        server.sendmail(email_user, email_send, text)\n        server.quit()\n        winsound.Beep(freq, duration)\n        ctypes.windll.user32.MessageBoxW(0, &quot;Appointments are available, book now!&quot;, &quot;AvailabilityChecker&quot;, 1)\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">def<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">availabilityChecker<\/span><span style=\"color: #D8DEE9FF\">():<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">r<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">requests<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">get<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">url<\/span><span style=\"color: #D8DEE9FF\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">soup<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">BeautifulSoup<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">r<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">content<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">html.parser<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">Sorry, there are no available appointments<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">in<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">soup<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">text<\/span><span style=\"color: #D8DEE9FF\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #88C0D0\">print<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">No appointments available<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">else<\/span><span style=\"color: #D8DEE9FF\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">text<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">msg<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">as_string<\/span><span style=\"color: #D8DEE9FF\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">server<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">smtplib<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">SMTP<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">smtp.gmail.com<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">587<\/span><span style=\"color: #D8DEE9FF\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">server<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">starttls<\/span><span style=\"color: #D8DEE9FF\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">server<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">login<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">email_user<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">email_password<\/span><span style=\"color: #D8DEE9FF\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">server<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">sendmail<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">email_user<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">email_send<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">text<\/span><span style=\"color: #D8DEE9FF\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">server<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">quit<\/span><span style=\"color: #D8DEE9FF\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">winsound<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">Beep<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">freq<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">duration<\/span><span style=\"color: #D8DEE9FF\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">ctypes<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">windll<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">user32<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">MessageBoxW<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">Appointments are available, book now!<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">AvailabilityChecker<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">)<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The email aspect is all handled within the script, but you&#8217;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.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"550\" height=\"327\" src=\"https:\/\/ghothi.co.uk\/wp-content\/uploads\/2022\/06\/python-sending-email.png\" alt=\"\" class=\"wp-image-151\" srcset=\"https:\/\/ghothi.co.uk\/wp-content\/uploads\/2022\/06\/python-sending-email.png 550w, https:\/\/ghothi.co.uk\/wp-content\/uploads\/2022\/06\/python-sending-email-300x178.png 300w, https:\/\/ghothi.co.uk\/wp-content\/uploads\/2022\/06\/python-sending-email-500x297.png 500w, https:\/\/ghothi.co.uk\/wp-content\/uploads\/2022\/06\/python-sending-email-150x89.png 150w, https:\/\/ghothi.co.uk\/wp-content\/uploads\/2022\/06\/python-sending-email-400x238.png 400w, https:\/\/ghothi.co.uk\/wp-content\/uploads\/2022\/06\/python-sending-email-200x119.png 200w\" sizes=\"(max-width: 550px) 100vw, 550px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Step 5: Keeping it Running<\/h4>\n\n\n\n<p>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.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"while True:\n    availabilityChecker()\n    sleep(sleepTimer)\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #81A1C1\">while<\/span><span style=\"color: #D8DEE9FF\"> True<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">availabilityChecker<\/span><span style=\"color: #D8DEE9FF\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">sleep<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">sleepTimer<\/span><span style=\"color: #D8DEE9FF\">)<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">The Results<\/h2>\n\n\n\n<p>After manually trying for days with no luck, this script helped us secure a slot within 3 hours! It&#8217;s not the prettiest code, but it worked&#8230;<\/p>\n\n\n\n<p>If you find yourself doing something repetitive and thinking &#8220;there&#8217;s got to be a better way,&#8221;: there probably is &#8211; and it probably involves python.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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&#8217;s near-impossible to actually secure a slot. The slots appear randomly throughout the day and disappear [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":26,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[],"class_list":["post-1","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai-ml-automation"],"_links":{"self":[{"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/1","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1"}],"version-history":[{"count":9,"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/1\/revisions"}],"predecessor-version":[{"id":153,"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/1\/revisions\/153"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=\/wp\/v2\/media\/26"}],"wp:attachment":[{"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}