Docs

Use the MetaTrader 5 API on Linux and macOS

Why the official MetaTrader5 Python package only works on Windows next to a running terminal, the Wine, Docker and VPS workarounds people use on Linux and macOS, and how to trade MT5 accounts over plain HTTP instead — from any OS and any language.

If you have tried pip install MetaTrader5 on a Mac or a Linux server, you have met the problem this page is about. The official package is built for Windows and talks to a MetaTrader 5 terminal running on the same machine. This guide explains why, what people do about it, and how to skip the problem entirely by trading over HTTP.

Why the official package needs Windows

MetaQuotes' own documentation describes the package as a way to obtain data "via interprocessor communication directly from the MetaTrader 5 terminal". It is not a network client for the broker: it is a bridge to a terminal process on the same computer.

Two facts follow from that:

  • It needs a running MetaTrader 5 terminal. initialize() "establishes a connection with the MetaTrader 5 terminal", and takes the path to the terminal's .exe; if required, the terminal is launched when initialize() is called. Every call after that — order_send, positions_get, history_deals_get — goes through that terminal.
  • It is published for Windows only. On PyPI, the files published for the package are Windows x86-64 wheels (win_amd64); there are none for Linux or macOS, so pip on those systems finds nothing it can install.

Sources, checked on 30 September 2026: MetaTrader5 on PyPI, Python integration — MQL5 documentation, initialize() — MQL5 documentation.

The workarounds people use

Wine

MetaQuotes publishes instructions for running the MetaTrader 5 terminal on Linux through Wine, with an install script for Ubuntu, Debian, Linux Mint and Fedora, and a separate page for macOS (MetaTrader 5 on Linux). That runs the terminal. To use the Python package, you then also install a Windows build of Python inside the same Wine prefix, install MetaTrader5 there, and run your script with that interpreter.

A bridge between Linux Python and Wine Python

Open-source projects such as mt5linux automate the second half: a server runs in Wine's Windows Python next to the terminal, and a client library in your normal Linux Python forwards each call to it over RPyC. Your code imports a module that mirrors the MetaTrader5 API.

Docker images

Community images bundle Wine, the terminal, a Windows Python, a bridge like the one above, and often a VNC server so you can see the terminal's window. They make the setup reproducible; they do not make it smaller.

A Windows VPS

The simplest option that keeps the official package: rent a Windows machine, install the terminal, run your Python there, and expose what you need to the rest of your system yourself.

What all of them have in common

Each approach runs a full desktop trading terminal that you now operate:

  • One terminal per account at a time. A terminal is logged in to one trading account; trading many accounts at once means running many terminals and keeping track of which is which.
  • A GUI application on a server. It expects a display (a virtual one under Xvfb or VNC), updates itself, and can stop on a dialog nobody sees.
  • Keeping it alive is your job: restarts, logins after a broker disconnect, disk and memory per terminal, and noticing when one has quietly stopped.
  • Your code is tied to where the terminal runs, which is usually not where the rest of your application runs.

For one personal account on one machine, that is often fine. For a product that trades other people's accounts, it becomes an operations project.

Doing it over HTTP instead

fxapis runs the MetaTrader 5 terminals for you, in our cloud, and gives you a REST API. Your code — on macOS, Linux, Windows, a container, a serverless function, in any language — makes HTTPS requests:

  • No terminal, VPS, Wine or Expert Advisor on your side.
  • Many accounts at once, each connected with its login, password and server.
  • An account comes online in about ten seconds in our tests when needed, and can go offline by itself when idle.
  • Orders sent with an Idempotency-Key are safe to retry with the same key, and every order gets a recorded result; an unclear one is confirmed with the broker, not guessed.

The same trade, both ways

With the official package, on Windows, next to a terminal:

import MetaTrader5 as mt5

mt5.initialize(login=26177561, password="…", server="VantageMarkets-Demo")
tick = mt5.symbol_info_tick("EURUSD")
result = mt5.order_send({
    "action": mt5.TRADE_ACTION_DEAL,
    "symbol": "EURUSD",
    "volume": 0.01,
    "type": mt5.ORDER_TYPE_BUY,
    "price": tick.ask,
    "deviation": 20,
})
print(result.retcode, result.price)
mt5.shutdown()

With fxapis, from anywhere:

import os, uuid, requests

API = "https://api.fxapis.com"
s = requests.Session()
s.headers["Authorization"] = f"Bearer {os.environ['FXAPIS_KEY']}"

account = s.post(f"{API}/v1/accounts", json={
    "login": "26177561", "server": "VantageMarkets-Demo",
    "password": os.environ["MT5_PASSWORD"], "mode": "warm_on_demand",
}).json()["data"]                                   # once; keep account["id"]

order = s.post(f"{API}/v1/accounts/{account['id']}/orders/market",
    headers={"Idempotency-Key": str(uuid.uuid4())},
    json={"symbol": "EURUSD", "side": "buy", "volume": "0.01", "deviationPoints": 20},
    timeout=90,
).json()["data"]
print(order["state"], order["filledPrice"], order["retcode"])

The fxapis version needs no price: a market order executes at the market, and an account in warm_on_demand mode comes online by itself for the order. For a complete program with correct retries, see the Python guide — or the same program in Node.js, PHP, C#, Go, Java or Ruby.

Mapping the package's calls

MetaTrader5 packagefxapis
initialize(), login()POST /v1/accounts once, then POST /v1/accounts/{id}/warm (or let an order bring it online)
shutdown()POST /v1/accounts/{id}/cool, or nothing — idle accounts go offline by themselves
order_send() with TRADE_ACTION_DEALPOST /v1/accounts/{id}/orders/market
order_send() with TRADE_ACTION_PENDINGPOST /v1/accounts/{id}/orders/pending
order_send() with TRADE_ACTION_SLTPPOST /v1/accounts/{id}/positions/{ticket}/modify
order_send() with TRADE_ACTION_REMOVEPOST /v1/orders/{id}/cancel
Closing with an opposite TRADE_ACTION_DEALPOST /v1/accounts/{id}/positions/{ticket}/close
positions_get()GET /v1/accounts/{id}/positions
history_deals_get()GET /v1/accounts/{id}/deals
history_orders_get()GET /v1/orders?accountId=…
order_calc_margin(), order_calc_profit()POST /v1/accounts/{id}/calculate
symbol_info_tick(), copy_rates_*(), copy_ticks_*()No equivalent — see below

Some differences to expect:

  • Volumes and prices are strings ("0.01"), not floats, so no size is ever rounded by a double.
  • Stops are absolute prices, as in MT5.
  • Return codes are kept. Each order carries the broker's own retcode; errors carry a stable code such as ORDER_REJECTED or SEND_FAILED. See Errors.
  • Positions are a snapshot with a timestamp (observedAt), refreshed about every 15 seconds while the account is online.

What fxapis does not replace

fxapis is for trading accounts and their history. It does not stream prices or serve bars and ticks, so if your strategy computes signals from MT5 market data, you need a data source for that part. It supports MetaTrader 5 only, not MetaTrader 4. There are no event webhooks yet; you poll.

Next steps

On this page