Algo Trading API for MT4 & MT5
FxSocket gives algo traders a clean REST API and real-time WebSocket streams to automate strategies on MetaTrader 4 and MetaTrader 5. Write your logic in Python, Node.js, Go, Rust, or any language that speaks HTTP. No MQL. No VPS. No terminal running on your desktop.
Whether you're running a single mean-reversion strategy or orchestrating a portfolio of bots across multiple broker accounts, FxSocket provides the infrastructure layer so you can focus entirely on alpha generation. Our API handles order routing, position management, account monitoring, and real-time market data, all through standard HTTP and WebSocket protocols that integrate with any tech stack.
Why Algo Traders Choose FxSocket
- Any language, any framework. Stop fighting MQL syntax. Use the tools you already know: pandas, NumPy, backtrader, or your own custom stack.
- Sub-30ms execution. Our cloud terminals are co-located near major broker infrastructure. Orders go from your code to the broker in milliseconds.
- Real-time data via WebSocket. Stream live bid/ask prices, tick data, and order updates directly to your bot. No polling required.
- 24/7 uptime. Your strategy runs on our cloud infrastructure, not your laptop. No disconnections, no missed trades, no babysitting.
- Historical data for backtesting. Pull OHLCV candles and tick history through the same API. Backtest locally, deploy live. Same code.
- Official SDKs. First-class client libraries for Python, Node.js, Go, and Rust, with typed responses, automatic retries, and built-in authentication handling.
- Affordable at scale. Starting at just €12/account/month on the Starter plan, with Pro plans available for higher-volume traders who need priority support and advanced features.
How It Works
Connect your broker account to FxSocket. We spin up a cloud-hosted MetaTrader terminal and expose it through our API. Your bot sends HTTP requests to place orders, check positions, and pull market data. WebSocket streams push real-time prices and order updates to your application.
The entire lifecycle looks like this: you sign up at app.fxsocket.com, enter your MT4 or MT5 broker credentials, and receive an API key within seconds. From that point, every operation you would normally perform inside MetaTrader (opening trades, modifying stop-losses, querying account balance, pulling chart data) is available as a straightforward API call to api.fxsocket.com. For real-time streaming, open a WebSocket to that same host and subscribe to the symbols and events you care about.
Example: Place a Trade from Python
The simplest way to get started is a basic order placement. Here is a minimal example followed by a production-ready version with proper error handling:
import requests
API_KEY = "fxs_live_..."
ACCOUNT_ID = "your_account_id"
BASE = "https://api.fxsocket.com/mt5"
# Open a buy position on EURUSD
response = requests.post(
f"{BASE}/{ACCOUNT_ID}/OrderSend",
headers={"X-API-Key": API_KEY},
json={
"symbol": "EURUSD",
"operation": "Buy",
"volume": 0.1,
"stopLoss": 1.0720,
"takeProfit": 1.0950,
},
)
print(response.json())Production-Ready Version with Error Handling
In production, you need to handle network errors, authentication failures, and broker rejections gracefully. Here is an expanded version:
import requests
import time
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("fxsocket_bot")
API_KEY = "fxs_live_..."
ACCOUNT_ID = "your_account_id"
BASE = "https://api.fxsocket.com/mt5"
HEADERS = {"X-API-Key": API_KEY}
def place_order(symbol, operation, volume, sl=None, tp=None, retries=3):
"""Place an order with automatic retry on transient failures."""
payload = {
"symbol": symbol,
"operation": operation,
"volume": volume,
}
if sl is not None:
payload["stopLoss"] = sl
if tp is not None:
payload["takeProfit"] = tp
for attempt in range(1, retries + 1):
try:
response = requests.post(
f"{BASE}/{ACCOUNT_ID}/OrderSend",
headers=HEADERS,
json=payload,
timeout=10,
)
if response.status_code == 200:
result = response.json()
# A 200 only means MT5 replied. Confirm the broker
# accepted it via success / retcode.
if result.get("success"):
logger.info(f"Order placed: ticket {result['order']}")
return result
logger.error(
f"Broker rejected: {result.get('retcode')} "
f"{result.get('retcodeDescription')}"
)
return None # A rejection is final. Do not retry.
elif response.status_code == 400:
logger.error(f"Validation error: {response.json()}")
return None # Do not retry on validation errors
elif response.status_code == 401:
logger.error("Authentication failed. Check your API key.")
raise SystemExit("Invalid API key")
elif response.status_code == 503:
logger.warning(
f"Trade engine not ready (attempt {attempt}/{retries})"
)
elif response.status_code >= 500:
logger.warning(
f"Server error (attempt {attempt}/{retries})"
)
except requests.exceptions.Timeout:
logger.warning(f"Timeout (attempt {attempt}/{retries})")
except requests.exceptions.ConnectionError:
logger.warning(f"Connection error (attempt {attempt}/{retries})")
if attempt < retries:
time.sleep(2 ** attempt) # Exponential backoff
logger.error("All retries exhausted. Order not placed.")
return None
# Usage
order = place_order("EURUSD", "Buy", 0.1, sl=1.0720, tp=1.0950)
if order:
print(f"Ticket: {order['order']}, Price: {order['price']}")
Example: WebSocket Price Streaming
For strategies that react to real-time price movements, the per-account WebSocket at wss://api.fxsocket.com/mt5/{account_id}/ws delivers tick data with minimal latency. The following example shows how to stream prices with automatic reconnection logic:
import asyncio
import json
import websockets
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("fxsocket_ws")
API_KEY = "fxs_live_..."
ACCOUNT_ID = "your_account_id"
WS_URL = f"wss://api.fxsocket.com/mt5/{ACCOUNT_ID}/ws?api_key={API_KEY}"
SYMBOLS = ["EURUSD", "GBPUSD", "USDJPY"]
async def on_tick(symbol, bid, ask, ts):
"""Process incoming tick data. Replace with your strategy logic."""
spread = ask - bid
logger.info(f"{symbol} | Bid: {bid} | Ask: {ask} | Spread: {spread:.5f}")
async def stream_prices():
"""Connect to the FxSocket WebSocket with automatic reconnection."""
reconnect_delay = 1
while True:
try:
# Auth rides in the api_key query param. A WebSocket upgrade
# can't carry a custom header.
async with websockets.connect(
WS_URL,
ping_interval=20,
ping_timeout=10,
) as ws:
logger.info("Connected to FxSocket WebSocket")
reconnect_delay = 1 # Reset on successful connection
# Subscribe to the prices topic. One frame per symbol.
for symbol in SYMBOLS:
await ws.send(json.dumps({
"action": "subscribe",
"topic": "prices",
"symbol": symbol,
}))
async for message in ws:
msg = json.loads(message)
if msg.get("type") == "tick":
tick = msg["data"]
await on_tick(
msg["symbol"],
tick["bid"],
tick["ask"],
tick["time"],
)
elif msg.get("type") == "trade":
logger.info(f"Trade event: {msg['data']}")
except websockets.ConnectionClosedError as e:
logger.warning(f"Connection closed: {e}. Reconnecting...")
except Exception as e:
logger.error(f"WebSocket error: {e}")
await asyncio.sleep(reconnect_delay)
reconnect_delay = min(reconnect_delay * 2, 60)
asyncio.run(stream_prices())Any Language: Python, Node.js, and Go
There are no SDKs to install. The API is plain HTTP and JSON, so you call it from any language. Here is the same market order in three:
Python
import requests
ACCOUNT_ID = "your_account_id"
resp = requests.post(
f"https://api.fxsocket.com/mt5/{ACCOUNT_ID}/OrderSend",
headers={"X-API-Key": "fxs_live_..."},
json={"symbol": "EURUSD", "operation": "Buy", "volume": 0.1,
"stopLoss": 1.0720, "takeProfit": 1.0950},
)
print(resp.json())Node.js
const ACCOUNT_ID = "your_account_id";
const resp = await fetch(
`https://api.fxsocket.com/mt5/${ACCOUNT_ID}/OrderSend`,
{
method: "POST",
headers: {
"X-API-Key": "fxs_live_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
symbol: "EURUSD",
operation: "Buy",
volume: 0.1,
stopLoss: 1.0720,
takeProfit: 1.0950,
}),
},
);
console.log(await resp.json());Go
package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
func main() {
accountID := "your_account_id"
url := "https://api.fxsocket.com/mt5/" + accountID + "/OrderSend"
body := []byte(`{"symbol":"EURUSD","operation":"Buy","volume":0.1,"stopLoss":1.0720,"takeProfit":1.0950}`)
req, _ := http.NewRequest("POST", url, bytes.NewReader(body))
req.Header.Set("X-API-Key", "fxs_live_...")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(string(out))
}Prefer a typed client? Every account serves its own OpenAPI 3 spec at /mt5/{account_id}/api-doc/openapi.json. Point any OpenAPI generator at it to produce one for your language.
From Backtest to Live in Minutes
Most algo traders spend weeks wiring up MetaTrader connectivity. With FxSocket, you skip that entirely. The same API that serves historical data for backtesting also executes live trades. Switch from demo to live by changing one parameter.
A typical workflow looks like this: start by pulling historical candle data through the REST API, run your backtest locally using pandas or backtrader, iterate on your strategy until the metrics look right, then deploy the same code against a live account. Because the API interface is identical for historical data and live trading, there is no translation layer to build and no MQL conversion step. Your Python or Node.js code is your production trading system.
Built for Serious Automation
- Connect multiple accounts under one API key
- Granular permissions: read-only, trade, or full access
- IP whitelisting for production bots
- No rate limits on WebSocket connections
- Works with any MT4 or MT5 broker
- 99.99% uptime SLA on all plans
- Encrypted credentials: your broker login is never stored in plain text
Broker-Specific Tips
FxSocket works with any MT4 or MT5 broker, but brokers differ in how they configure symbols, execution modes, and trading constraints. Here are some practical tips to keep in mind when building your algo:
Symbol Naming Differences
Not all brokers use the same symbol names. The standard "EURUSD" might appear as "EURUSDm", "EURUSD.r", "EURUSD.ecn", or "EURUSDb" depending on the broker and account type. Micro accounts often append an "m" suffix, while ECN accounts may add ".ecn" or similar. Always use the GET /mt5/{account_id}/symbols endpoint to fetch the exact symbol list for your connected account rather than hardcoding symbol names.
Execution Modes
Brokers offer different execution modes: instant execution and market execution. With instant execution, the broker may reject your order with a requote if the price moves between your request and their fill. With market execution, orders are always filled but at the current market price, which may differ from the price you saw. FxSocket surfaces the execution mode per symbol so your bot can adapt, for example, by omitting a price parameter on market execution symbols or by widening your slippage tolerance on instant execution brokers.
Lot Size Constraints
Each broker defines minimum volume, maximum volume, and volume step for every symbol. A typical standard account has a minimum of 0.01 lots with a step of 0.01, but some brokers use 0.1 as the minimum or support micro lots at 0.001. If you send a volume that does not align with the broker's step size, the order will be rejected. Query the GET /mt5/{account_id}/SymbolInfo endpoint to retrieve these constraints (volumeMin, volumeMax, volumeStep) programmatically and round your lot sizes accordingly.
Spread Considerations
Spreads vary dramatically between brokers and account types. An ECN account might show 0.1-pip spreads on EURUSD during London session but widen to 3+ pips during the Asian rollover. If your strategy is sensitive to spread, subscribe to the WebSocket tick stream and calculate the live spread before placing each order. You can also set a maximum spread threshold in your bot logic to skip trades when conditions are unfavorable.
Common Errors and Troubleshooting
Here are the most frequent issues algo traders encounter when integrating with FxSocket, along with solutions:
401 Unauthorized
This means your API key is missing, expired, or incorrect. Double-check that you are sending the key in the X-API-Key header (or the api_key query parameter for WebSocket). If you recently rotated your key in the dashboard, make sure your bot is using the new one, and give it a minute, since the terminal restarts briefly when the new key lands. API keys are scoped to your account and you can rotate them at any time.
Rejected Orders
A 200 response means MT5 replied, not that the broker filled your order. Always check success and retcode in the response body. A malformed request (missing field, unknown operation) returns 400 instead. Common causes of a rejection:
- Invalid symbol: The symbol name does not match what the broker uses. Call GET /mt5/{account_id}/symbols to get the correct names.
- Volume out of range: The lot size is below the minimum, above the maximum, or not aligned to the step size.
- Invalid stop-loss or take-profit: SL/TP levels are too close to the current price. Most brokers enforce a minimum stop distance (usually a few pips).
- Market closed: You are trying to trade a symbol outside its broker-defined trading hours.
WebSocket Disconnects
WebSocket connections can drop due to network interruptions, server maintenance, or idle timeouts. Always implement reconnection logic with exponential backoff (as shown in the streaming example above). Send periodic pings to keep the connection alive and detect dead connections early. After reconnecting, re-send your subscription messages. The server does not remember your previous subscriptions.
Tracking Pending Orders
Market orders fill or reject synchronously. The OrderSend response already tells you the outcome. Pending orders (limit / stop) sit until their trigger price is hit. To track them, poll GET /mt5/{account_id}/OpenedOrders or subscribe to the WebSocket trades topic for fills as they happen. If a pending order has not triggered within your threshold, cancel it with POST /mt5/{account_id}/OrderClose and re-evaluate.
Frequently Asked Questions
Can I run multiple strategies on the same account?
Yes. FxSocket does not restrict how you organize your trading logic. You can run multiple bots that each target different symbols or timeframes, all operating against the same connected account. Use the comment or magic number field when placing orders to tag which strategy opened each position. This makes it easy to track performance per strategy and ensures one bot does not accidentally close another bot's positions.
What about rate limits?
There are no enforced rate limits today. Every request is served by your own dedicated terminal, so heavy polling only ever slows down your own account, nobody else's. That said, for live prices, positions, and account changes, prefer the WebSocket streams over polling: you get pushed updates without burning round-trips, and you receive every tick as it happens.
How do I handle overnight swaps?
Overnight swap charges (or credits) are applied by your broker, not by FxSocket. Swaps are typically applied at the daily rollover time (usually around 00:00 server time) and appear as adjustments on your open positions. You can query the current swap rates for any symbol through the GET /mt5/{account_id}/SymbolInfo endpoint (swapLong / swapShort). If your strategy is swap-sensitive, factor these costs into your backtesting by including the swap rates in your P&L calculations. Wednesday usually carries a triple swap to account for the weekend.
Can I use FxSocket with a demo account?
Absolutely. FxSocket works identically with both demo and live accounts. In fact, we recommend starting with a demo account to test your integration, validate your strategy logic, and confirm that symbol names and lot sizes are correct before going live. The API interface is the same. Your code does not need to change when switching from demo to production.
How do I monitor my bot's performance?
The FxSocket dashboard at app.fxsocket.com provides real-time visibility into your connected accounts, including open positions, order history, account balance, and equity curves. For programmatic monitoring, use the GET /mt5/{account_id}/AccountSummary endpoint to pull balance, equity, margin, and free margin. Many traders also pipe their order data into a separate analytics platform or database for custom reporting and drawdown tracking.