Problem Description
Solution
To fetch data from a website or a JSON API in MQL4, you must use the built-in WebRequest function. Since MQL4 does not have a native JSON parser, you must also implement a method to parse the returned string to extract the specific data you need.
Prerequisites
Before the code will work, you must enable HTTP requests in your MetaTrader 4 terminal:
- Go to Tools -> Options -> Expert Advisors.
- Check "Allow WebRequest for listed URL".
- Add the specific URL of your API to the list (e.g.,
https://api.binance.comorhttps://jsonplaceholder.typicode.com).
Implementation Strategy
WebRequest: Sends a GET request to the API.CharArrayToString: Converts the raw byte response into a readable string.- Custom Parsing: A helper function searches the string for a specific JSON key (e.g.,
"price":) and extracts the value associated with it.
MQL4 Code Example
This Expert Advisor fetches data from a public testing API. It sends a request, receives a JSON response, and parses a specific value.
//+------------------------------------------------------------------+
//| APIFetcherBot.mq4 |
//| Copyright 2023, Quantitative |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Quantitative"
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
//--- Input Parameters
input string InpUrl = "https://jsonplaceholder.typicode.com/todos/1"; // Example API URL
input int InpTimeout = 5000; // Timeout in milliseconds
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Check if WebRequest is allowed
if(!TerminalInfoInteger(TERMINAL_DLLS_ALLOWED))
{
Print("Error: DLLs must be allowed for some network functions (optional check).");
}
// Note: There is no direct programmatic check for "Allow WebRequest"
// specifically, but the function will return error 4060 if not allowed.
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// We use a static variable to run this only once per bar or specific interval
// to avoid spamming the API and getting banned.
static datetime lastCheck = 0;
if(TimeCurrent() - lastCheck < 10) return; // Wait 10 seconds between requests
lastCheck = TimeCurrent();
// --- 1. Prepare Request Data ---
char postData[]; // Array for POST data (empty for GET)
char resultData[]; // Array to store the API response
string resultHeaders; // To store response headers
// --- 2. Send the WebRequest ---
// Reset error state
ResetLastError();
int res = WebRequest(
"GET", // HTTP Method
InpUrl, // URL
NULL, // Cookie (usually NULL)
NULL, // Referer (usually NULL)
InpTimeout, // Timeout
postData, // POST data array
0, // Data size (0 for GET)
resultData, // Result array
resultHeaders // Result headers
);
// --- 3. Handle the Response ---
if(res == -1)
{
int error = GetLastError();
if(error == 4060)
{
Print("Error 4060: WebRequest not allowed. Go to Tools->Options->Expert Advisors and add the URL.");
}
else
{
Print("WebRequest failed. Error code: ", error);
}
}
else if(res == 200) // HTTP 200 OK
{
// Convert the character array to a string
string jsonResponse = CharArrayToString(resultData);
Print("Raw JSON: ", jsonResponse);
// --- 4. Parse Specific Data ---
// Example: Extracting the value of the "title" key from the JSON
string titleValue = GetJsonValue(jsonResponse, "title");
string completedValue = GetJsonValue(jsonResponse, "completed");
Print("Parsed Title: ", titleValue);
Print("Parsed Completed Status: ", completedValue);
// Logic Example: If 'completed' is false, maybe do something
if(completedValue == "false")
{
// Trading logic here...
}
}
else
{
Print("API returned unexpected HTTP code: ", res);
}
}
//+------------------------------------------------------------------+
//| Helper: Simple JSON Value Extractor |
//| Note: This is a basic string parser. For complex nested JSON, |
//| a dedicated library is recommended. |
//+------------------------------------------------------------------+
string GetJsonValue(string json, string key)
{
string searchKey = "\"" + key + "\"";
int startPos = StringFind(json, searchKey);
if(startPos == -1) return(""); // Key not found
// Move position to the end of the key
startPos += StringLen(searchKey);
// Find the colon
int colonPos = StringFind(json, ":", startPos);
if(colonPos == -1) return("");
// Start reading after the colon
int valueStart = colonPos + 1;
// Skip whitespace
while(StringSubstr(json, valueStart, 1) == " " && valueStart < StringLen(json))
{
valueStart++;
}
// Check if value is a string (starts with quote)
bool isString = (StringSubstr(json, valueStart, 1) == "\"");
int valueEnd;
if(isString)
{
valueStart++; // Move past opening quote
valueEnd = StringFind(json, "\"", valueStart);
}
else
{
// Find end of value (comma or closing brace)
int commaPos = StringFind(json, ",", valueStart);
int bracePos = StringFind(json, "}", valueStart);
if(commaPos == -1) valueEnd = bracePos;
else if(bracePos == -1) valueEnd = commaPos;
else valueEnd = MathMin(commaPos, bracePos);
}
if(valueEnd == -1) return("");
return(StringSubstr(json, valueStart, valueEnd - valueStart));
}
//+------------------------------------------------------------------+
Key Considerations for MQL4 Networking
- Synchronous Execution:
WebRequestis synchronous. This means the entire trading robot pauses and waits for the server to respond. If the API takes 2 seconds to respond, your EA stops processing ticks for 2 seconds. Do not use this in high-frequency scalping strategies insideOnTickwithout careful timer management. - Indicators: You cannot use
WebRequestinside Custom Indicators. It only works in Expert Advisors (EAs) and Scripts. - JSON Complexity: The
GetJsonValuefunction provided above is a lightweight text parser. It works for flat JSON structures (e.g.,{"price": 1.12, "vol": 100}). If you are dealing with complex, nested arrays (e.g.,{"data": [{"id": 1}, {"id": 2}]}), you should look for a dedicated MQL4 JSON library (such asJAson.mqh) rather than writing your own parser. - Error 4060: This is the most common error. It means you forgot to add the specific URL to the "Allowed URLs" list in the terminal settings.
Q&A
Q: Can I use Python to get the data and send it to MT4?
A: Yes. You can write a Python script to fetch the data and write it to a text file in the MQL4/Files folder (common folder). The MT4 EA can then read that file using FileOpen. This avoids the freezing issue of WebRequest.
Q: How do I send data (POST) instead of getting it?
A: You need to populate the postData array.
string headers = "Content-Type: application/json\r\n";
string jsonBody = "{\"signal\": \"buy\"}";
char postData[];
StringToCharArray(jsonBody, postData);
int res = WebRequest("POST", url, headers, NULL, timeout, postData, ArraySize(postData), resultData, resultHeaders);
Q: Why does my EA freeze when fetching data?
A: As mentioned, WebRequest halts execution until a response is received. To mitigate this, run the request in a separate "Timer" event (OnTimer) rather than OnTick, or use a separate "Worker EA" just for data fetching that writes to Global Variables, which your main trading EA reads.