If you have ever tried to build a single trading dashboard that pulls order book data from Binance, OKX, and Bybit at the same time, you already know the pain: every exchange speaks its own JSON dialect. Symbols are spelled differently, prices arrive as strings instead of numbers, update IDs are called different things, and timestamps are wrapped in nested objects on some venues and flat on others. After a few hours of debugging KeyError and TypeError messages, most beginners give up and just pick one exchange.

This tutorial is written for absolute beginners. We will start from zero, look at the raw payload from each exchange side by side, then design a single unified schema, and finally write a small Python normalizer that converts all three into the same shape. By the end, your strategy code will not need to know which exchange the data came from, and you will be able to swap venues by editing a single config line.

Along the way I will show you how to plug this pipeline into the HolySheep Tardis-style crypto market data relay (Sign up here), which already delivers normalized trades, order book deltas, liquidations, and funding rates from Binance, OKX, Bybit, and Deribit through one WebSocket. That removes about 80 percent of the glue code you would otherwise have to maintain yourself.

Who this guide is for — and who it is not for

It is for you if:

It is NOT for you if:

Step 1 — what a "depth snapshot" actually is

Think of an order book like a stadium. Each row has a price and a pile of people willing to buy or sell at that price. A "depth snapshot" is one photograph of the whole stadium at one millisecond. Most exchanges also send "delta" updates between snapshots — small diff messages that say "row 17 just got 12 more buyers." For this tutorial we focus on the snapshot; the deltas use the same unified schema once you normalize the snapshot.

A snapshot normally contains:

Step 2 — the raw payload from each exchange

Here is the exact JSON shape each exchange sends on its REST depth endpoint. Open these in any text editor side by side and you will see the differences immediately.

Binance — https://fapi.binance.com/fapi/v1/depth?symbol=BTCUSDT&limit=5

{
  "lastUpdateId": 1234567890123,
  "E": 1717000000000,
  "T": 1717000000999,
  "bids": [
    ["67890.10", "1.234"],
    ["67890.00", "2.500"],
    ["67889.90", "0.800"]
  ],
  "asks": [
    ["67890.20", "0.500"],
    ["67890.30", "1.000"],
    ["67890.40", "3.200"]
  ]
}

OKX — https://www.okx.com/api/v5/market/books?instId=BTC-USDT-SWAP&sz=5

{
  "code": "0",
  "msg": "",
  "data": [{
    "instId": "BTC-USDT-SWAP",
    "ts": "1717000000100",
    "bids": [
      ["67890.1", "1.234", "0", "4"],
      ["67890.0", "2.5",   "0", "8"]
    ],
    "asks": [
      ["67890.2", "0.5",   "0", "2"],
      ["67890.3", "1.0",   "0", "3"]
    ]
  }]
}

Bybit — https://api.bybit.com/v5/market/orderbook?category=linear&symbol=BTCUSDT&limit=5

{
  "retCode": 0,
  "retMsg": "OK",
  "result": {
    "s": "BTCUSDT",
    "ts": 1717000000200,
    "bids": [
      ["67890.10", "1.234"],
      ["67890.00", "2.500"]
    ],
    "asks": [
      ["67890.20", "0.500"],
      ["67890.30", "1.000"]
    ],
    "u": 987654321,
    "seq": 12345
  }
}

Notice four confusing things a beginner will hit immediately:

  1. Symbol spelling: Binance and Bybit use BTCUSDT; OKX uses BTC-USDT-SWAP.
  2. Timestamp units: Binance uses E

    Related Resources

    Related Articles