I hope you’re doing well.
I’m working on a Python program that utilizes the MEXC API to retrieve historical data on the crypto market.
The code functions correctly for about 100 to 300 iterations, but I eventually encounter the error below.
I attempted to restrict the iterations to 5, and while it sometimes completes these iterations, it also occasionally triggers the same error again.
the sample code:
import requests
from datetime import datetime, timezone
from pandas import DataFrame, concat, date_range
base_endpoint = r"https://api.mexc.com"
def interval_range(
start=datetime.fromtimestamp(0, timezone.utc),
end=datetime.now(timezone.utc).replace(second=0, microsecond=0),
timeframe: str = "1m",
):
freq = ""
if timeframe == "1m":
freq = "16h"
elif timeframe == "5m":
freq = "83h"
elif timeframe == "15m":
freq = "250h"
elif timeframe == "30m":
freq = "500h"
elif timeframe == "60m":
freq = "1000h"
elif timeframe == "4h":
freq = "4000h"
elif timeframe == "1d":
freq = "24000h"
elif timeframe == "1W":
freq = "168000h"
elif timeframe == "1M":
freq = "1000MS"
intervals = date_range(start, end, freq=freq).to_pydatetime().tolist()
intervals.append(end)
return [(intervals[i], intervals[i + 1]) for i in range(len(intervals) - 1)]
def get_historical_data(
symbol: str,
timeframe: str = "1m",
start: datetime = datetime.fromtimestamp(0, timezone.utc),
end: datetime = datetime.now(timezone.utc).replace(second=0, microsecond=0),
):
endpoint = base_endpoint + r"/api/v3/klines"
intervals = interval_range(start, end, timeframe)
intervals.reverse()
df = None
columns = [
"open timestamp",
"open",
"high",
"low",
"close",
"volume",
"close timestamp",
"quote asset volume",
]
for index, interval in enumerate(intervals):
print(f"<{index} of {len(intervals)}>")
payload = {
"symbol": symbol,
"interval": timeframe,
"startTime": int(interval[0].timestamp() * 1000),
"endTime": int(interval[1].timestamp() * 1000),
"limit": 1000,
}
response = requests.get(url=endpoint, params=payload, timeout=30)
if response.status_code == 200:
new_df = DataFrame(response.json(), columns=columns)
if df is None:
df = new_df
else:
df = concat([df, new_df])
else:
raise f"Error [{response.status_code}]: {response.json()["msg"]}"
df = df.sort_values("open timestamp")
df = df[~df.duplicated(keep="last")]
df = df.reset_index(drop=True)
return df
btcusdt_df = get_historical_data("BTCUSDT")
btcusdt_df.to_csv("BTCUSDT.csv")
The output:
<0 of 30127>
<1 of 30127>
<2 of 30127>
<3 of 30127>
...
<128 of 30127>
<129 of 30127>
<130 of 30127>
<131 of 30127>
<132 of 30127>
Traceback (most recent call last):
File "venvLibsite-packagesurllib3connectionpool.py", line 464, in _make_request
self._validate_conn(conn)
~~~~~~~~~~~~~~~~~~~^^^^^^
File "venvLibsite-packagesurllib3connectionpool.py", line 1093, in _validate_conn
conn.connect()
~~~~~~~~~~~~^^
File "venvLibsite-packagesurllib3connection.py", line 741, in connect
sock_and_verified = _ssl_wrap_socket_and_match_hostname(
sock=sock,
...<14 lines>...
assert_fingerprint=self.assert_fingerprint,
)
File "venvLibsite-packagesurllib3connection.py", line 920, in _ssl_wrap_socket_and_match_hostname
ssl_sock = ssl_wrap_socket(
sock=sock,
...<8 lines>...
tls_in_tls=tls_in_tls,
)
File "venvLibsite-packagesurllib3utilssl_.py", line 460, in ssl_wrap_socket
ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls, server_hostname)
File "venvLibsite-packagesurllib3utilssl_.py", line 504, in _ssl_wrap_socket_impl
return ssl_context.wrap_socket(sock, server_hostname=server_hostname)
~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "PythonPython313Libssl.py", line 455, in wrap_socket
return self.sslsocket_class._create(
~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
sock=sock,
^^^^^^^^^^
...<5 lines>...
session=session
^^^^^^^^^^^^^^^
)
^
File "PythonPython313Libssl.py", line 1076, in _create
self.do_handshake()
~~~~~~~~~~~~~~~~~^^
File "PythonPython313Libssl.py", line 1372, in do_handshake
self._sslobj.do_handshake()
~~~~~~~~~~~~~~~~~~~~~~~~~^^
ssl.SSLError: [SSL: DECRYPTION_FAILED_OR_BAD_RECORD_MAC] decryption failed or bad record mac (_ssl.c:1020)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "venvLibsite-packagesurllib3connectionpool.py", line 787, in urlopen
response = self._make_request(
conn,
...<10 lines>...
**response_kw,
)
File "venvLibsite-packagesurllib3connectionpool.py", line 488, in _make_request
raise new_e
urllib3.exceptions.SSLError: [SSL: DECRYPTION_FAILED_OR_BAD_RECORD_MAC] decryption failed or bad record mac (_ssl.c:1020)
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "venvLibsite-packagesrequestsadapters.py", line 667, in send
resp = conn.urlopen(
method=request.method,
...<9 lines>...
chunked=chunked,
)
File "venvLibsite-packagesurllib3connectionpool.py", line 841, in urlopen
retries = retries.increment(
method, url, error=new_e, _pool=self, _stacktrace=sys.exc_info()[2]
)
File "venvLibsite-packagesurllib3utilretry.py", line 519, in increment
raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='api.mexc.com', port=443): Max retries exceeded with url: /api/v3/klines?symbol=BTCUSDT&interval=1m&startTime=1732204800000&endTime=1732262400000&limit=1000 (Caused by SSLError(SSLError(1, '[SSL: DECRYPTION_FAILED_OR_BAD_RECORD_MAC] decryption failed or bad record mac (_ssl.c:1020)')))
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "test.py", line 81, in <module>
btcusdt_df = get_historical_data("BTCUSDT")
File "test.py", line 66, in get_historical_data
response = requests.get(url=endpoint, params=payload, timeout=30)
File "venvLibsite-packagesrequestsapi.py", line 73, in get
return request("get", url, params=params, **kwargs)
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "venvLibsite-packagesrequestssessions.py", line 589, in request
resp = self.send(prep, **send_kwargs)
File "venvLibsite-packagesrequestssessions.py", line 703, in send
r = adapter.send(request, **kwargs)
File "venvLibsite-packagesrequestsadapters.py", line 698, in send
raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='api.mexc.com', port=443): Max retries exceeded with url: /api/v3/klines?symbol=BTCUSDT&interval=1m&startTime=1732204800000&endTime=1732262400000&limit=1000 (Caused by SSLError(SSLError(1, '[SSL: DECRYPTION_FAILED_OR_BAD_RECORD_MAC] decryption failed or bad record mac (_ssl.c:1020)')))
What leads to this error? What is the most effective way to resolve this issue?