EODHD offers one of the best ways for investors, developers, and data analysts to incorporate real-time finance data for the stocks, 1100+ Forex pairs, 1000+ Digital Currencies into their decision-making projects with a delay of less than 50ms via WebSockets. For stocks our real-time data API supports pre-market and post-market hours (from 4 am to 8 pm EST).
The subscription provides real-time access to prices for 50 tickers simultaneously via WebSockets. Additionally, the 50-symbol limit can be increased through the user dashboard.
For global markets and all exchanges around the world we also offer Live (Delayed) data with 15min delay.
What is WebSocket protocol
WebSockets is a communication protocol that provides full-duplex communication channels over a single TCP connection. It enables real-time communication between a client and a server, allowing them to exchange messages continuously without the overhead of repeatedly establishing new connections. In the case of financial data providers, Websockets API provides real-time stock market information with minimal delay.
Because real-time WebSocket streaming is resource-intensive, it is offered on paid plans rather than a free tier.
What you get (Data availability)
Stocks (full list of tickers available)
• Trade stream (last price, size, conditions, etc.)
• Quote stream (bid/ask, sizes)
• Extended hours supported (pre‑ and post‑market)
FOREX (full list of available currency pairs)
• Bid/ask + day change/difference
• Tickers like EURUSD, AUDUSD, etc.
Digital Currencies (Full list of available crypto pairs)
• Last price, quantity, day change/difference
• Tickers like ETH-USD, BTC-USD
Lists of available tickers and pairs for Real-Time feeds can be retrieved in JSON format via this API endpoint, providing the full list of exchange or asset class components (use “US” for US stocks, “CC” for cryptocurrencies, “FOREX” for currency pairs).
Demo access is available with API key “demo” for: AAPL, MSFT, TSLA, EURUSD, ETH-USD, BTC-USD.
Data source and what the data represents
Real-time US and European equities are delivered directly from Cboe Global Cloud, our official exchange data source. Because this is a direct-from-exchange feed rather than an aggregated one, it is worth being precise about what it contains.
US equities
US trades and quotes come from Cboe EDGX, one of Cboe’s four US equity exchanges. Trades are executions that occurred on EDGX — this is not a consolidated (SIP) tape, so it does not include executions from other exchanges, or off-exchange and FINRA TRF prints. Quotes are the EDGX top of book with sizes, not a national best bid and offer aggregated across venues. Pre-market and post-market trades are delivered and flagged through the market status field.
European equities
European trades and quotes come from Cboe Europe, across its BXE, CXE and DXE order books, covering UK-listed names and continental large-caps over a single endpoint. Trading hours follow each instrument’s home venue, so the last trade for a symbol may lag once that venue enters its closing auction while quotes continue elsewhere.
European quotes differ from the US ones in one important way: they are a consolidated best bid and offer across all three books. The best price wins, and where two books show the same price their sizes are added, so the size you see is the depth available at that price across the venues we carry.
Updates & Latency
- Streaming updates pushed in real time over a persistent WebSocket connection.
- Typical transport latency < 50 ms from our gateway to your client (excluding network distance).
- Market status flag indicates open, closed, or extended hours for stocks.
Endpoints
Open connection – use wss:// in production. ws:// is available for local testing.
Equities (Trades and Quotes):
wss://ws.eodhistoricaldata.com/ws/us?api_token=YOUR_API_KEY
wss://ws.eodhistoricaldata.com/ws/us-quote?api_token=YOUR_API_KEY
European Equities (Trades and Quotes):
wss://ws.eodhistoricaldata.com/ws/eu?api_token=YOUR_API_KEY
wss://ws.eodhistoricaldata.com/ws/eu-quote?api_token=YOUR_API_KEY
Minute Bars (US and Europe):
wss://ws.eodhistoricaldata.com/ws/us-candles?api_token=YOUR_API_KEY
wss://ws.eodhistoricaldata.com/ws/eu-candles?api_token=YOUR_API_KEY
Forex
wss://ws.eodhistoricaldata.com/ws/forex?api_token=YOUR_API_KEY
Crypto
wss://ws.eodhistoricaldata.com/ws/crypto?api_token=YOUR_API_KEY
Subscribe / Unsubscribe
After the socket is open, send JSON commands.
Connection and status messages: on a successful connection the server first sends an authorization message. If you subscribe to a symbol your plan does not allow, for example a non-demo ticker on the demo key, the server replies with a status message instead of data.
{"status_code": 200, "message": "Authorized"}
{"status_code": 422, "message": "Only limited symbols allowed for demo"}
Subscribe:
{"action": "subscribe", "symbols": "ETH-USD"}
Multiple symbols (comma‑separated):
{"action": "subscribe", "symbols": "AAPL,TSLA"}
Unsubscribe:
{"action": "unsubscribe", "symbols": "ETH-USD,BTC-USD"}
Response Schemas
Trades (endpoint: /ws/us):
{
"s": "AAPL", // ticker
"p": 309.19, // last trade price
"c": [], // trade conditions (array) - empty on this feed, see note
"v": 2, // trade size (shares)
"dp": false, // dark pool flag - always false on this feed, see note
"ms": "extended-hours", // market status: open | closed | extended-hours
"t": 1787671313868 // epoch ms, UTC
}
Two fields need a word of explanation. The conditions field c is an array, and on this feed it is always empty: the exchange top-of-book source does not carry per-trade sale conditions. The field is kept so the message shape stays identical across all our equity streams. The dark-pool flag dp is always false, because this is a single lit-exchange feed with no off-exchange or FINRA TRF prints in it.
Quotes (endpoint: /ws/us-quote):
{
"s": "AAPL", // ticker
"ap": 317.297, // ask price
"as": 160, // ask size
"bp": 316.988, // bid price
"bs": 40, // bid size
"t": 1784115291977 // epoch ms
}
European Equities (endpoints: /ws/eu and /ws/eu-quote):
European equities use exactly the same schemas as US equities — the trade stream matches /ws/us and the quote stream matches /ws/us-quote. Only the symbol format differs. Example trade message:
{
"s": "GSK.LSE", // ticker (TICKER.EXCHANGE)
"p": 1911, // last trade price, in the venue's quoting units
"c": [], // trade conditions (array) - empty on this feed
"v": 155, // trade size (shares)
"dp": false, // dark pool flag - always false on this feed
"ms": "open", // market status: open | closed
"t": 1787671304945 // epoch ms, UTC
}
Prices are JSON numbers and may arrive with no decimal part when the venue quotes in whole units, as above. Do not assume a fractional component.
Minute Bars (endpoints: /ws/us-candles and /ws/eu-candles):
A rolling one-minute OHLCV bar per subscribed symbol, built from the trade stream.
{
"s": "AAPL", // ticker
"i": "1m", // bar interval
"t": 1787671260000, // bar OPEN time, epoch ms UTC
"o": 309.25, // open
"h": 309.26, // high
"l": 309.19, // low
"c": 309.19, // close
"v": 1101 // volume in shares, accumulated within the bar
}
The field c means two different things depending on the stream: on the trade streams it is the conditions array, and on the minute-bar streams it is the bar close price. The current bar is also re-sent every time it changes, so the same bar-open timestamp arrives repeatedly with a growing volume until the minute rolls over. Treat the newest message for a given timestamp as authoritative rather than adding them together.
FOREX (endpoint: /ws/forex):
{
"s": "EURUSD", // symbol
"a": 1.1419, // ask
"b": 1.1416, // bid
"dc": "0.3005", // daily change, % (string)
"dd": "0.0034", // daily difference, price units (string)
"ppms": true, // pre/post market status flag
"t": 1784115288241 // epoch ms
}
Crypto (endpoint: /ws/crypto):
{
"s": "ETH-USD", // symbol
"p": "1881.0931", // last price (string)
"q": "1.9e-7", // trade quantity (string, may use exponent notation)
"dc": "5.6041", // daily change, % (string)
"dd": "105.4177", // daily difference, price units (string)
"t": 1784115286805 // epoch ms
}
Symbol Limits & Usage Notes
Concurrent subscriptions: up to 50 symbols per connection by default (upgradeable in user dashboard for extra fee).
Tickers:
- US Stocks: use plain tickers like AAPL, MSFT — no exchange suffix
- European Stocks: use TICKER.EXCHANGE, e.g., GSK.LSE, SAP.XETRA, ASML.AS — the native Cboe symbol is accepted too
- Forex: no separator, e.g., EURUSD
- Crypto: dash‑separated, e.g., BTC-USD
Resubscribe on reconnect: if the socket reconnects, re‑send your current subscriptions.
Compression/Throughput: consider batching symbol lists in a single subscribe call for efficiency.
Symbols that never arrive
A symbol that is unknown, or correct-looking but in the wrong format for the market, is accepted silently — no error is returned and the symbol simply never streams. If one symbol arrives and others stay quiet, check the format of the quiet ones first. The most common cause is an exchange suffix on a US ticker, or a missing one on a European ticker.
One input mistake does produce an error: sending the symbols value as a JSON array instead of a comma-separated string is rejected with a 422.
European tickers containing a hyphen
Known limitation. European tickers that contain a hyphen — mostly Nordic dual-class shares such as ERIC-B.ST or NOVO-B.CO — do not currently resolve under that name, and because unknown symbols are ignored silently you will see no error. Subscribe with the hyphen removed instead, for example ERICB.ST or NOVOB.CO. This affects the subscription name only, not the data. We are correcting the mapping so the hyphenated ticker works, and the un-hyphenated form will keep working afterwards, so code written against it today will not break. Note also that some hyphenated tickers are not part of the venue coverage behind this feed and return nothing in either form.
Connection limits
You may hold up to 64 concurrent connections per API token. That budget is shared across every market — trades, quotes, minute bars, forex and crypto sockets all count toward the same total. Opening one beyond it is refused with a 429 before the WebSocket opens.
Opening a separate connection per stream is expected and supported. The cap exists so one runaway client cannot degrade the feed for everyone, so if you legitimately need more, contact support rather than retrying in a loop.
Errors and status codes
Error frames come in two shapes, and the difference matters if you write one parser for both. An authentication failure uses the key status. Every other frame uses status_code.
Authentication, before the connection opens
{"status":422,"message":"Server error"} // api_token missing
{"status":403,"message":"Server error"} // token not recognised, or no real-time entitlement
These are returned as the HTTP response to the handshake, so the WebSocket never opens and nothing arrives on the socket. Browsers deliberately hide the details of a failed WebSocket handshake, so a browser client sees only a generic connection error — to tell a missing token from an unentitled one, read the HTTP status from a server-side client.
After the connection is open
| Code | Message | Cause |
|---|---|---|
| 404 | No market ‘…’ found | The endpoint path is not one of the markets listed above. |
| 422 | Invalid request | The command was not valid JSON. |
| 422 | action and symbols should be passed in a command | One of the two required keys is missing. |
| 422 | Action and symbols should be string | Wrong types — most often symbols sent as a JSON array instead of a comma-separated string. |
| 422 | Unknown action. Possible actions: subscribe, unsubscribe | The action value is not recognised. |
| 422 | Symbols limit reached | The subscription would exceed your plan’s symbol limit. |
| 422 | Only limited symbols allowed for demo | A demo token asked for a symbol outside the demo list. |
| 429 | Too many connections (token) | The 64-connection budget for this token is full. |
| 500 | Internal error. Try again later | Server-side failure. |
Examples (copy‑paste ready)
Open connection for trades:
wss://ws.eodhistoricaldata.com/ws/us?api_token=demo
Then send:
{"action": "subscribe", "symbols": "AMZN,TSLA"}
Open connection for Forex pairs:
wss://ws.eodhistoricaldata.com/ws/forex?api_token=demo
Then send:
{"action": "subscribe", "symbols": "EURUSD,AUDUSD"}
Open connection for Crypto:
wss://ws.eodhistoricaldata.com/ws/crypto?api_token=demo
Then send:
{"action": "subscribe", "symbols": "ETH-USD,BTC-USD"}
Tools for Testing
Chrome: Simple WebSocket Client extension (open a socket, paste open URL, send JSON quote).
EODHD Chrome extension: free mini ticker window for live Stocks/FX/Crypto. Perfect to see our real-time data feed. No commands needed. Install from here.
Postman (or Insomnia) – point-and-click:
- New → WebSocket Request
- URL: wss://ws.eodhistoricaldata.com/ws/crypto?api_token=demo
- Connect → send: {“action”:”subscribe”,”symbols”:”BTC-USD”}
Python (minimal script):
import asyncio, websockets, json
URL = "wss://ws.eodhistoricaldata.com/ws/crypto?api_token=demo"
async def main():
async with websockets.connect(URL) as ws:
await ws.send(json.dumps({"action":"subscribe","symbols":"BTC-USD"}))
while True:
print(await ws.recv())
asyncio.run(main())
Mac Os Terminal – websocat (via Homebrew):
Install websocat:
brew install websocat
One-liner command:
printf '{"action":"subscribe","symbols":"BTC-USD"}\n' | \
websocat "wss://ws.eodhistoricaldata.com/ws/crypto?api_token=demo"
Quick Comparison with Live (Delayed) API and Intraday API
| Aspect | Real-Time (WebSockets) | Live (Delayed) | Intraday Historical |
|---|---|---|---|
| Transport | WebSocket (push) | HTTPS REST (pull) | HTTPS REST (pull) |
| Latency / Freshness | ~live (<50 ms transport) | Stocks: 15–20 min delay; Currencies: ~1 min | Finalized ~2–3 h after US after-hours close |
| Data types | Trades & quotes; FX ticks; crypto ticks | Latest OHLCV snapshot (1-min updates) | OHLCV bars at 1m / 5m / 1h |
| Time ranges | n/a (streaming) | n/a (snapshot feed) | 1m: 120 d · 5m: 600 d · 1h: 7200 d |
| Markets & assets* | US stocks (pre/post supported), Forex & Digital Currencies | US & Global Stocks, Forex & Digital Currencies | US & Global Stocks, Forex & Digital Currencies |
| Best for | Dashboards, signals, market-making tools | Quote tickers, watchlists, lightweight UIs | Backtests, analytics, charting |
* Get the full list of covered tickers.