XRPL WebSocket API: Real-Time Token Prices & Market Data
Instead of asking the API for prices every few seconds, open one WebSocket and xrpl.to sends each change as the ledger produces it. The streams there are, a subscription that works, and what actually comes back.
The streams
| /ws/sync/ | Prices and market data for a list of tokens, or the top of the market by volume |
| /ws/token/{md5} | Every change to one token, optionally only the fields that changed |
| /ws/ohlc/{md5} | Candles as they form, at 1 minute to 1 week |
| /ws/history/{md5} | Each trade in a token as it fills |
| /ws/orderbook | Order book depth for a pair |
| /ws/ledger | Each ledger as it closes |
| /ws/account/watch/{account} | An account’s activity, as readable events |
| /ws/news | News stories as they are published |
wss://api.xrpl.to; the full list, with each stream’s options, is in the API docs.Subscribing to prices
const ws = new WebSocket('wss://api.xrpl.to/ws/sync/');
ws.onopen = () => {
ws.send(JSON.stringify({
type: 'subscribe',
tokens: ['0dd550278b74cb6690fdae351e8e0df3'], // token md5s
lightweight: true, // the essential fields only
}));
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.type === 'subscribed') return; // the acknowledgement
if (msg.snapshot) render(msg.tokens); // current state, once
else if (msg.seq) update(msg.tokens, msg.seq); // changes; may be empty
};
// Reconnect with growing delays when the socket closes.{
"type": "subscribe",
"tokens": [
"0dd550278b74cb6690fdae351e8e0df3"
],
"lightweight": true,
"skip_metrics": true
}{
"res": "success",
"snapshot": true,
"seq": 1501,
"time": 1792387911108,
"count": 1,
"tokens": [
{
"md5": "0dd550278b74cb6690fdae351e8e0df3",
"name": "RLUSD",
"exch": 0.762471760532176,
"pro24h": -1.4321792493104502,
"vol24hxrp": 3092792.208121,
"marketcap": 777906798.0382205,
"holders": 67589,
"tvl": 3687370.976908
}
]
}What arrives, in order
- A welcome frame on connecting, with the market’s totals.
- The acknowledgement,
type: "subscribed", echoing the md5s you asked for. - A snapshot of every subscribed token as it stands (skip it with
snapshot: false). - Updates with a
seqnumber and the tokens that changed; a quiet market sends empty ones now and then, as a heartbeat.
Instead of a list, you can subscribe to the top of the market with filter: { topN, minVolume, tags }, and change the list later with addTokens and removeTokens.
Staying connected
- Gaps: compare each update’s
prevSeqwith the lastseqyou saw, and sendresyncif they differ. - Close codes say why: 4010 rate limit, 4011 too many connections or subscriptions, 4012 message too large, 4020–4025 a bad parameter.
- Credit the data: an app that shows xrpl.to data shows a visible “Data by xrpl.to” link (API terms).
For one-off reads use the REST API instead (API guide); for prices in bulk, the price API.
Questions
- Does the xrpl.to WebSocket need an API key?
- No. Public streams work without one at anonymous limits; send { "type": "auth", "apiKey": "…" } on the socket to use your key’s limits.
- How do I know I missed an update?
- Each update carries seq and prevSeq. If prevSeq is not the last seq you saw, ask the socket to resync and it sends the current state again.
- How do I keep the connection alive?
- Send { "type": "ping" } and the server answers with a pong. When it does close, reconnect with a growing delay.