Python wrapper for CoWin API's

Related tags

cowin
Overview

Cowin Tracker

Python API wrapper for CoWin, India's digital platform launched by the government to help citizens register themselves for the vaccination drive by booking an appointment at the nearby vaccination centres

The process to look-up for available slots to take the vaccine is tedious as you need to log in to the portal every time

This wrapper is meant to enable folks to build their own versions of a system to lookup for vaccine availablity either in a district or in a particular pin code.

Example:

from cowin_api import CoWinAPI

cowin = CoWinAPI()

states = cowin.get_states()
print(states)

Install

pip install cowin

Usage

The wrapper currently covers four endpoints used by the CoWin portal specified below.

Initialize

from cowin_api import CoWinAPI

cowin = CoWinAPI()

Get all the available states

Returns the list of states in which vaccine drive is being conducted. This also returns the state_id which would be required in the subsequent requests.

from cowin_api import CoWinAPI

cowin = CoWinAPI()
states = cowin.get_states()
print(states)
Sample Response:
{
  "states": [
    {
      "state_id": 1,
      "state_name": "Andaman and Nicobar Islands"
    },
    {
      "state_id": 2,
      "state_name": "Andhra Pradesh"
    }
  ],
  "ttl": 24
}

Get all the available districts

Returns the list of districts in a particular states in which vaccine drive is being conducted. This also returns the district_id which would be required in the subsequent requests.

In this method, you would need to pass the state_id retrieved from the previous method.

from cowin_api import CoWinAPI

state_id = '21'
cowin = CoWinAPI()
districts = cowin.get_districts(state_id)
print(districts)
Sample Response:
{
  "districts": [
    {
      "district_id": 395,
      "district_name": "Mumbai"
    },
    {
      "district_id": 363,
      "district_name": "Pune"
    }
  ],
  "ttl": 24
}

Get all the centers available in a district

Use this method to lookup for centers based on a district_id or a list of district_ids. This method is broader than searching by pin code as it covers the whole district.

In this method, you would need to pass the district_id retrieved from the previous methods. By default, the method looks-up for slots with today's date. For any other dates pass the date in DD-MM-YYYY format.

from cowin_api import CoWinAPI

district_id = '395'
date = '03-05-2021'  # Optional. Takes today's date by default
min_age_limit = 18  # Optional. By default returns centers without filtering by min_age_limit

cowin = CoWinAPI()
available_centers = cowin.get_availability_by_district(district_id, date, min_age_limit)
print(available_centers)
Sample Response:
{
  "centers": [
    {
      "center_id": 561660,
      "name": "BKC COVID Facility4 (18-44 Yr)",
      "state_name": "Maharashtra",
      "district_name": "Mumbai",
      "block_name": "Ward H East Corporation - MH",
      "pincode": 400051,
      "lat": 19,
      "long": 72,
      "from": "09:00:00",
      "to": "17:00:00",
      "fee_type": "Free",
      "sessions": [
        {
          "session_id": "524ee1c1-550f-4e02-be36-79259175aa30",
          "date": "02-05-2021",
          "available_capacity": 0,
          "min_age_limit": 18,
          "vaccine": "",
          "slots": [
            "09:00AM-11:00AM",
            "11:00AM-01:00PM",
            "01:00PM-03:00PM",
            "03:00PM-05:00PM"
          ]
        },
        {
          "session_id": "faf4a93e-fdf2-48f2-93de-254d19136d87",
          "date": "03-05-2021",
          "available_capacity": 0,
          "min_age_limit": 18,
          "vaccine": "",
          "slots": [
            "09:00AM-11:00AM",
            "11:00AM-01:00PM",
            "01:00PM-03:00PM",
            "03:00PM-05:00PM"
          ]
        }
      ]
    }
  ]
}

Get all the available centers in a pin code

Use this method to lookup for centers based on a pin_code or a list of pin_codes. By default, the method looks-up for slots with today's date. For any other dates pass the date in DD-MM-YYYY format.

from cowin_api import CoWinAPI

pin_code = "400080"
date = '03-05-2021'  # Optional. Default value is today's date
min_age_limit = 18  # Optional. By default returns centers without filtering by min_age_limit

cowin = CoWinAPI()
available_centers = cowin.get_availability_by_pincode(pin_code, date, min_age_limit)
print(available_centers)
Sample Response:
{
  "centers": [
    {
      "center_id": 574933,
      "name": "SEVEN HIILS 2 Age (18-44)",
      "state_name": "Maharashtra",
      "district_name": "Mumbai",
      "block_name": "Ward K East Corporation - MH",
      "pincode": 400059,
      "lat": 19,
      "long": 72,
      "from": "09:00:00",
      "to": "17:00:00",
      "fee_type": "Free",
      "sessions": [
        {
          "session_id": "0645407e-fe72-4483-85d4-99ba4c567758",
          "date": "03-05-2021",
          "available_capacity": 0,
          "min_age_limit": 18,
          "vaccine": "",
          "slots": [
            "09:00AM-11:00AM",
            "11:00AM-01:00PM",
            "01:00PM-03:00PM",
            "03:00PM-05:00PM"
          ]
        },
        {
          "session_id": "0c4bc740-5429-4359-a2a4-428cf8649e38",
          "date": "08-05-2021",
          "available_capacity": 0,
          "min_age_limit": 45,
          "vaccine": "",
          "slots": [
            "09:00AM-11:00AM",
            "11:00AM-01:00PM",
            "01:00PM-03:00PM",
            "03:00PM-05:00PM"
          ]
        }
      ]
    },
    {
      "center_id": 574931,
      "name": "SEVEN HIILS 1",
      "state_name": "Maharashtra",
      "district_name": "Mumbai",
      "block_name": "Ward K East Corporation - MH",
      "pincode": 400059,
      "lat": 19,
      "long": 72,
      "from": "09:00:00",
      "to": "18:00:00",
      "fee_type": "Free",
      "sessions": [
        {
          "session_id": "819ca013-67f5-4074-8614-f49b7c41878f",
          "date": "08-05-2021",
          "available_capacity": 0,
          "min_age_limit": 45,
          "vaccine": "",
          "slots": [
            "09:00AM-11:00AM",
            "11:00AM-01:00PM",
            "01:00PM-03:00PM",
            "03:00PM-06:00PM"
          ]
        }
      ]
    },
    {
      "center_id": 574935,
      "name": "SEVEN HIILS 3",
      "state_name": "Maharashtra",
      "district_name": "Mumbai",
      "block_name": "Ward K East Corporation - MH",
      "pincode": 400059,
      "lat": 19,
      "long": 72,
      "from": "12:00:00",
      "to": "17:00:00",
      "fee_type": "Free",
      "sessions": [
        {
          "session_id": "4cfc728b-ce00-4e39-9285-8679130fbcb0",
          "date": "08-05-2021",
          "available_capacity": 0,
          "min_age_limit": 45,
          "vaccine": "",
          "slots": [
            "12:00PM-01:00PM",
            "01:00PM-02:00PM",
            "02:00PM-03:00PM",
            "03:00PM-05:00PM"
          ]
        }
      ]
    }
  ]
}

Notes:

The API's of CoWin may at times return a 401 Unauthorized response. To mitigate this we are passing user agents in the request. Still, if the issue persists please wait for a few minutes before trying again.

Please try not to spam the CoWin servers and try to keep a timeout between subsequent requests if you are polling at a fixed interval


Roadmap:

  • Add a filter to search by age group of 18-45 and 45+
  • Allow user to search for multiple pin codes
  • Allow user to search for multiple districts
  • Catch and raise custom exceptions
  • Implement Rate Limiting
  • Implement mocking in test cases

Contributions

Contributions are always welcome!

The roadmap given above is just a line of thought. Please feel free to contribute any other method which you feel could be helpful.


License:

MIT License

Issues
  • Vaccine and Dose filters added

    Vaccine and Dose filters added

    I've added two more filters:

    • Vaccine (covaxin/covishield)
    • Dose (first/second)

    Updated filter function mechanism to accommodate multiple filters with a dry approach. Updated param typo min_age_limt -> min_age_limit

    opened by tshrv 5
  • Client error in get availability by pincode

    Client error in get availability by pincode

    401 Client Error: Unauthorized for url: https://cdn-api.co-vin.in/api/v2/appointment/sessions/calendarByPin?pincode=700091&date=04-05-21

    Error when get availability by pincode method is run

    opened by AdityaMitra5102 4
  • 403 Client Error while executing the code

    403 Client Error while executing the code

    403 Client Error: Forbidden for url: https://cdn-api.co-vin.in/api/v2/admin/location/states while executing the below code what needs to be done here, please guide.

    from cowin_api import CoWinAPI

    cowin = CoWinAPI()

    states = cowin.get_states() print(states)

    opened by pankajmitsom 3
  • module 'cowin_api.models' has no attribute 'IO'

    module 'cowin_api.models' has no attribute 'IO'

    While running the following script in Jupyter Environment

    from cowin_api import CoWinAPI

    Error Message: 
    
    AttributeError                            Traceback (most recent call last)
    <ipython-input-6-6c470a7ea45e> in <module>
    ----> 1 from cowin_api import CoWinAPI
    
    ~\anaconda3\lib\site-packages\cowin_api\__init__.py in <module>
          4 
          5 from cowin_api import models
    ----> 6 from cowin_api.api_client import ApiClient, AsyncApis, SyncApis  # noqa F401
          7 
          8 for model in inspect.getmembers(models, inspect.isclass):
    
    ~\anaconda3\lib\site-packages\cowin_api\api_client.py in <module>
         14     SyncBeneficiaryRegistrationAPIsApi,
         15 )
    ---> 16 from cowin_api.api.certificate_ap_is_api import AsyncCertificateAPIsApi, SyncCertificateAPIsApi
         17 from cowin_api.api.metadata_ap_is_api import AsyncMetadataAPIsApi, SyncMetadataAPIsApi
         18 from cowin_api.api.user_authentication_ap_is_api import AsyncUserAuthenticationAPIsApi, SyncUserAuthenticationAPIsApi
    
    ~\anaconda3\lib\site-packages\cowin_api\api\certificate_ap_is_api.py in <module>
         10 
         11 
    ---> 12 class _CertificateAPIsApi:
         13     def __init__(self, api_client: "ApiClient"):
         14         self.api_client = api_client
    
    ~\anaconda3\lib\site-packages\cowin_api\api\certificate_ap_is_api.py in _CertificateAPIsApi()
         14         self.api_client = api_client
         15 
    ---> 16     def _build_for_download(self, beneficiary_reference_id: str) -> Awaitable[m.IO]:
         17         """
         18         API to download vaccination certificate in PDF format by beneficiary reference id.
    
    AttributeError: module 'cowin_api.models' has no attribute 'IO'
    
    opened by Kartik-Singhal26 3
  • Find by PinCode is working

    Find by PinCode is working

    File "t.py", line 8, in available_centers = cowin.get_availability_by_pincode(pin_code, date, min_age_limit) File "C:\Users\byashwan\Anaconda3\lib\site-packages\cowin_api\api.py", line 22, in get_availability_by_pincode return filter_centers_by_age_limit(self._call_api(url), min_age_limt) if min_age_limt else self._call_api(url) File "C:\Users\byashwan\Anaconda3\lib\site-packages\cowin_api\utils.py", line 11, in filter_centers_by_age_limit original_centers = centers.get('centers') AttributeError: 'HTTPError' object has no attribute 'get'

    opened by sonu1125 2
  • Not an issue but a general info.

    Not an issue but a general info.

    Hi,

    Sorry if I registered this as an issue. But I have one doubt related to deployments. I have created my custom worker script integrated cowin API and deployed it on Heroku and hosted it in Europe region (As they have US and EU as only option for worker based applications). Due to this I'm repeatedly getting 403 forbidden error codes when ever someone interacts with my bot.

    If I use this python wrapper and integrate it with my script will it benefit me with region based issues?

    Thanks 🙏

    opened by kuckchuck96 2
  • :sparkles: Added 'available_capacity_gte' to filter center with available slot.

    :sparkles: Added 'available_capacity_gte' to filter center with available slot.

    This version allows to search for centers with slots that are open for registration. It is a default parameter, and works only in conjunction with min_age_limit.

    opened by mpmic 2
  • AttributeError: 'HTTPError' object has no attribute 'get'

    AttributeError: 'HTTPError' object has no attribute 'get'

    When I run the get_availability_by_district for let's say, for next 15 days, one query after the other, I get the below error and program crashes out.

    File "cowin.py", line 33, in job available_centers = cowin.get_availability_by_district(district_id, date.strftime("%d-%m-%Y"), min_age_limit) File "/Users/sm/Library/Python/3.8/lib/python/site-packages/cowin_api/api.py", line 49, in get_availability_by_district return self.get_availability_by_base(caller='district', areas=district_id, File "/Users/sm/Library/Python/3.8/lib/python/site-packages/cowin_api/api.py", line 35, in get_availability_by_base curr_result = filter_centers_by_age_limit(self._call_api(url), File "/Users/sm/Library/Python/3.8/lib/python/site-packages/cowin_api/utils.py", line 11, in filter_centers_by_age_limit original_centers = centers.get('centers') AttributeError: 'HTTPError' object has no attribute 'get'

    opened by muthyas 2
  • Final test fails

    Final test fails

    The final test whose code is listed below fails

    def test_min_age_limit_filter():
        cowin = CoWinAPI()
        availability = cowin.get_availability_by_district("395", min_age_limt=18)
    
        assert isinstance(availability, dict)
        assert isinstance(availability.get('centers'), list)
        assert len(availability.get('centers')[0].get('sessions')) == 0
    

    Reason: Date is not specified, hence the results will keep changing daily depending on when the tests are run.

    Solution: Pass the date parameter and accordingly correct the final assertion test (based on the readme). The below code passes the tests

    def test_min_age_limit_filter():
        cowin = CoWinAPI()
        availability = cowin.get_availability_by_district("395", date="03-05-2021", min_age_limt=18)
    
        assert isinstance(availability, dict)
        assert isinstance(availability.get('centers'), list)
        assert len(availability.get('centers')[0].get('sessions')) == 2
    

    Also, in the constants file, date format needs to be corrected to be consistent with the API, DD_MM_YYYY = "%d-%m-%y" to DD_MM_YYYY = "%d-%m-%Y".

    opened by DragonWarrior15 1
  • minor refactor

    minor refactor

    opened by sprajosh 1
  • Show available centers

    Show available centers

    opened by sprajosh 1
  • API is unable to fetch data by pincode

    API is unable to fetch data by pincode

    from cowin_api import CoWinAPI

    pin_code = ["570021","560066"] date = '03-05-2021' # Optional. Default value is today's date min_age_limit = 18 # Optional. By default returns centers without filtering by min_age_limit for pin in pin_code: cowin = CoWinAPI() print(pin, type(pin)) try: available_centers = cowin.get_availability_by_pincode(pin_code, date, min_age_limit) print(available_centers) except Exception as Error: print("Error for pin,", pin, Error)

    570021 <class 'str'> Error for pin, 570021 'HTTPError' object has no attribute 'get' 560066 <class 'str'> Error for pin, 560066 'HTTPError' object has no attribute 'get'

    opened by babvin 1
  • Feature retry

    Feature retry

    • Fix #13
    • Added the retry module and updated the requests sessions
    • Updated the last test dependent on date, apparently the API now gives client error for old dates
    opened by DragonWarrior15 0
  • Design change separate filters api call

    Design change separate filters api call

    …updated tests isolated from api calls

    all tests passed, except the first two test_get_states and test_get_districts. I manually tried to run the urls in the browser and get the similar {"message":"Forbidden"} error.

    Please have a look at the function filter_centers. I might have made it a little difficult to understand and welcome your comments/suggestions to improve the same.

    Now the filters available are min_age_limit, min_capacity, vaccine, and fee_type.

    opened by DragonWarrior15 2
  • [Design Change] Separating filtering and api calls

    [Design Change] Separating filtering and api calls

    Currently the code to apply min age filter runs like this

    curr_result = filter_centers_by_age_limit(self._call_api(url),
                                                              min_age_limt)
    

    The potential problem with this is that the filter is coupled with the api call, hence making changes or places where the code is branched like the following case

    if min_age_limt:
        curr_result = filter_centers_by_age_limit(self._call_api(url),
                                                  min_age_limt)
    else:
        curr_result = self._call_api(url)
    

    becomes difficult and has chances of introduction of errors.

    Proposal: change the structure so that the code for filter only works on the received data and does not need to make the api call. The fetch is going to happen first anyways since the API itself not going to apply any filter and return all the data always (at least for now). The code would then look like

    curr_result = self._call_api(url)
    
    if min_age_limt:
        curr_result = filter_centers_by_age_limit(curr_result, min_age_limt)
    
    if some_other_filter:
        curr_result = some_other_filter_function(curr_result, *kwargs)
    

    Please let me know if this is something that can make the code better, and I will make the changes in a separate PR.

    opened by DragonWarrior15 10
  • [Feature] The code should retry fetching the data if the connection fails

    [Feature] The code should retry fetching the data if the connection fails

    Currently the code does not support any kind of retry in order to call the api again to fetch the results. The following piece of code might work for this (this will be wrapped around the base api call so that modifications are needed at only one place)

    success = False
    for i in range(Constants.max_retries):
        if(success):
            break
        try:
            some_result = api_call()
            success = True
        except Exception as e:
            # wait few sec and continue
            time.sleep(Constants.sleep_time)
            continue
    

    We could keep Constants.max_retries as 3 and Constants.sleep_time as 2. I am not sure if this is the best way to do this, but if this is something useful, I can add it to the code with a PR. This is useful in cases where the API may not be reachable, or when any part of the package, or an external user is running a loop which calls the api multiple times.

    opened by DragonWarrior15 6
Owner
Saiprasad Balasubramanian
Socially Awkward Developer | Terrible Object Oriented Programmer | Tinkerer | Looking for opportunities
Saiprasad Balasubramanian
A Python Script to automate searching of available vaccination centers in the city and hence booking

Cowin Vaccine Availability Notifier Cowin Vaccine Availability Notifier takes your City or PIN code as an input and automatically notifies you via ema

Jayesh Padhiar 6 May 21, 2021
A collective list of free APIs for use in software and web development.

Public APIs A collective list of free APIs for use in software and web development. A public API for this project can be found here! For information o

null 131.1k Jun 13, 2021
Telegram Bot to check covid vaccine slot availability on CoWin site

Cowin Assist Telegram Bot Check the bot here @cowinassistbot. This is a simple Telegram bot to Check slots availability Get an alert when slots become

null 26 May 27, 2021
Is the CoWin website updated for registration?

CoWin-Update Is the CoWin website updated for registration? This is a very hacky PYTHON3 script to lookup the CoWin portal if they re-deployed their J

Yash Jakhotiya 5 May 10, 2021
Tracker to check the covid shot slot availability in India and send mobile alerts via Twilio Messaging Service.

Cowin-Slot-Tracker Tracker to check the covid vaccine slot availability in India and send mobile notifications through Twilio Messaging Service. Requi

invalid username 26 Jun 1, 2021
Telegram bot to check availability of vaccination slots in India.

cowincheckbot Telegram bot to check availability of vaccination slots in India. Setup Install requirements using pip3 install -r requirements.txt Crea

Muhammed Shameem 11 May 30, 2021
:snake: Python SDK to query Scaleway APIs.

Scaleway SDK Python SDK to query Scaleway's APIs. Stable release: Development: Installation The package is available on pip. To install it in a virtua

Scaleway 107 Jun 2, 2021
🏆 A ranked list of awesome machine learning Python libraries. Updated weekly.

Best-of Machine Learning with Python ?? A ranked list of awesome machine learning Python libraries. Updated weekly. This curated list contains 840 awe

Machine Learning Tooling 5.3k Jun 13, 2021
Python wrapper for the Sportradar APIs ⚽️🏈

Sportradar APIs This is a Python wrapper for the sports APIs provided by Sportradar. You'll need to sign up for an API key to use the service. Sportra

John W. Miller 30 Jun 12, 2021
This very basic script can be used to automate COVID-19 vaccination slot booking on India's Co-WIN Platform.

COVID-19 Vaccination Slot Booking Script This very basic CLI based script can be used to automate covid vaccination slot booking on Co-WIN Platform. I

null 619 Jun 13, 2021
A python API for BSCScan (Binance Smart Chain Explorer), available on PyPI.

bscscan-python A complete Python API for BscScan.com, available on PyPI. Powered by BscScan.com APIs. This is a gently modified fork of the etherscan-

Panagiotis Kotsias 86 Jun 13, 2021
A thin Python Wrapper for the Dark Sky (formerly forecast.io) weather API

Dark Sky Wrapper This is a wrapper for the Dark Sky (formerly forecast.io) API. It allows you to get the weather for any location, now, in the past, o

Ze'ev Gilovitz 413 Jun 12, 2021
First Party data integration solution built for marketing teams to enable audience and conversion onboarding into Google Marketing products (Google Ads, Campaign Manager, Google Analytics).

Megalista Sample integration code for onboarding offline/CRM data from BigQuery as custom audiences or offline conversions in Google Ads, Google Analy

Google 22 Jun 4, 2021
Python wrapper for eBay API

python-ebay - Python Wrapper for eBay API This project intends to create a simple python wrapper around eBay APIs. Development and Download Sites The

Roopesh 97 Jun 9, 2021