PycURL exposes libcurl’s FTP and SOCKS support through one transfer handle. For a passive FTP download, the application can leave both the control connection and the separate data connection to that implementation.

import pycurl

transfer = pycurl.Curl()
try:
    transfer.setopt(pycurl.URL, ftp_url)
    transfer.setopt(pycurl.PROXY, "socks5h://proxy.example.net:1080")
    transfer.setopt(pycurl.NOPROXY, "")
    transfer.setopt(pycurl.WRITEDATA, output)
    transfer.setopt(pycurl.CONNECTTIMEOUT, 10)
    transfer.setopt(pycurl.TIMEOUT, 60)
    transfer.perform()
finally:
    transfer.close()

ftp_url is the application’s FTP resource URL, and output is an already-open binary output stream. The timeouts are example limits to choose for the expected file size and connection. For a public FTP resource where public intermediaries are permitted, the SOCKS5 proxy list offers candidates for the proxy URL; check that the chosen node allows both the control and passive data destinations.

socks5h delegates destination hostname resolution to the SOCKS proxy. NOPROXY is explicitly empty so an inherited no_proxy environment setting does not bypass the route for this transfer.

Leave active FTP disabled: it expects an incoming server connection and is unavailable with this proxy mode. The proxy’s outbound policy must allow the FTP control port and the passive data port selected for the transfer. Successful login alone therefore does not establish that the file can be downloaded.

When authentication is needed, use PycURL’s PROXYUSERNAME and PROXYPASSWORD for the intermediary; FTP server credentials belong to the FTP connection.

Ũhoro ũhĩtĩte