A Script To Check Vaccination Slots
--
This is a story of how I put together a script for checking vaccination slots (in India). It’s pretty simple if you are a coder but this post is to explain the process to the general public.
Ok so here’s what I did as the first thing –
I visited the CoWin website, entered my pincode and clicked on the submit button. Then I right-clicked on the web page and clicked on “inspect element” (in Google Chrome).
Then I checked the “network” tab and tried submitting the form twice with different pincodes to see what requests are being sent each time I submit the form.
Here’s what I found –
You can see two requests at the bottom there, one for 400607 and the other for 400608.
If I click one either of those, I’ll see more information as follows –
I’m interested in the “Request URL”. If you copy this URL and paste it in the browser, you will get some structured response. Here’s an example –
It’s a little difficult to read it but we can prettify it by using an online JSON prettifier.
Here’s the pretty version of the same response –
{
"centers":[
{
"center_id":692991,
"name":"THANE Global Hub (18-44) 1",
"address":"Laxmi Nagar Balkum Pada Thane",
"state_name":"Maharashtra",
"district_name":"Thane",
"block_name":"Thane Municipal Corporation",
"pincode":400607,
"lat":19,
"long":72,
"from":"09:00:00",
"to":"13:00:00",
"fee_type":"Free",
"sessions":[
{
"session_id":"47494740-4324-4c0f-a092-24ab142414a2",
"date":"08-05-2021",
"available_capacity":0,
"min_age_limit":18,
"vaccine":"COVAXIN",
"slots":[
"09:00AM-10:00AM",
"10:00AM-11:00AM",
"11:00AM-12:00PM",
"12:00PM-01:00PM"
]
}
]
},
{
"center_id":695478,
"name":"THANE Global Hub (18-44) 2",
"address":"Laxmi Nagar Balkum Pada Thane",
"state_name":"Maharashtra",
"district_name":"Thane",
"block_name":"Thane Municipal Corporation",
"pincode":400607,
"lat":19,
"long":72,
"from":"14:00:00",
"to":"18:00:00",
"fee_type":"Free",
"sessions":[
{
"session_id":"1141f9c3-502c-4bce-8d45-38890b8db96e",
"date":"08-05-2021",
"available_capacity":0,
"min_age_limit":18,
"vaccine":"COVAXIN",
"slots":[
"02:00PM-03:00PM",
"03:00PM-04:00PM",
"04:00PM-05:00PM",
"05:00PM-06:00PM"
]
}
]
}
]
}
Since my end goal is to get an “alert” whenever there’s a slot available for my age (under 45), I’m only interested the following information –
min_age_limit
available_capacity
Logic
Alright, so here’s my logic –
“Send a request to that URL every X seconds and then process the response by checking whether any of the centers with min_age_limit
of 18
has available_capacity
that’s more than 0
. If so, make an alert till I manually abort the script.”
Now this has to be converted into code in order to automate it. I used Python3 for this since it’s pretty simple and intuitive to use.
Let’s build the code step by step!
A Simple Request
Here’s a simple script that sends a request (to the specified URL) and prints the response –
import requestsurl = https://cdn-api.co-vin.in/api/v2/appointment/sessions/public/calendarByPin?pincode=400607&date=08-05-2021r = requests.get( url )print(r.text)
Note: You can save it as test.py
on your desktop and run it via terminal by switching to desktop cd desktop
and typing in python3 test.py
.
It produces the same response that we got before via the browser. Cool. I’m now interested in accessing the relevant parts of the response.
The Response
In order to access the contents of the response, I use the json package.
import jsonresponse = json.loads(r.text)print( response['centers'] )for center in response['centers']:
print( center['sessions'][0]['min_age_limit'] )
print( center['sessions'][0]['available_capacity'] )
This code along with the one above it allows me to send a request to a URL, get a response and access the contents of that response.
403 Response
After a while, I started seeing a 403 response when I made a request via Python3 but everything worked fine if I accessed it via the browser.
What happened there? Something changed on CoWin’s side. To fix it, I simply had to show that my request is actually coming from a browser.
This can be done by passing a user-agent
header in our request as follows –
url = https://cdn-api.co-vin.in/api/v2/appointment/sessions/public/calendarByPin?pincode=400607&date=08-05-2021headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36'} # This is chrome, you can set whatever browser you liker = requests.get( url, headers=headers )
Params
Similarly, we can take the pincode
and date
parameters out from the url
and pass them as params
in our request as follows –
url = https://cdn-api.co-vin.in/api/v2/appointment/sessions/public/calendarByPinheaders = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36'} # This is chrome, you can set whatever browser you likepayload = {
'pincode': 400607,
'date': '08-05-2021'
}r = requests.get( url, headers=headers, params=payload )
Make Some Noise
I wanted the script to make some noise and alert me whenever a slot was available so I could go and book it asap.
Here’s a neat little trick that helps to create a beep
noise. This will beep three times –
import osbeep = lambda x: os.system("echo -n '\a';sleep 0.2;" * x)beep(3)
There’s also a way to make the computer say whatever you want it to say. For example –
import osos.system( "say VACCINE ALERT VACCINE ALERT")
It’s silly but gets the job done.
Repeat The Code Every X Seconds
Now I have everything to put together something decent but I still need a way to repeat my code to automatically check for a slot, right?
To do this, I use the sleep
method from the time
package –
import timestarttime = time.time()
seconds = 30.0while True:
print( 'Hello' )
time.sleep ( seconds - ((time.time() - starttime) % seconds) )
This simply prints “Hello” every 30 seconds. I’m sure there’s a better way of doing this but I just did a quick Google search and got this snippet from StackOverflow.
Processing The Response
Now it is time to finally process the response using some “logic” that we discussed above.
I defined a function that processes the response based on the payload (the date and the pincode) that we send to it –
Note: I’m sharing it as a screenshot because it is too difficult to read in medium’s code block.
- The code above is making a request using
params
andheaders
and stores the response inr
. - If
r
is all okay and didn’t return any errors, it loads the content ofr
as json inside theresponse
variable. If it did return any errors, it simply exits the function. - Next it checks whether the response contains a list of
centers
. - If it does, check each
center
in the list ofcenters
as follows – - If the
center
hasmin_age_limit
as 18 andavailable_capacity
is greater than0
then make some noise and print that a “slot is available” (with date and pincode). Otherwise print “no slots”. - If there’s no
center
in the list ofcenters
then print “no centers”.
Putting Everything Together
Putting everything together, here’s what I got in the end –
Just for testing purposes, it checks for an update every 2 seconds for the given date and two payloads (two pincodes).
Once a slot is available, it will keep beeping with the alert message till you manually abort the program.
Here’s a link to the final code in case you’re interested.
It’s not great. It’s just okay and gets the job done. Plus, it’s good stuff for explaining “APIs” to the general public ;)
Talking of APIs, CoWin’s public APIs are available here.
Thanks for reading! :)
Edit –
If you run into the “requests module missing” error, you can install it by opening the terminal and typing in python3 -m pip install requests
command. You can use the same command to install other missing modules (if any).