MT5 CANDLE DATA API
SECUREMetaTrader 5 — Real-Time & Historical OHLCV Data
Follow these exact steps to configure N8N to fetch candle data from the MT5 API.
GET
X-API-Key
43zr7RvLh7ZEZCw6cWHsZgbHc2tqW5OSAvfjpnPrqqk
X-API-Key, Value: 43zr7RvLh7ZEZCw6cWHsZgbHc2tqW5OSAvfjpnPrqqk
$json.candles — access it with {{ $json.candles }} in subsequent nodes.
{
"symbol": "EURUSDm",
"timeframe": "H1",
"count": 5,
"candles": [
{ "time": "2026-03-27T00:00:00", "open": 1.15, "high": 1.16,
"low": 1.14, "close": 1.155, "tick_volume": 1234 },
...
]
}
{{ $json.symbol }}— Symbol name{{ $json.candles[0].close }}— Latest candle close price{{ $json.candles[0].high }}— Latest candle high{{ $json.candles[0].tick_volume }}— Latest tick volume{{ $json.count }}— Number of candles returned
Example N8N workflow that fetches H4 candles and sends a summary to Telegram every morning:
Workflow:
1. Cron Trigger → Daily at 08:00
2. HTTP Request
Method: GET
URL: https://mt5api.invoker4916.io.vn/api/v1/candles?symbol=XAUUSDm&timeframe=H4&count=5
Headers: X-API-Key = 43zr7RvLh7ZEZCw6cWHsZgbHc2tqW5OSAvfjpnPrqqk
3. Code Node (JavaScript):
const candles = $input.first().json.candles;
const latest = candles[0];
const trend = latest.close > latest.open ? "UP 📈" : "DOWN 📉";
return { json: {
symbol: "XAUUSD",
close: latest.close,
high: latest.high,
low: latest.low,
trend,
time: latest.time
}};
4. Telegram Node:
Message: "{{ $json.trend }} XAUUSD | Close: {{ $json.close }} | H4 candle at {{ $json.time }}"
pip install requests pandas
import requests url = "https://mt5api.invoker4916.io.vn/api/v1/candles?symbol=EURUSDm&timeframe=M15&count=100" response = requests.get(url, headers={ "X-API-Key": "43zr7RvLh7ZEZCw6cWHsZgbHc2tqW5OSAvfjpnPrqqk" }) data = response.json() print(f"Loaded {data['count']} candles from {data['from_dt']} to {data['to_dt']}") print(data["candles"][0])
url = "https://mt5api.invoker4916.io.vn/api/v1/candles?symbol=EURUSDm&timeframe=M15&count=100"
import requests import pandas as pd url = "https://mt5api.invoker4916.io.vn/api/v1/candles?symbol=EURUSDm&timeframe=H1&count=500" headers = {"X-API-Key": "43zr7RvLh7ZEZCw6cWHsZgbHc2tqW5OSAvfjpnPrqqk"} data = requests.get(url, headers=headers).json() df = pd.DataFrame(data["candles"]) df["time"] = pd.to_datetime(df["time"]) df = df.iloc[::-1].reset_index(drop=True) # oldest first # Simple Moving Averages df["sma20"] = df["close"].rolling(20).mean() df["sma50"] = df["close"].rolling(50).mean() # RSI delta = df["close"].diff() gain = delta.where(delta > 0, 0).rolling(14).mean() loss = (-delta.where(delta < 0, 0)).rolling(14).mean() df["rsi"] = 100 - (100 / (1 + gain / loss)) # Latest values latest = df.iloc[-1] print(f"{latest['time'].date()} | Close: {latest['close']:.5f} | RSI: {latest['rsi']:.1f}") print(f"SMA20: {latest['sma20']:.5f} | SMA50: {latest['sma50']:.5f}") # Golden cross signal if latest["sma20"] > latest["sma50"]: print('>>> GOLDEN CROSS — BUY signal') elif latest["sma20"] < latest["sma50"]: print('>>> DEATH CROSS — SELL signal')
pip install sseclient-py import sseclient, requests, json url = "https://mt5api.invoker4916.io.vn/api/v1/subscribe" params = {"symbol": "XAUUSDm", "timeframe": "M1", "api_key": "43zr7RvLh7ZEZCw6cWHsZgbHc2tqW5OSAvfjpnPrqqk"} resp = requests.get(url, params=params, headers={"Accept": "text/event-stream"}, stream=True) client = sseclient.SSEClient(resp) for event in client.events(): msg = json.loads(event.data) if msg["type"] == "snapshot": print(f"Loaded {len(msg['candles'])} historical candles") elif msg["type"] == "candle": c = msg["data"] print(f"{c['time']} | Close: {c['close']} | Vol: {c['tick_volume']}")
Run these commands in order after VPS restart or shutdown.
# Open this file: # C:\Users\Administrator\Desktop\ClaudeCode-API-MT5\.env MT5_API_KEY=43zr7RvLh7ZEZCw6cWHsZgbHc2tqW5OSAvfjpnPrqqk MT5_USERNAME=YOUR_MT5_LOGIN_ID ← Find in MT5: File → Login to Trade Account MT5_PASSWORD=YOUR_MT5_PASSWORD ← Your MT5 account password WEB_USERNAME=admin WEB_PASSWORD=admin123 ← Web login page password (change after first login)
start "" "C:\Users\Administrator\Desktop\Exness\terminal64.exe"
cd C:\Users\Administrator\Desktop\ClaudeCode-API-MT5 "C:\Program Files\Python312\python.exe" mt5_server.py --port 8000 --reload
cd C:\nginx nginx.exe
curl -H "X-API-Key: 43zr7RvLh7ZEZCw6cWHsZgbHc2tqW5OSAvfjpnPrqqk" https://mt5api.invoker4916.io.vn/api/v1/health
{"status":"ok","mt5_connected":true,...}nginx.exe -s reload instead of starting fresh.https://mt5api.invoker4916.io.vn. You will be redirected to the login page. Default credentials:Username: admin Password: admin123
import requests import pandas as pd resp = requests.get( "https://mt5api.invoker4916.io.vn/api/v1/candles", params={"symbol": "EURUSDm", "timeframe": "M15", "count": 10000}, headers={"X-API-Key": "43zr7RvLh7ZEZCw6cWHsZgbHc2tqW5OSAvfjpnPrqqk"} ) df = pd.DataFrame(resp.json()["candles"]) df["time"] = pd.to_datetime(df["time"]) df = df.iloc[::-1].reset_index(drop=True) # oldest first # RSI delta = df["close"].diff() gain = delta.where(delta > 0, 0).rolling(14).mean() loss = (-delta.where(delta < 0, 0)).rolling(14).mean() df["rsi"] = 100 - (100 / (1 + gain / loss)) # Bollinger Bands df["sma20"] = df["close"].rolling(20).mean() df["bb_lower"] = df["sma20"] - 2 * df["close"].rolling(20).std() df["signal"] = (df["rsi"] < 30) & (df["close"] < df["bb_lower"]) print("Entry signals:", df[df["signal"]].shape[0])
import sseclient, requests, json resp = requests.get( "https://mt5api.invoker4916.io.vn/api/v1/subscribe", params={"symbol": "XAUUSDm", "timeframe": "M1", "api_key": "43zr7RvLh7ZEZCw6cWHsZgbHc2tqW5OSAvfjpnPrqqk"}, headers={"Accept": "text/event-stream"}, stream=True ) client = sseclient.SSEClient(resp) for event in client.events(): msg = json.loads(event.data) if msg["type"] == "candle": c = msg["data"] o, h, l, cl = c.get("open"), c.get("high"), c.get("low"), c.get("close") body = abs(cl - o) lower_wick = min(o, cl) - l upper_wick = h - max(o, cl) # Pin bar: lower wick > 2x body, tiny upper wick if lower_wick > body * 2 and upper_wick < body * 0.5: print('>>> BULLISH PIN BAR at', c.get('time'), '| Close:', cl) else: print('Close:', cl, '| Vol:', c.get('tick_volume'))
# N8N Workflow:
# 1. Schedule Trigger → Daily at 08:00
# 2. HTTP Request
# GET /api/v1/candles?symbol=XAUUSDm&timeframe=H4&count=5
# Header: X-API-Key = 43zr7RvLh7ZEZCw6cWHsZgbHc2tqW5OSAvfjpnPrqqk
# 3. Code (JS):
# const candles = $json.candles;
# const closes = candles.map(c => c.close);
# const avg = (closes.reduce((a,b) => a+b, 0) / closes.length).toFixed(2);
# const latest = closes[closes.length-1];
# return { latest, avg, signal: latest > avg ? "BUY" : "SELL" };
# 4. Telegram Node:
# Message: "{{ $json.signal }} signal | XAUUSD H4 close: {{ $json.latest }}"
# N8N Workflow:
# 1. Wait (Webhook) — receives manual /push trigger
# 2. HTTP Request
# GET /api/v1/candles?symbol=XAUUSDm&timeframe=M5&count=2&source=mql5
# Header: X-API-Key = 43zr7RvLh7ZEZCw6cWHsZgbHc2tqW5OSAvfjpnPrqqk
# 3. Code (JS) — detect engulfing:
const candles = $input.first().json.candles;
const prev = candles[1], curr = candles[0];
const body = Math.abs(curr.close - curr.open);
const prevBody = Math.abs(prev.close - prev.open);
const engulfing = curr.close > prev.open && curr.open < prev.close
&& body > prevBody;
if (engulfing) {
return { json: { alert: "BULLISH ENGULFING", close: curr.close } };
}
# 4. Discord Node → Post: {{ $json.alert }} at {{ $json.close }}
import requests API_KEY = "43zr7RvLh7ZEZCw6cWHsZgbHc2tqW5OSAvfjpnPrqqk" BASE = "https://mt5api.invoker4916.io.vn/api/v1/candles" def get_candles(symbol, tf, count=200): r = requests.get(BASE, params={"symbol": symbol, "timeframe": tf, "count": count}, headers={"X-API-Key": API_KEY}) return r.json()["candles"] def sma(closes, period): return sum(closes[-period:]) / period def rsi(closes, period=14): deltas = [closes[i] - closes[i-1] for i in range(1, len(closes))] gain = sum([d for d in deltas[-period:] if d > 0]) / period loss = abs(sum([d for d in deltas[-period:] if d < 0]) / period) return 100 - (100 / (1 + gain / loss)) if loss != 0 else 50 # Step 1: D1 trend (200 SMA) d1 = get_candles("EURUSDm", "D1", 200) d1_closes = [c["close"] for c in reversed(d1)] trend_up = d1_closes[-1] > sma(d1_closes, 200) # Step 2: M15 entry (RSI) m15 = get_candles("EURUSDm", "M15", 100) m15_closes = [c["close"] for c in reversed(m15)] r = rsi(m15_closes) # Signal if trend_up and r < 40: print('LONG — D1 up, RSI=', round(r, 1)) elif not trend_up and r > 60: print('SHORT — D1 down, RSI=', round(r, 1)) else: print('No signal')
| GET | /api/v1/health | MT5 + watcher status. Use in uptime monitors |
| GET | /api/v1/connect | Force MT5 reconnect after terminal restart |
| GET | /api/v1/symbols | List all 348 tradeable symbols |
| GET | /api/v1/timeframes | M1–MN1 supported timeframes |
| GET | /api/v1/candles | Fetch OHLCV (max 10,000). Core endpoint |
| GET | /api/v1/push | Force MQL5 EA to push latest candles |
| GET | /api/v1/subscribe | SSE stream — live tick-by-tick data |
| GET | /api/v1/calendar | Economic calendar — ?currency=USD&impact=High&tz=GMT&days=7 |
| GET | /api/v1/calendar/subscribe | SSE stream — high-impact economic event alerts |
| symbol | EURUSDm, XAUUSDm, BTCUSDm, US500m... |
| timeframe | M1 M5 M15 H1 H4 D1 W1 MN1 |
| count | 1–10,000 candles |
| source | mt5 (historical, default) or mql5 (live) |
Header: X-API-Key: 43zr7RvLh7ZEZCw6cWHsZgbHc2tqW5OSAvfjpnPrqqk
SSE subscribe uses query param instead: ?api_key=YOUR_KEY (browsers block custom headers on EventSource)
{
"symbol": "EURUSDm",
"timeframe": "M15",
"count": 5,
"from_dt": "2026-03-27T03:00:00",
"to_dt": "2026-03-27T03:56:00",
"candles": [
{ "time": "2026-03-27T03:00:00",
"open": 1.15337, "high": 1.15352,
"low": 1.15325, "close": 1.15347,
"tick_volume": 99 },
...
],
"source": "mt5"
}
| Symbol | Name | Price | 1D% | 3D% | 1W% | 10D% | Volume | OI | Unit | Sector |
|---|
Upcoming economic events from Forex Factory. Works 24/7 including weekends. Data is cached for 30 minutes.
Connect to real-time SSE stream for high-impact event notifications.
Fetch all high-impact USD events for the next 14 days in London time:
import requests, pandas as pd
resp = requests.get(
"https://mt5api.invoker4916.io.vn/api/v1/calendar",
params={
"currency": "USD",
"impact": "High",
"tz": "GMT",
"days": 14
},
headers={"X-API-Key": "YOUR_KEY"}
)
cal = pd.DataFrame(resp.json()["events"])
cal["time"] = pd.to_datetime(cal["time"])
# Align with your candle timestamps
upcoming = cal[cal["time"] > pd.Timestamp.now()]
# Count high-impact events this week
high_count = len(upcoming[upcoming["impact"] == "High"])
Timezone options: EST5EDT (New York), GMT (London), local (server time) |
Days: 1-30 |
Filters: currency, impact |
Force refresh: ?refresh=true
Upload a profile avatar (JPG, PNG, GIF, WebP)
All credentials are stored in one file. Edit it directly to change any value.
MT5_API_KEY — API keyMT5_USERNAME — MT5 account IDMT5_PASSWORD — MT5 passwordMT5_SERVER — Broker serverMT5_TERMINAL_PATH — .exe pathWEB_USERNAME — Web login userWEB_PASSWORD_HASH — Hashed web passwordUpdate the MT5 trading account password. After changing, run Initialize to apply.
Update the password used to log in to this web page. Takes effect immediately.