MetaTrader 4 APIWebSocket Streams

For AI agents: this page is also available as Markdown at /docs/mt4/websocket.md. The index of every docs page is /docs/llms.txt.

MetaTrader 4 WebSocket API

Stream live MetaTrader 4 data over a single WebSocket per account: ticks, OHLC bar closes, account updates, open positions, trade events, and terminal status. Subscribe and unsubscribe with simple JSON control frames, no polling.

How streaming works on MT4

  • Polled, not event-driven. MT4 offers no event hooks a bridge can attach to, so every topic is produced by polling inside the terminal's main loop, after any queued requests have been handled.
  • Prices on change. A tick is sent whenever bid or ask changes. last is always 0 and volume is the tick count of the current M1 bar.
  • Account and positions once per second. Both are re-read every second and sent when something changed.
  • Trades every 250 ms. Trade events are built by comparing snapshots of open orders and recent history. An order that opens and closes within one interval may not show its opening event, but its close is still reported; reconcile with /OrderHistory when you need every step.
  • MT4 event fields. deal is always 0, position is the order ticket, and magic and comment are present on both the opening and the closing event, because MT4 orders keep them for their whole life.
WS wss://api.fxsocket.com/mt4/{account_id}/ws?api_key=fxs_live_...

One streaming socket per account. Authentication is via the api_key query parameter, the only method available on WebSocket connections. Send JSON control frames to subscribe and unsubscribe; on subscribe the server first sends one current snapshot (account / positions / prices) before streaming deltas. Non-browser clients: the upgrade requires HTTP/1.1. On MT4 every topic is produced by polling inside the terminal (MT4 has no event hooks for this), at the rates listed below. Six topics are available:

  • prices: Per-symbol ticks (requires symbol), sent whenever bid or ask changes; volume is the tick count of the current M1 bar.
  • bars: OHLC bar closes per symbol + timeframe (requires symbol and timeframe).
  • account: Account snapshot, then changes, checked once per second.
  • positions: Open positions snapshot, then changes, checked once per second.
  • trades: Trade events, built every 250 ms by comparing snapshots of open orders and recent history. deal is 0, position is the order ticket, and magic and comment are present on both the opening and the closing event.
  • terminal: Terminal status, roughly once per second.
Client → server frames
{"action": "subscribe", "topic": "prices", "symbol": "EURUSD"}
{"action": "subscribe", "topic": "bars", "symbol": "EURUSD", "timeframe": "M5"}
{"action": "subscribe", "topic": "account"}
{"action": "unsubscribe", "topic": "prices", "symbol": "EURUSD"}
WS server → client messages

Every server message is a JSON object with a type. Data messages mirror the REST shapes; control replies confirm your frames. Slow consumers get dropped messages plus a warning message rather than a stalled socket.

Server → client messages
{"type": "tick", "symbol": "EURUSD", "data": {"bid": 1.15325, "ask": 1.15333, "last": 0.0, "volume": 37, "time": "2026-06-11T08:55:56.728Z"}}
{"type": "bar", "symbol": "EURUSD", "timeframe": "M5", "data": {"open": 1.15301, "high": 1.15348, "low": 1.15289, "close": 1.15330}}
{"type": "account", "data": { ... }}
{"type": "positions", "data": [ ... ]}
{"type": "trade", "data": { ... }}
{"type": "terminal", "data": {"connected": true, "tradeAllowed": true, "serverTime": "2026-06-11T08:55:57.000Z"}}
{"type": "subscribed" | "unsubscribed" | "error" | "warning", ...}
GET /ws-tester

A built-in browser tester is served per account at https://api.fxsocket.com/mt4/{account_id}/ws-tester?api_key=fxs_live_... (handy for poking at the stream before writing code). The page is API-key gated, and since browsers can't attach headers the key must ride in the URL (it will appear in your browser history). Open yours from the Request Builder on the overview page.