Skip to content

Node.js / TypeScript quickstart ​

Compile a typed public-price request and WebSocket subscription with bybit-api, then run it in Node.js. No API key is needed. Prices are BTCUSDT last traded prices.

Create the project ​

Use Node.js 24 with npm. Download the complete TypeScript starter, or copy the files below.

sh
mkdir bybit-typescript-quickstart
cd bybit-typescript-quickstart

Copy the files below, or extract the downloaded archive into this directory (adjust the download path if needed):

sh
tar -xzf ~/Downloads/typescript.tar.gz

Install the dependencies after saving or extracting the files:

sh
npm install

The SDK installs from latest and includes its type definitions. This starter uses TypeScript 6.0.3. Its market.ts imports the SDK's constructor types so the compiler checks the REST methods and subscription arguments against the installed package.

Project files ​

package.json ​

json
{
  "name": "bybit-typescript-quickstart",
  "private": true,
  "type": "module",
  "scripts": {
    "check": "tsc --noEmit",
    "build": "tsc",
    "start": "npm run build && node dist/prices.js"
  },
  "dependencies": {
    "bybit-api": "latest"
  },
  "devDependencies": {
    "typescript": "6.0.3",
    "@types/node": "24.13.2"
  }
}

market.ts ​

ts
import type * as SDK from 'bybit-api';
type Sdk = typeof SDK;

export const endpoints = {"rest": "https://api.bybit.com/v5/market/tickers?category=spot&symbol=BTCUSDT", "websocket": "wss://stream.bybit.com/v5/public/spot"};
export function client(sdk: Sdk) { return new sdk.RestClientV5({}, {timeout:15000}); }
export async function read(client: InstanceType<Sdk['RestClientV5']>) {
  const response = await client.getTickers({ category: 'spot', symbol: 'BTCUSDT' });
  if (response.retCode !== 0) throw new Error(response.retMsg);
  return response.result.list[0].lastPrice;
}
export function stream(sdk: Sdk, logger?: ConstructorParameters<Sdk['WebsocketClient']>[1]) { return new sdk.WebsocketClient({}, logger); }
export const event = 'update';
export function value(message: any) { return message.topic === 'tickers.BTCUSDT' ? message.data?.lastPrice : undefined; }
export async function subscribe(ws: InstanceType<Sdk['WebsocketClient']>) { await Promise.all(ws.subscribeV5('tickers.BTCUSDT', 'spot')); }

price.ts ​

ts
import * as sdk from 'bybit-api';
import * as market from './market.js';

function positivePrice(value: unknown): string {
  if (!Number.isFinite(Number(value)) || Number(value) <= 0) {
    throw new Error('The exchange did not return a positive BTC price.');
  }
  return String(value);
}

export async function readPrice(): Promise<string> {
  return positivePrice(await market.read(market.client(sdk)));
}

// Returns cleanup without waiting for subscription acknowledgement.
export function watchPrice(onPrice: (price: string) => void, onError: (error: unknown) => void): () => void {
  const ws = market.stream(sdk);
  let stopped = false;
  const receive = (message: Parameters<typeof market.value>[0]) => {
    const value = market.value(message);
    if (!stopped && value !== undefined) {
      clearTimeout(deadline);
      try { onPrice(positivePrice(value)); } catch (error) { fail(error); }
    }
  };
  const fail = (error: unknown) => { if (!stopped) onError(error); };
  const deadline = setTimeout(() => fail(new Error('No BTC update within 30 seconds. Check network access.')), 30000);
  ws.on(market.event, receive);
  ws.on('exception', fail);
  // React may clean up an effect before its queued subscription starts.
  Promise.resolve().then(async () => {
    if (stopped) return;
    try {
      await market.subscribe(ws);
    } finally {
      // A connection may finish opening after cleanup was requested.
      if (stopped) ws.closeAll();
    }
  }).catch(fail);
  return () => {
    if (stopped) return;
    stopped = true;
    clearTimeout(deadline);
    ws.closeAll();
    ws.removeListener(market.event, receive);
    ws.removeListener('exception', fail);
  };
}

prices.ts ​

ts
import process from 'node:process';
import { readPrice, watchPrice } from './price.js';

async function main() {
  console.log('BTC REST price:', await readPrice());
  let stop: (() => void) | undefined;
  try {
    const price = await new Promise<string>((resolve, reject) => {
      stop = watchPrice(resolve, reject);
    });
    console.log('BTC WebSocket price:', price);
  } finally {
    stop?.();
    console.log('WebSocket closed.');
  }
}
main().catch(error => {
  console.error(error.message || String(error));
  process.exitCode = 1;
});

tsconfig.json ​

json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "skipLibCheck": true,
    "outDir": "dist",
    "types": [
      "node"
    ]
  },
  "include": [
    "*.ts"
  ]
}

Run ​

Check types without making any exchange requests:

sh
npm run check

Compile and run:

sh
npm start

npm start runs tsc and then node dist/prices.js. It stops on a compiler error. The script prints a REST price and one WebSocket price, closes the client in finally, and exits:

text
BTC REST price: 65000.5
BTC WebSocket price: 65001.2
WebSocket closed.

The NodeNext compiler settings follow Node.js module resolution. Relative imports name the emitted .js files even though the source files end in .ts. The selected WebSocket event payload is an untyped boundary; the shared price helper validates the numeric value before presenting it.

Troubleshooting ​

  • Run npm run check to see SDK method or argument errors before execution. Keep the included tsconfig.json when copying this starter.
  • If Node cannot find dist/prices.js, run npm run build first or use npm start, which builds automatically. This recipe uses tsc for type checking and compilation rather than relying on Node's type stripping.
  • If types cannot be resolved, run npm install and keep both development dependencies in package.json.
  • For HTTP failures or no update within 30 seconds, allow the exchange endpoints in market.ts from your network and region. See Runtime compatibility and Troubleshooting.

Built by Siebly. Open source SDKs for exchange APIs.