Get Crypto Data from Bybit

by John | April 28, 2023

Are you looking to take your cryptocurrency trading to the next level? Look no further than Bybit, the leading crypto derivatives exchange. With advanced trading tools, low fees, and a user-friendly platform, Bybit makes it easy to trade Bitcoin, Ethereum, and other popular cryptocurrencies. And if you sign up using our affiliate link  and use the referral code CODEARMO, you'll receive exclusive benefits and bonuses up to $30,000 to help you get started. Don't miss out on this opportunity to join one of the fastest-growing communities in crypto trading. Sign up for Bybit today and start trading like a pro!


If you haven't already installed Pybit please see the article on setting up an API key and installing Pybit. Once we have imported Pybit as shown below:


from pybit.unified_trading import HTTP
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import datetime as dt
import time 
import json

with open('authcreds.json') as j:
        creds = json.load(j)

key = creds['KEY_NAME']['key']
secret = creds['KEY_NAME']['secret']
session = HTTP(api_key=key, api_secret=secret, testnet=False)



In order to collect historical data from Bybit there are a number of parameters we must decide on prior to calling the API. For the purposes of this article we will be collecting USDT future perpetual contracts. Therefore the category we will use is 'linear' as shown below. 



Parameter Required Type Comments
category true string Product type. spot,linear,inverse,option
symbol false string Symbol name
baseCoin false string Base coin. For option only
expDate false string Expiry date. e.g., 25DEC22. For option only



Get List of  Available USDT Perpetuals Bybit 


A cryptocurrency ticker is a symbol or abbreviation that represents a particular cryptocurrency, similar to how stock symbols represent publicly traded companies.

Cryptocurrency tickers are typically a combination of letters and numbers that are used to uniquely identify a particular cryptocurrency. For example, Bitcoin's ticker is "BTC", Ethereum's ticker is "ETH", and so on.

Cryptocurrency tickers are used to track the performance of a particular cryptocurrency and to provide easy reference when discussing or trading that cryptocurrency. When you look up a cryptocurrency on a trading platform or a price tracker, you'll typically see its ticker symbol displayed alongside its current price and other information.




result = session.get_tickers(

tickers = [asset['symbol'] for asset in result if asset['symbol'].endswith('USDT')]


This will print out a total list of which USDT perps Bybit currently offer. Users can then select an asset to download historical data in the next section. 




Get Historical Daily Data


Once we have chosen a USDT perpetual we can proceed to collecting data. The table below shows the arguments we need to be aware of to retrieve historical data. Note that the interval parameter shown in the table below relates to the data frequency i.e. 1 = 1 minute. 


Request Arguments


Parameter Required Type Comments
category true string Product type. spot, linear, inverse
symbol true string Symbol name
interval true int/string Kline interval. 1, 3, 5, 15, 30, 60, 120, 240, 360, 720, D, M, W
start false integer The start timestamp (ms)
end false integer The end timestamp (ms)


The table below shows the response parameters , the function format_data above extracts the information in the list from the API and formats them in to a pandas dataframe. 


Request Response


Parameter Type Comments
category string Product type
symbol string Symbol name
list array An string array of individual candle
  • Sort in reverse by startTime
  • list[0]: startTime - Start time of the candle (ms)
  • list[1]: openPrice - Open price
  • list[2]: highPrice - Highest price
  • list[3]: lowPrice - Lowest price
  • list[4]: closePrice - Close price. Is the last traded price when the candle is not closed
  • list[5]: volume - Trade volume. Unit of contract: pieces of contract. Unit of spot: quantity of coins
  • list[6]: turnover - Turnover. Unit of figure: quantity of quota coin



The python script below calls the get_kline method from Pybit. Note that we do not pass the start/end timestamp argument, which we will come back to later in the article. 



response = session.get_kline(category='linear', 

def format_data(response):

    respone : dict
        response from calling get_klines() method from pybit.

    dataframe of ohlc data with date as index

    data = response.get('list', None)
    if not data:
    data = pd.DataFrame(data,
                        columns =[
    f = lambda x: dt.datetime.utcfromtimestamp(int(x)/1000)
    data.index = data.timestamp.apply(f)
    return data[::-1].apply(pd.to_numeric)

df = format_data(response)


               timestamp         open  ...        volume      turnover
timestamp                              ...                            
2022-10-12  1.665533e+12  1279.300049  ...  7.275909e+05  9.415818e+08
2022-10-13  1.665619e+12  1293.849976  ...  2.185120e+06  2.725300e+09
2022-10-14  1.665706e+12  1286.500000  ...  1.124476e+06  1.480705e+09
2022-10-15  1.665792e+12  1295.650024  ...  5.074429e+05  6.510826e+08
2022-10-16  1.665878e+12  1274.250000  ...  5.975026e+05  7.729099e+08
                 ...          ...  ...           ...           ...
2023-04-25  1.682381e+12  1841.000000  ...  8.319169e+05  1.524671e+09
2023-04-26  1.682467e+12  1865.099976  ...  1.701774e+06  3.202957e+09
2023-04-27  1.682554e+12  1865.209961  ...  1.035564e+06  1.968957e+09
2023-04-28  1.682640e+12  1907.699951  ...  5.036653e+05  9.560499e+08
2023-04-29  1.682726e+12  1890.010010  ...  2.651855e+05  5.038554e+08

[200 rows x 7 columns]      



The problem with this approach is that we are constrained to only 200 rows of data. Therefore if we want data exceeding (in this case) 200 days we have to make multiple function calls. Let's say we wanted to get hourly data for DOGE since the start of 2023. We will have to make multiple API calls. 


def get_last_timestamp(df):
    return int(df.timestamp[-1:].values[0])

start = int(dt.datetime(2023, 1, 1).timestamp()* 1000)

interval = 60
symbol = 'DOGEUSDT'
df = pd.DataFrame()

while True:
    response = session.get_kline(category='linear', 
    latest = format_data(response)
    if not isinstance(latest, pd.DataFrame):
    start = get_last_timestamp(latest)
    df = pd.concat([df, latest])
    print(f'Collecting data starting {dt.datetime.fromtimestamp(start/1000)}')
    if len(latest) == 1: break

df.drop_duplicates(subset=['timestamp'], keep='last', inplace=True)


Cool now we have hourly data!






Get Orderbook Data


A cryptocurrency order book is similar to the order book for any other asset, but it's specific to cryptocurrencies like Bitcoin or Ethereum.

In a cryptocurrency order book, you'll see the current bids and asks for a particular cryptocurrency, along with the amount of cryptocurrency being offered and the price being asked for it.

On the buy side, people place bids to purchase a certain amount of cryptocurrency at a specific price. On the sell side, people place asks to sell a certain amount of cryptocurrency at a specific price.

The order book will typically show the highest bids and lowest asks at the top, with lower bids and higher asks listed further down. This provides traders with an idea of the current market depth and the supply and demand of the cryptocurrency.




Traders use the information in the order book to make informed decisions about when to buy or sell cryptocurrency. For example, if there are a lot of buy orders at a certain price level, it may indicate that demand for the cryptocurrency is increasing and that the price is likely to rise. Conversely, if there are a lot of sell orders at a certain price level, it may indicate that there is a lot of supply and that the price is likely to fall.



response = session.get_orderbook(

def format_order_book(response):

    response : dict
    two list of lists containing bid/ask price with associated volume

    bids = response.get('b')
    asks = response.get('a')
    return bids, asks

bids, asks = format_order_book(response)          

for bid in bids:
    print(f'Bid price - {bid[0]} , quantity = {bid[1]}')

Bid price - 0.081 , quantity = 1177521
Bid price - 0.08099 , quantity = 936765
Bid price - 0.08098 , quantity = 541063
Bid price - 0.08097 , quantity = 483457
Bid price - 0.08096 , quantity = 1211693



Get Open Interest Data


Open interest is the total number of outstanding futures contracts that have not been settled or closed out by an offsetting trade. In other words, it represents the number of contracts that are currently open or active in the market.


When someone buys or sells a futures contract, the open interest increases by one. When someone closes out a position by selling or buying a contract to offset their original trade, the open interest decreases by one.


Open interest is an important indicator of market liquidity and sentiment, as it represents the number of market participants who are actively trading a particular futures contract. High open interest suggests that there is a lot of trading activity and interest in the contract, while low open interest may indicate that the market is less active or less popular. 


The input arguments are similar to the get_klines method we used previously. However, the interval seems to be different for some reason. Also note the loop through the dictionaries, this is due to the fact that Pandas doesn't seem to like the 7 trailing zeros , and sometimes returns NaN and sometimes doesn't! So we use a suboptimal solution as shown below. 


Parameter Required Type Comments
category true string Product type. linear,inverse
symbol true string Symbol name
intervalTime true string Interval. 5min,15min,30min,1h,4h,1d
startTime false integer The start timestamp (ms)
endTime false integer The end timestamp (ms)
limit false integer Limit for data size



def format_oi(response):

    respone : dict
        response from calling get_open_interest

    dataframe of open interest and timestamp

    data = response.get('list', None)
    if not data:
    ois =[] 
    tss = []
    for row in data:
        oi = float(row.get('openInterest'))
        ts = int(row.get('timestamp'))
    data = pd.DataFrame()
    data['open_interest'] = ois
    data['timestamp'] = tss
    f = lambda x: dt.datetime.utcfromtimestamp(int(x)/1000)
    data.index = data.timestamp.apply(f)
    return data[::-1]

response = session.get_open_interest(

oi = format_oi(response)

                     openInterest     timestamp
2023-04-28 01:00:00   934277376.0  1.682644e+12
2023-04-28 02:00:00   935817856.0  1.682647e+12
2023-04-28 03:00:00   935150784.0  1.682651e+12
2023-04-28 04:00:00   934870976.0  1.682654e+12
2023-04-28 05:00:00   933942976.0  1.682658e+12



If you want to get open interest data for longer than 200 periods, you can apply the same logic as we used for the get_klines method previously. 


Join the discussion

Share this post with your friends!