Search code examples
curlproxypycurl

How to connect to a HTTPS proxy (secure web proxy) in pycurl?


I'm trying to connect to a secure web proxy with pycurl. When trying to set the appropriate proxy type, these options are available, which correspond to the curl proxy options (in brackets):

 - "PROXYTYPE_HTTP" (CURLPROXY_HTTP)
 - "PROXYTYPE_HTTP_1_0" (CURLPROXY_HTTP_1_0)
 - "PROXYTYPE_SOCKS4" (CURLPROXY_SOCKS4)
 - "PROXYTYPE_SOCKS4A" (CURLPROXY_SOCKS4A)
 - "PROXYTYPE_SOCKS5" (CURLPROXY_SOCKS5)
 - "PROXYTYPE_SOCKS5_HOSTNAME" (CURLPROXY_SOCKS5_HOSTNAME)

But, there's also a curl option called CURLPROXY_HTTPS, as stated in the docs, that does not seem to be available.

With plain curl, I use this command to connect to the proxy:

curl --proxy https://proxy-host:proxy-port --proxy-insecure -U username:password https://target.com

And everything just works as expected. But not with pycurl.

How can I achieve the same behavior in pycurl?


Solution

  • Following the suggestion I got in the pycurl github issues, I've found the option code for CURLPROXY_HTTPS, and it is 2.

    I was able to make a request through a secure web proxy with pycurl using the next code:

    import pycurl
    from io import BytesIO
    import certifi
    
    
    def request_with_pycurl(username, password, host, port, target_url='https://api.ipify.org/'):
        buffer = BytesIO()
        c = pycurl.Curl()
    
        c.setopt(pycurl.CAINFO, certifi.where())
    
        # set proxy-insecure
        c.setopt(c.PROXY_SSL_VERIFYHOST, 0)
        c.setopt(c.PROXY_SSL_VERIFYPEER, 0)
    
        # set headers
        c.setopt(pycurl.USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:8.0) Gecko/20100101 Firefox/8.0')
    
        # set proxy
        c.setopt(pycurl.PROXY, f"https://{host}:{port}")
    
        # proxy auth
        c.setopt(pycurl.PROXYUSERPWD, f"{username}:{password}")
    
        # set proxy type = "HTTPS"
        c.setopt(pycurl.PROXYTYPE, 2)
    
        # target url
        c.setopt(c.URL, target_url)
    
        c.setopt(c.WRITEDATA, buffer)
        c.perform()
        c.close()
    
        body = buffer.getvalue()
        return body
    
    
    response = request_with_pycurl("proxy_username", "proxy_password", "proxy_host", "proxy_port").decode()
    
    print(response)