XBTXBJETHETCXMRXRPREPLTCLSKFCTBFXZECRecentAllXRP7D0.00001237-3.28%XMR7D0.009220+2.82%REP7D0.007629+2.49%BFXV160.5901+1.99%ZECZ160.783768+108.70%XBTUSD684.50+2.01%XBTZ16716.13+1.80%XBJ24H72547+4.35%XBJ7D72646+3.50%XBJZ1675363+2.85%ETHXBT0.01689-0.65%ETC7D0.001454-5.03%LTCXBT0.00587+2.98%LSKXBT0.000274-1.79%FCTXBT0.003871-1.10%XBT/USD Spot682.77+1.81%XBT/JPY Spot72482.99+3.45%ETH/XBT Spot0.01685-1.17%ZEC/XBT Spot--.-+0.00%24H XBT Volatility1.40-32.04%Funding:  @ 0.0399%Time:
WebSocket API

BitMEX offers a complete pub/sub API with table diffing over WebSocket. You may subscribe to real-time changes on any available table.


Connect your websocket client to wss://www.bitmex.com/realtime.

You can get a basic idea of how to use our websocket API by sending "help".

All Commands

A basic command is sent in the following format:

{"op": "<command>", "args": ["arg1", "arg2", "arg3"]}

The args array is optional on some commands. If you are only sending a single argument, the array is not necessary.

Note that placing and canceling orders is not supported via the Websocket. Please use the REST API for this. When using HTTP Keep-Alive, request/response round-trip time will be identical to Websocket.


BitMEX allows subscribing to real-time data. This access is not rate-limited and is the best way to get the most up-to-date data to your programs.

To subscribe to topics, send them as a comma-separated list in your connection string. For example:


If you are already connected and wish to subscribe to a new topic, send a message with the following format:

{"op": "subscribe", "args": [<SubscriptionTopic>]}

You may subscribe to multiple topics at a time by sending an array of subscription topics.

The following subscription topics are available without authentication:

"chat",        // Trollbox chat
"connected",   // Statistics of connected users/bots
"instrument",  // Instrument updates including turnover and bid/ask
"insurance",   // Daily Insurance Fund updates
"liquidation", // Liquidation orders as they're entered into the book
"orderBookL2", // Full level 2 orderBook
"orderBook10", // Top 10 levels using traditional full book push
"orderBook",   // Top 50 levels using deltas (deprecated)
"orderBook25", // Top 25 levels using deltas (deprecated)
"publicNotifications", // System-wide notifications
"quote",       // Top level of the book
"quoteBin1m",  // 1-minute quote bins
"settlement",  // Settlements
"trade",       // Live trades
"tradeBin1m",  // 1-minute ticker bins

The following subjects require authentication:

"affiliate",   // Affiliate status, such as total referred users & payout %
"execution",   // Individual executions; can be multiple per order
"order",       // Live updates on your orders
"margin",      // Updates on your current account balance and margin requirements
"position",    // Updates on your positions
"privateNotifications", // Individual notifications - currently not used
"transact"     // Deposit/Withdrawal updates
"wallet"       // Bitcoin address balance data, including total deposits & withdrawals

If you wish to get real-time order book data, we recommend you use the orderBook10 subscription rather than the orderBookL2 subscription. orderBook10 pushes a full 10-level book upon any change, while orderBookL2 pushes only the deltas. While orderBookL2 is more efficient and pushes changes on the full book, it is more difficult to program for and may not be worth the effort for most applications.

When applicable, subjects may be filtered to a given instrument by appending a colon and instrument name. For example, trade:XBTN14 will subscribe you to messages only for the XBTN14 instrument.

Upon subscription, you will receive an image of the existing data, so you can get started. This comes through as a partial action.

For example:

> {"op": "subscribe", "args": ["orderBookL2:XBT24H"]}
  < {"success":true,"subscribe":"orderBookL2:XBT24H","request":{"op":"subscribe","args":["orderBookL2:XBT24H"]}}
  < {
      "types":{"symbol":"symbol","level":"long", ...}
        {"symbol":"XBT24H","level":0, ...}
        {"symbol":"XBT24H","level":1, ...}
        {"symbol":"XBT24H","level":2, ...}
        {"symbol":"XBT24H","level":3, ...}

You may unsubscribe using the 'unsubscribe' operation. The formatting is identical to 'subscribe'.


A number of data streams are publicly available (see below). If you wish to subscribe to user-locked streams, you must authenticate first. Note that invalid auth will close the connection.

In the following examples, all key/value pairs may also be sent as HTTP headers.

There are three methods of authentication available.

1. Email / Password

You can authenticate directly with your email and password.

To authenticate, send your email and password when connecting to the websocket. If you have two-factor authentication enabled on your account, send your OTP password as otpToken. For example:


2. Access Token

If you are using the REST API as well, you may have an Access Token handy.

You can use that token to authenticate by sending the accessToken key. If the websocket library you use cannot send querystrings, use an authentication header instead. Your connection string will look something like:


Access Tokens retrieved via the API expire every 24 hrs. If you wish to extend your session, you have two options:

{"op": "authToken", "args": "<token>"} // if you have a token
{"op": "authLogin", "args": ["<email>", "<password>", "<otpToken>"]} // with email/pass/optional otpToken

Either request will extend your session.

3. Permanent API Key

Permanent API Keys are the best form of authentication for your tools, as they can be locked to IP address ranges and revoked at will without compromising your main credentials. They also do not require renewal, but they are slightly more involved to implement.

To use API Key auth, you must generate an API Key.

To use an API Key with websockets, you must sign the initial upgrade request in the same manner you would sign other REST calls. On connection, send an "authKey", with a signature as if you were signing GET /realtime. See this Python implementation for an example and working code.

// signature is hex(HMAC_SHA256(secret, 'GET/realtime' + nonce))
// nonce must be a number, not a string
{"op": "authKey", "args": ["<APIKey>", <nonce>, "<signature>"]}


Some WebSocket libraries are better than others at detecting connection drops. If your websocket library supports hybi-13, or ping/pong, you may send a ping at any time and the server will return with a pong.

The server also supports expectant pings using the ?heartbeat=true query. This will expect the client to send the message ping every 25 seconds. The server will respond with a pong message immediately. We recommend waiting up to 5 seconds for this message, then closing and reconnecting.

If you use this option, note that the server will close the connection automatically if a heartbeat or other traffic is not received within 35 seconds.

Dead Man’s Switch (Auto Cancel)

BitMEX offers “Dead Man’s Switch” functionality to help prevent unexpected losses from network malfunctions. If you are putting up significant risk on BitMEX, it can be nerve-wracking to think of what might happen if you or your datacenter loses connectivity.

Via REST at /order/cancelAllAfter or via WebSocket via the example below, one can set a millisecond timeout. This will start a timer. If cancelAllAfter is not called again before time runs out, all of your existing orders on all symbols will be canceled.

To cancel this operation and keep your orders open, pass a timeout of 0.

Advanced users of BitMEX should use this operation. A common use pattern is to set a timeout of 60000, and call it every 15 seconds. This gives you sufficient wiggle room to keep your orders open in case of a network hiccup, while still offering significant protection in case of a larger outage. Of course, the parameters are up to you.

We recommend not setting a timeout of less than 5 seconds to avoid being rate limited or having your orders unexpectedly canceled in case of network congestion.

For example:

// Places a dead man's switch at 60 seconds.
> {"op": "cancelAllAfter", "args": 60000}
  < {"now":"2015-09-02T14:18:43.536Z","cancelTime":"2015-09-02T14:19:43.536Z","request":{"op":"cancelAllAfter","args":60000}}
// Cancels the switch.
> {"op": "cancelAllAfter", "args": 0}
  < {"now":"2015-09-02T14:19:11.617Z","cancelTime":0,"request":{"op":"cancelAllAfter","args":0}}

Response Format

Websocket responses may be of the following three types:

Success: (Emitted upon a successful subscription to a topic)

{"subscribe": subscriptionName, "success": true}

Error: (Emitted upon a malformed request or an attempt to request a locked resource)

{"error": errorMessage}

Data: (Emitted when data is available or requested)

  // Table name / Subscription topic.
  // Could be "trade", "order", etc.
  "table": tableName,

  // The type of the message. Types:
  // 'partial'; This is a table image, replace your data entirely.
  // 'update': Update a single row.
  // 'insert': Insert a new row.
  // 'delete': Delete a row.
  "action": actionName

  // Attribute names that are guaranteed to be unique per object.
  // If more than one is provided, the key is composite.
  // Use these key names to uniquely identify rows. Key columns are guaranteed
  // to be present on all data received.
  "keys": [keyName1, keyName2],

  // An array of objects is emitted here. They are identical in structure to data returned from the REST API.
  "data": [Object, Object, Object....]

Reference Implementation

We have a reference implementation of the websocket as part of our reference Market Maker.

Of interest is the __on_message function, which handles updating tables in memory.

Data Example

Outgoing messages are prefixed with >. Incoming messages are prefixed with <.

Using the python tool wsdump:

~/g/f/w/bin (master|✔) $ python wsdump.py wss://www.bitmex.com/realtime/websocket?accessToken=xnyXWIQL0sbrLC91ISDlFhuLUGQJNq05A...
Press Ctrl+C to quit

  < {"info":"Welcome to the BitMEX Realtime API.","version":"1.1.0","timestamp":"2015-01-18T10:14:06.802Z","docs":"https://www.bitmex.com/app/wsAPI","heartbeatEnabled":false}

> "help"

  < {"info":"See https://www.bitmex.com/app/wsAPI and https://www.bitmex.com/explorer for more documentation.",...}

> {"op": "subscribe", "args": ["trade:XBT24H", "orderBook10:XBT24H", "instrument:XBT24H"]}

  < {"success":true,"subscribe":"trade:XBT24H","request":{"op":"subscribe","args":["trade:XBT24H","orderBook10:XBT24H","instrument:XBT24H"]}}
  < {"success":true,"subscribe":"orderBook10:XBT24H","request":{"op":"subscribe","args":["trade:XBT24H","orderBook10:XBT24H","instrument:XBT24H"]}}
  < {"success":true,"subscribe":"instrument:XBT24H","request":{"op":"subscribe","args":["trade:XBT24H","orderBook10:XBT24H","instrument:XBT24H"]}}

  < {"table":"trade","action": "partial", ...}
  < {"table":"orderBook10","action": "partial", ...}
  < {"table":"instrument","action": "partial", ...}

  < {"table":"instrument","action":"update","data":[{"symbol":"XBT24H","fairPrice":380.52,"markPrice":380.52,"indicativeSettlePrice":380.52,"timestamp":"2016-01-15T22:33:15.000Z"}]}
  < {"table":"instrument","action":"update","data":[{"symbol":"XBT24H","openValue":673520400,"timestamp":"2016-01-15T22:33:15.000Z"}]}


This is intended for advanced users only.

The BitMEX Websocket supports a very simple multiplexing scheme. Use this in place of many individual connections.

The most common use case is to keep a stream open for market data, and multiple streams for individual subaccounts.

Multiplexing has a different endpoint. Use /realtimemd (that’s “realtime-mux-demux”) for multiplexing capabilities.

The protocol is very simple:

Packet Format:



  • type: See “Packet Types” below.
  • id: Client-selected unique ID for this stream. This can be arbitrary; consider using a unique identifier like userID.
  • topic: Client-selected non-unique purpose for this stream. This is required but can be any string you wish.
    • Note: All returned messages will include the id and topic. Unsubscribing is done via id.
  • payload: For MESSAGE types, the payload is exactly equal to any message one would send via a non-multiplexed stream.

Packet Types:

  • MESSAGE: 0
    • When a stream is opened, use this type to send a message on a given topic.
    • Use to open a stream. Both id and topic may contain any data but must be unique.
    • Use to close a stream. id must match the one used for the subscription.

Outgoing messages are prefixed with >. Incoming messages are prefixed with <.

# Create stream with an id of hudsyg1q5dda4, topic of user_1
> [1, "hudsyg1q5dda4", "user_1"]
# A welcome message greets you.
< [0, "hudsyg1q5dda4", "user_1",{"info":"Welcome to the BitMEX Realtime API.",...}]

# The stream is created! The stream acts exactly like any other WS connection, just framed with type and id.

# Authenticate inside that stream - see authentication above
> [0, "hudsyg1q5dda4", "user_1", {"op": "authToken", "args": ["pV1CPhfZWUlZM93v..."]}]
< [0, "hudsyg1q5dda4", "user_1", {"success":true,"expiry":1469034456847,...}]

# Subscribe to a private table.
> [0, "hudsyg1q5dda4", "user_1", {"subscribe": "position"}]
# One message confirms the subscription,
< [0, "hudsyg1q5dda4", "user_1", {"success":true,"subscribe":"position","request":{"subscribe":"position"}}]
# And another sends the first partial.
< [0, "hudsyg1q5dda4", "user_1", {"table":"position","action":"partial","keys":["account","symbol", ...]}]

# Data will flow from here on out.

# To close a stream:
> [2, "hudsyg1q5dda4", "user_1"]
# A confirmation echo is sent from the server.
< [2, "hudsyg1q5dda4", "user_1"]