Good afternoon QuantConnect team and community,
I believe I isolated a regression/issue with QCAlgorithm.download in Python Cloud Backtests and Live Paper.
The issue is not general external connectivity. download(url) works, and download(url, {}) works. However, download(url, non-empty headers) returns an empty string.
This affects both Cloud Backtests and Live Paper.
Environment:
- Language: Python
- LEAN Engine: v2.5.0.0.17695
- Cloud Backtest DL2 Algorithm Id: cb8abfa1cc2d64e6ff4d728573f26eb1
- Cloud Backtest DL3 Algorithm Id: 8788e06c589f8f6dab353989d6fedd21
- Live Paper Smoke Algorithm Id: 4b5d929b1580c7b999d505246695328e
Observed Cloud Backtest results:
DL2 token_present=1 token_len=93 qc_bearer_present=0 qc_bearer_len=0
download(url) works:
DL2 result name=raw_public_no_headers len=14 empty=0 preview=404: Not Found
DL2 result name=github_api_public_no_headers len=141 empty=0 preview={"message": "Not Found", ...
DL2 result name=cloudflare_public_health_no_headers len=43 empty=0 preview={"ok":true,"ts":"2026-05-05T22:43:55.815Z"}
download(url, {}) works:
DL2 result name=raw_public_empty_headers len=14 empty=0 preview=404: Not Found
download(url, non-empty headers) returns empty:
DL2 result name=raw_public_user_agent len=0 empty=1 preview=
DL2 result name=github_api_public_headers len=0 empty=1 preview=
DL2 result name=github_api_private_bearer len=0 empty=1 preview=
Basic-auth overload also returns empty:
DL3 github_token_present=1 github_token_len=93 state_secret_present=0 state_secret_len=0
DL3 result name=github_private_basic_empty_headers len=0 empty=1 preview=
Observed Live Paper results:
LIVE_DL token_present=1 token_len=93 state_secret_present=0 state_secret_len=0
LIVE_DL result name=cloudflare_public_health_no_headers len=43 empty=0 preview={"ok":true,"ts":"2026-05-05T23:06:18.393Z"}
LIVE_DL result name=cloudflare_public_health_empty_headers len=43 empty=0 preview={"ok":true,"ts":"2026-05-05T23:06:18.569Z"}
LIVE_DL result name=cloudflare_public_health_user_agent len=0 empty=1 preview=
LIVE_DL result name=github_private_parameters_bearer len=0 empty=1 preview=
The same GitHub request works from my local terminal with HTTP 200 and a valid JSON body. The GitHub token is valid and has contents=read permission.
Impact:
My algorithm loads a private GitHub JSON config file using QCAlgorithm.download(url, headers). This worked previously, but now returns an empty body and causes:
Strategy config ERROR ... empty_response
This also affects bearer-protected endpoints used for closed-loop state reads, because those also require Authorization headers.
The behavior seems isolated to non-empty headers/authentication:
download(url) works
download(url, {}) works
download(url, {"User-Agent": ...}) returns empty
download(url, Authorization header) returns empty
download(url, {}, user, password) returns empty
Could someone from QuantConnect please check whether there is a regression in Python QCAlgorithm.download(url, headers) and QCAlgorithm.download(url, headers, userName, password) in Cloud Backtests and Live Paper?
Minimal repro code below.
from AlgorithmImports import *
from typing import Any, cast
class DownloadHeadersRepro(QCAlgorithm):
def initialize(self):
self.set_start_date(2024, 1, 1)
self.set_cash(100000)
tests = [
(
"cloudflare_health_no_headers",
"https://steffi-webhook.orazmedov-timur.workers.dev/health",
None,
),
(
"cloudflare_health_empty_headers",
"https://steffi-webhook.orazmedov-timur.workers.dev/health",
{},
),
(
"cloudflare_health_user_agent",
"https://steffi-webhook.orazmedov-timur.workers.dev/health",
{"User-Agent": "Steffi"},
),
(
"github_api_public_no_headers",
"https://api.github.com/repos/QuantConnect/Lean/contents/README.md",
None,
),
(
"github_api_public_user_agent",
"https://api.github.com/repos/QuantConnect/Lean/contents/README.md",
{"User-Agent": "Steffi"},
),
]
for name, url, headers in tests:
try:
if headers is None:
txt = self.download(url)
else:
txt = self.download(url, cast(Any, headers))
s = "" if txt is None else str(txt)
preview = s[:120].replace("\n", " ")
self.log(
f"REPRO name={name} len={len(s)} "
f"empty={1 if s.strip()=='' else 0} preview={preview}"
)
except Exception as e:
self.log(f"REPRO error name={name} err={str(e)[:300]}")
self.quit("REPRO_DONE")
Timur
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!