Skip to main content

The unofficial API for the Boursa

Project description

(Doesn't work on the new site. Going to fix it)

(0.0.5: Market.listing and Corporation.price_history works. Take a look at examples 3 and 3.1 below)

Amwal - Unofficial API For the Kuwaiti Stock Market (Boursa)

Amwal is a small python library designed to make it easier to get information from the Kuwaiti stock market, known as the Boursa. Unfortunately, since the Boursa website doesn't have an official HTTP API, this is a substitute that offers the same function by scraping the website directly for the data.

Some features to make life easier

  • Scraped data is cached in a JSON file by default to avoid making redundant requests
  • The data is converted into a properly typed pandas dataframe.
  • The API surface is small, intuitive, easy to use. It also mirrors the structure of the website itself.


pip3 install amwal

This project depends on the following libraries:

  • python-dateutil
  • pandas
  • requests
  • beautifulsoup4

Quick start

The main class representing the market as a whole is amwal.Market. For example, to get the companies listed on the Boursa:

Example 1

from amwal import Market

market = Market()
listing = market.listing()

The listing object is a pandas dataframe mirroring the listing page of the Boursa website.

To get the daily price bulletin for 05/05/2020 (day/month/year):

Example 2

from amwal import Market

market = Market()
bulletin = market.daily_bulletin("05/05/2020")

To get information on a specific company, we first get an object representing the company. The Market object has a method called get_corporation. It takes a valid ticker or stock number and returns a Corporation object. For example, to get zain's price history

Example 3

from amwal import Market
market = Market()
zain = market.get_corporation("zain")

we can now get information about Zain by calling the methods of the zain object. To get the price history, for example:

Example 3.1

price_history = zain.price_history()

This will return a dataframe containing price points streching back until 2004. To get Zain's yearly income statement, we call the yearly_income method:

Example 3.2

yearly_income = zain.yearly_income()

It's pretty straightforward



You may have noticed that an amwal_cache folder has been created in the path where the python interpreter was started. By default, data that is scraped is cached in the folder as JSON files.

You can change the name of the folder that Amwal uses to cache or retrieve results by supplying a cache_path argument to the Market constructor:

Example 4

market = Market(cache_path="another_cache")

You can also turn off the cache globally by doing the following

Example 5

from amwal.cache import JsonCache
JsonCache.enabled = False

Or for a single function call by passing the recompute=True argument

Example 6

zain = zain.price_history(recompute=True)

Be considerate

Don't DDOS the Boursa website with a million requests. Keep the cache enabled instead of repeatedly asking for the same resource. Limit your requests.


Pandas has many useful functions to serialize dataframes, or to convert from a dataframe into other representations. So if you want to save the data as a CSV or a JSON or convert into a numpy array, there are ways to do that, refer to the Pandas documentation.


You can get some output by passing a verbose=True argument to the scraping functions.


class Market(cache_path='amwal_cache', downloader=SyncDownloader) -> Market

  def daily_bulletin(self, date: str, verbose: bool = False, recompute: bool = False) > pandas.core.frame.DataFrame 
  #date should be a string formatted as dd/mm/yyyyy

  def listing(self, verbose: bool = False, recompute: bool = False) > pandas.core.frame.DataFrame 

  def is_stock_number(ident: str) > bool 

  def is_ticker(ident: str) > bool

  def get_corporation(self, ident: str, verbose: bool = False) > Corporation 

class Corporation (ident: str, market: Market, **kwargs)  
#You should not call this constructor directly, use get_corporation instead.

  def price_history(self, verbose: bool = False, recompute: bool = False) > pandas.core.frame.DataFrame 

  def quarterly_income(self, verbose: bool = False, recompute: bool = False) > pandas.core.frame.DataFrame 

  def yearly_income(self, verbose: bool = False, recompute: bool = False) > pandas.core.frame.DataFrame 


  • Update library to work with the new Boursa website.
  • Add balance sheet and cash flow statement methods to the corporation class.
  • Change scraping to be asynchronous.

Project details

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Files for amwal, version 0.0.5
Filename, size File type Python version Upload date Hashes
Filename, size amwal-0.0.5-py3-none-any.whl (11.1 kB) File type Wheel Python version py3 Upload date Hashes View
Filename, size amwal-0.0.5.tar.gz (11.3 kB) File type Source Python version None Upload date Hashes View

Supported by

AWS AWS Cloud computing Datadog Datadog Monitoring Facebook / Instagram Facebook / Instagram PSF Sponsor Fastly Fastly CDN Google Google Object Storage and Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Salesforce Salesforce PSF Sponsor Sentry Sentry Error logging StatusPage StatusPage Status page