1

I am working on a Django application, currently deployed on a Free Heroku dyno, which consumes the CoWin public API.

On Heroku server, the requests.get() method returns HttpResponse status code 403.
This is what my API call looks like -

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36'}
url = "https://cdn-api.co-vin.in/api/v2/appointment/sessions/public/calendarByPin?pincode=110001&date=23-05-2021"
api_response = requests.get(url, headers = headers)

When I run it locally using heroku local command, everything works fine & the HttpResponse status code returned is 200. I am failing to understand why it returns 403 status code when running it on Heroku server.

1 Answers1

1

This was exactly the same issue that I was facing initially when I started building vaccine tracker application.

Reason behind the issue is that these COWIN APIs are geofenced and no server outside the Indian region would work because of geo-fencing. You might be getting "Internal Server Error" after deploying your app on heroku and must be working fine when running locally.

For security reasons, browsers restrict cross-origin HTTP requests initiated from scripts. For example, XMLHttpRequest and the Fetch API follow the same-origin policy. This means that a web application using those APIs can only request resources from the same origin the application was loaded from unless the response from other origins includes the right CORS headers.

The Cross-Origin Resource Sharing standard works by adding new HTTP headers that let servers describe which origins are permitted to read that information from a web browser. Reference

You can use the JavaScript's Fetch API for making HTTP requests, browsers come with a global fetch() function that we can use to make requests. The argument of fetch() is the URL with the server-side resource. We then chain the promise with the then() method, which captures the HTTP response in the response argument and call its json() method. Reference

fetch() function to send a GET request to our API

fetch(url)
    .then(response => response.json())
    .then(json => console.log(json));

Modern browsers use CORS in APIs such as XMLHttpRequest or Fetch to mitigate the risks of cross-origin HTTP requests.

Therefore this worked for me, making request from the clients browser instead of making api call from server to get data. Otherewise you can you try exploring HTTP proxy integration.

  • Thank you for this detailed answer Sameer. Currently in my web app, the API calls are part of a continuous running background server side script. The response from API is used to send a notification to users over email who have shared their email addresses while registering on my app. The data from API calls is not something which is sent as a response to a client's server request & displayed it on a browser. Hence not sure if putting API call on client side will server my purpose. – thesteadyprogrammer May 25 '21 at 02:35
  • But you must be making api call from the server side right in order to get data and then validate if vaccines are available or not and if available you must be sending notification to the user. So the error remains the same only. While making api call from the server it is not giving back the response because it must be blocking any IP hit outside from Indian server as hosting sites like Heroku, Indian IP is not an option. – Sameer Srivastava May 25 '21 at 02:58
  • If you found my answer useful. Can you please mark it as accepted answer or up vote please. Thank you – Sameer Srivastava May 25 '21 at 03:19
  • Sure. Once I have enough reputation points I will do that. One more thing I wished to ask, what other web hosting services can I use to make my application work. I know AWS and Google Cloud have India servers but they require credit card information for free tier. Are there any other free alternatives that you could suggest. Thanks. – thesteadyprogrammer May 25 '21 at 04:55
  • Yea I would suggest to move to AWS and Google Cloud or Azure servers in Indian regions whichever you are comfortable with and add your credit card details, they are not going to charge you and that might work for you if you want to make request through server side only. Otherwise as I suggested use the JavaScript fetch() method which is much easier and even faster and then deploy on Heroku, it will work perfectly. Or another method would be if you can create a proxy server and then you can host it in any location. It will work fine. – Sameer Srivastava May 25 '21 at 07:16