Streaming Real-Time Prices over WebSocket
If your app shows a live price, a REST endpoint polled every second is the obvious first attempt, and it does not scale well. A WebSocket keeps one connection open and the server pushes updates as they happen. This guide explains when that is worth it, how to keep a connection healthy, and how to subscribe to a live XAUUSD feed in a few lines of JavaScript.
WebSocket vs REST polling
With polling, the client asks "anything new?" on a timer. Most answers are "no", every request pays for a full HTTP round trip and counts against your quota, and the data you see is up to one polling interval old.
A WebSocket is a single long-lived connection. After the handshake, the server sends a message whenever there is new data. You get updates with less delay, far fewer requests, and less work on both ends.
- Use REST for history, snapshots, indicators on demand, and anything you fetch once or rarely.
- Use WebSocket for live tickers, dashboards, alerts and bots that react to each new price.
- Many apps use both: load history over REST, then append live updates from the stream.
Connecting to a price stream
RealMarketAPI streams live prices at wss://api.realmarketapi.com/price. Authentication and the subscription go in the query string: your apiKey, the symbolCode and the timeFrame. Each message is JSON with the latest price data for that symbol.
The example below uses the browser's built-in WebSocket API. In Node.js, the same code works with the ws package.
const url =
"wss://api.realmarketapi.com/price" +
"?apiKey=YOUR_KEY&symbolCode=XAUUSD&timeFrame=M1";
const socket = new WebSocket(url);
socket.onopen = () => console.log("connected");
socket.onmessage = (event) => {
const tick = JSON.parse(event.data);
console.log("XAUUSD", tick);
};
socket.onerror = (err) => console.error("socket error", err);
socket.onclose = (event) => console.log("closed", event.code, event.reason);Reconnecting with backoff
Connections drop: laptops sleep, mobile networks switch, servers deploy. Your client should expect this and reconnect on its own. Reconnecting immediately in a tight loop is the classic mistake; if the server is briefly unavailable, thousands of clients hammering it at once keep it down.
Use exponential backoff with jitter: wait about 1 second, then 2, 4, 8, up to a cap such as 30 seconds, adding a random offset so clients do not retry in sync. Reset the delay once a connection has been stable for a while.
function connect(url, onTick, attempt = 0) {
const socket = new WebSocket(url);
socket.onopen = () => { attempt = 0; };
socket.onmessage = (event) => onTick(JSON.parse(event.data));
socket.onclose = () => {
const base = Math.min(30000, 1000 * 2 ** attempt);
const delay = base / 2 + Math.random() * (base / 2);
setTimeout(() => connect(url, onTick, attempt + 1), delay);
};
return socket;
}Heartbeats and stale connections
A connection can look open while no data is flowing: a proxy silently dropped it, or the network changed underneath. The WebSocket protocol has ping and pong frames for this, but browsers do not expose them to JavaScript.
The practical answer in a browser is a watchdog. Remember when the last message arrived; if nothing has arrived for longer than you would expect for that symbol and timeframe, close the socket and let the reconnect logic take over. On a server (for example Node.js with ws) you can send protocol pings and drop connections that do not answer.
- Pick the timeout from real traffic. Quiet markets and weekends produce fewer updates; do not reconnect just because the market is closed.
- Show the user when data is stale instead of silently displaying an old price.
- Close sockets you no longer need, for example when a component unmounts.
Other streaming routes
The price stream is the simplest one. RealMarketAPI exposes several other WebSocket routes on the same host, using the same apiKey query parameter. Which symbols and timeframes you can subscribe to depends on your plan.
- /candles: live candle updates for a symbol and timeframe.
- /multi-timeframe: one symbol across several timeframes at once.
- /orderflow/imbalance: order flow imbalance data.
- /market: broader market updates.
Common mistakes
Most WebSocket bugs are lifecycle bugs rather than protocol bugs.
- Opening a new socket on every render or every symbol change without closing the old one.
- Putting a secret API key in public front-end code. In production, proxy the stream through your own backend or use a key you are prepared to rotate.
- Assuming messages arrive in order after a reconnect, or that none were missed. Refill gaps from the REST history endpoint.
- Doing heavy work inside onmessage. Parse, store, and render on the next animation frame instead.
Frequently asked questions
Does a WebSocket connection use my request quota?
How streaming is counted depends on your plan. Check the pricing and documentation pages for the current rules before you open many connections.
Can I subscribe to several symbols?
Each connection is opened for the symbol and timeframe in its query string. To follow several symbols, open one connection per subscription, or use a route such as /multi-timeframe where it fits your use case.
Why do I get disconnected after a while?
Idle timeouts in proxies, load balancers or the network are the usual cause. Reconnect with backoff, and treat a long silence as a sign the connection may be stale.
Should I use WebSocket or REST for a trading bot?
Use WebSocket to react to new prices and REST to load history at startup and to fill any gaps after a reconnect.
Want to build on real data?
RealMarketAPI gives you REST and WebSocket access to forex, gold and crypto prices, candles and indicators. Start with the docs or grab a free API key.