Skip to content

Vite (plain JavaScript) quickstart ​

Build a page that displays a public BTC REST price and live WebSocket updates from binance. No API key is needed. Prices are BTCUSDT last traded prices.

Create the project ​

Use Node.js with npm. Download the complete Vite starter, or create an empty directory and copy all files below.

sh
mkdir binance-vite-quickstart
cd binance-vite-quickstart

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

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

Install the dependencies after saving or extracting the files:

sh
npm install

The SDK installs from latest. Vite 5.4.21 is the tested build tool. Keep the supplied Vite config: it resolves the events polyfill and selects Binance browser support. See Runtime compatibility for the recorded browser execution results.

Project files ​

package.json ​

json
{
  "name": "binance-vite-quickstart",
  "private": true,
  "type": "module",
  "scripts": {
    "dev": "vite --host 127.0.0.1",
    "build": "vite build",
    "preview": "vite preview --host 127.0.0.1"
  },
  "dependencies": {
    "binance": "latest",
    "events": "3.3.0"
  },
  "devDependencies": {
    "vite": "5.4.21"
  }
}

market.js ​

js
export const endpoints = {"rest": "https://api.binance.com/api/v3/ticker/price?symbol=BTCUSDT", "websocket": "wss://stream.binance.com:9443"};
export function client(sdk) { return new sdk.MainClient({}, {timeout:15000}); }
export async function read(client) {
  const response = await client.getSymbolPriceTicker({ symbol: 'BTCUSDT' });
  if (Array.isArray(response)) throw new Error('Expected one ticker');
  return response.price;
}
export function stream(sdk, logger) { return new sdk.WebsocketClient({}, logger); }
export const event = 'message';
export function value(message) { return message.e === '24hrTicker' ? message.c : undefined; }
export async function subscribe(ws) { await ws.subscribeSpotSymbol24hrTicker('btcusdt'); }

price.js ​

js
import * as sdk from 'binance';
import * as market from './market.js';

function positivePrice(value) {
  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() {
  return positivePrice(await market.read(market.client(sdk)));
}

// Returns cleanup without waiting for subscription acknowledgement.
export function watchPrice(onPrice, onError) {
  const ws = market.stream(sdk);
  let stopped = false;
  const receive = message => {
    const value = market.value(message);
    if (!stopped && value !== undefined) {
      clearTimeout(deadline);
      try { onPrice(positivePrice(value)); } catch (error) { fail(error); }
    }
  };
  const fail = error => { 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);
  };
}

index.html ​

html
<!doctype html>
<html lang="en">
  <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width"><title>BTC price</title></head>
  <body>
    <h1>BTC price</h1>
    <p>REST: <output id="rest">Loading</output></p>
    <p>WebSocket: <output id="live">Connecting</output></p>
    <p id="error" role="alert"></p>
    <button id="stop" type="button">Stop stream</button>
    <script type="module" src="/main.js"></script>
  </body>
</html>

main.js ​

js
import { readPrice, watchPrice } from './price.js';

const showError = error => { document.querySelector('#error').textContent = error.message || String(error); };
readPrice().then(price => { document.querySelector('#rest').textContent = price; }).catch(showError);
const stop = watchPrice(price => { document.querySelector('#live').textContent = price; }, showError);
document.querySelector('#stop').addEventListener('click', () => {
  stop();
  document.querySelector('#live').textContent = 'Stopped';
});
window.addEventListener('pagehide', stop, { once: true });
if (import.meta.hot) import.meta.hot.dispose(stop);

vite.config.js ​

js
import {fileURLToPath} from 'node:url';

const utilDirectory = fileURLToPath(new URL('./node_modules/binance/lib/util/', import.meta.url));

export default {
  resolve: {
    alias: {
      events: fileURLToPath(new URL('./node_modules/events/events.js', import.meta.url)),
    },
  },
  plugins: [{
    name: 'binance-browser-support',
    enforce: 'pre',
    resolveId(source, importer) {
      if (source === './node-support' && importer?.startsWith(utilDirectory)) {
        return utilDirectory + 'browser-support.js';
      }
    },
  }],
};

Run ​

sh
npm run dev

Open the URL printed by Vite, normally http://localhost:5173/. The page shows a REST price and a changing WebSocket price. Click Stop stream to close the client. Navigation and Vite hot replacement also close the connection.

To check the production bundle:

sh
npm run build
npm run preview

Open the preview URL printed by Vite. Both price fields should contain positive numbers, such as 65000.5. REST and streaming prices may differ.

Troubleshooting ​

  • An events resolution error means the dependency or Vite config is missing. Keep the supplied browser-support selection in the same config. Copy the config exactly and restart Vite.
  • Run the page through Vite, rather than opening index.html directly. Check the browser network panel for blocked REST or WSS requests. The exchange must permit your origin and region; a successful bundle alone does not prove network access.
  • Keep private keys and API secrets on a server. This page uses public market data. See WebSocket subscriptions for subscription details.

Built by Siebly. Open source SDKs for exchange APIs.