_PROXY_POOL.next() is called in exactly one place — moon_download.py:448, inside download_file:
proxy_cfg = _PROXY_POOL.next()
dl_session = _PROXY_POOL.get_session(proxy_cfg) if proxy_cfg else _sess()
So proxies wrap the download HTTP session and nothing else. moon_extract.py never receives one: the browser that loads the file host's page, runs the Cloudflare challenge and solves Turnstile connects directly, from the user's real address, on every run.
That may well be the right design — the bandwidth is in the download, and routing a real Chrome through a rotating proxy pool would make the challenge harder to pass, not easier. The problem is that no document says so.
Every mention is about the file format or about load-time warnings, never about scope:
| Where |
What it says |
README.md:284 |
"Proxy list — ip:port:user:pass or http://user:pass@ip:port" |
docs/CONFIGURATION.md:136 |
the same line |
docs/CLI.md:23-36 |
--proxies default, and the four warning cases |
Someone who configures a proxy list reasonably assumes it applies to the whole run. It does not, and the half that does not is the half that identifies them to the host.
This is not theoretical — it was reported by a user who put deliberately unusable proxies in proxies.txt, watched the pages open anyway, and concluded the proxy system was broken. It was working exactly as built; the documentation simply never set the expectation.
What is needed
State the scope wherever proxies.txt is documented — README, docs/CONFIGURATION.md, docs/CLI.md. Something with no ambiguity in it, e.g.:
Proxies apply to file downloads only. Link extraction — including the browser session used for datanodes and its Cloudflare challenge — always connects directly.
Worth adding alongside it, in CONFIGURATION.md, one sentence on why, so the next reader does not file it as a bug: a rotating proxy pool makes the challenge harder to pass, and the traffic worth routing is the transfer.
Acceptance criteria
- All three documents state the scope; no reader can conclude proxies cover extraction
- The wording is checked against
moon_download.py:448 rather than against this issue
- No code changes — this is a documentation issue. If you think the behaviour itself should change, open a separate issue for it
Small, no Windows machine needed. Found by using the program.
_PROXY_POOL.next()is called in exactly one place —moon_download.py:448, insidedownload_file:So proxies wrap the download HTTP session and nothing else.
moon_extract.pynever receives one: the browser that loads the file host's page, runs the Cloudflare challenge and solves Turnstile connects directly, from the user's real address, on every run.That may well be the right design — the bandwidth is in the download, and routing a real Chrome through a rotating proxy pool would make the challenge harder to pass, not easier. The problem is that no document says so.
Every mention is about the file format or about load-time warnings, never about scope:
README.md:284ip:port:user:passorhttp://user:pass@ip:port"docs/CONFIGURATION.md:136docs/CLI.md:23-36--proxiesdefault, and the four warning casesSomeone who configures a proxy list reasonably assumes it applies to the whole run. It does not, and the half that does not is the half that identifies them to the host.
This is not theoretical — it was reported by a user who put deliberately unusable proxies in
proxies.txt, watched the pages open anyway, and concluded the proxy system was broken. It was working exactly as built; the documentation simply never set the expectation.What is needed
State the scope wherever
proxies.txtis documented — README,docs/CONFIGURATION.md,docs/CLI.md. Something with no ambiguity in it, e.g.:Worth adding alongside it, in
CONFIGURATION.md, one sentence on why, so the next reader does not file it as a bug: a rotating proxy pool makes the challenge harder to pass, and the traffic worth routing is the transfer.Acceptance criteria
moon_download.py:448rather than against this issueSmall, no Windows machine needed. Found by using the program.