This document describes a few notes specifically for Windows users on networks with custom certificates or proxy settings. For regular Windows users, things should work out of the box.


Multiple SSL Backends

In order to make SSL (https) connections, libcurl uses an SSL backend. Currently the Windows version of the curl package supports two SSL backends: OpenSSL and Windows Secure Channel. Only one can be enabled, which is determined when the curl package is first loaded in your R session.

Secure Channel OpenSSL
trust certificates Windows Cert Store curl-ca-bundle.crt file
works on corporate networks Usually Yes Maybe not
support http proxy server Yes Yes
support https proxy server No Yes
support client certificate authentication No Yes

The default backend on Windows 7 and up is Secure Channel. This uses the native Windows SSL API and certificates, which is the safest choice for most users.

To switch to OpenSSL, you need to set an environment variable CURL_SSL_BACKEND to "openssl" when starting R. A good place to set this is in your .Renviron file in your user home (Documents) directory; the ?Startup manual has more details.


Optionally, you can also set CURL_CA_BUNDLE here to use a custom trust bundle. If CURL_CA_BUNDLE is not set, we use curl-ca-bundle.crt which is included with R for Windows. When using Schannel, no trust bundle is needed because we use the certificates from the native Windows cert store.

Have a look at curl::curl_version() to see which ssl backends are available and which one is in use.

#> $version
#> [1] "7.64.1"
#> $ssl_version
#> [1] "(OpenSSL/1.1.1a) Schannel"
#> $libz_version
#> [1] "1.2.8"
#> ...

The part in parentheses means this backend is available but currently not in use. Hence the output above means that the current active backend is Secure Channel, but OpenSSL is also supported.

It is not possible to change the SSL backend once the curl package has been loaded.

Using a Proxy Server

Windows proxy servers are a complicated topic because depending on your corporate network configuration, different settings may be needed. If your company uses proxies with custom certificates, this might also interact with the previous topic.

Proxy settings can either be configured in the handle for a single request, or globally via environment variables. This is explained in detail on the curl website detail in the manual pages for CURLOPT_PROXY and libcurl-env.

If you know the address of your proxy server you can set it via the curlopt_proxy option:

h <- new_handle(proxy = "http://proxyserver:8080", verbose = TRUE)
req <- curl_fetch_memory("", handle = h)
#> Verbose output here...

The example above should yield some verbose output indicating if the proxy connection was successful.

If this did not work, study the verbose output from above to see what seems to be the problem. Note that curl supports many options related to proxies (types, auth, etc), the details of which you can find on the libcurl homepage.

##        haproxyprotocol        httpproxytunnel                noproxy              pre_proxy                  proxy 
##                    274                     61                  10177                  10262                  10004 
##           proxy_cainfo           proxy_capath          proxy_crlfile        proxy_keypasswd  proxy_pinnedpublickey 
##                  10246                  10247                  10260                  10258                  10263 
##     proxy_service_name  proxy_ssl_cipher_list      proxy_ssl_options   proxy_ssl_verifyhost   proxy_ssl_verifypeer 
##                  10235                  10259                    261                    249                    248 
##          proxy_sslcert      proxy_sslcerttype           proxy_sslkey       proxy_sslkeytype       proxy_sslversion 
##                  10254                  10255                  10256                  10257                    250 
##    proxy_tls13_ciphers proxy_tlsauth_password     proxy_tlsauth_type proxy_tlsauth_username    proxy_transfer_mode 
##                  10277                  10252                  10253                  10251                    166 
##              proxyauth            proxyheader          proxypassword              proxyport              proxytype 
##                    111                  10228                  10176                     59                    101 
##          proxyusername           proxyuserpwd 
##                  10175                  10006

To use a global proxy server for all your requests, you can set the environment variable http_proxy (lowercase!) or https_proxy or ALL_PROXY. See this page for details. This variable may be set or changed in R at runtime, for example:

Sys.setenv(ALL_PROXY = "")
req <- curl_fetch_memory("")
#> verbose output here...

To use a default proxy server for all your R sessions, a good place to set this environment variable is in your .Renviron as explained above:


An additional benefit of setting these environment variables is that they are also supported by base R download.file and install.packages. The manual page for ?download.file has a special section on “Setting Proxies” which explains this.

Discovering Your Proxy Server

If you don’t know what your proxy server is, the curl package has a few utilities that interact with Internet Explorer to help you find out. First have a look at ie_proxy_info() to see IE settings:

#> $AutoDetect
#> [1] FALSE
#> $AutoConfigUrl
#> [1] ""
#> $Proxy
#> [1] ""
#> $ProxyBypass
#> [1] "10.*;173.*;;;;"

There are a few settings here, such as default proxy server and a list of hosts which do not need proxying, usually hosts within the corporate intranet (these can probably be used in CURLOPT_NOPROXY).

The most complicated case is when your network uses different proxy servers for different target urls. The AutoConfigUrl field above refers to a proxy auto config (PAC) script that Internet Explorer has to run to find out which proxy server it has to use for a given host. The curl package exposes another function which calls out to Internet Explorer do it’s thing and tell us the appropriate proxy server for a given host:

#> [1] ""


The exact logic that Windows uses to derive the appropriate proxy server for a given host from the settings above is very complicated and may involve some trial and error until something works.

Currently curl does not automatically set IE proxies, so you need to manually set these in the handles or environment variables. One day we could try to make the curl package automatically discover and apply Windows proxy settings. However to make sure we cover all edge cases we need more examples from users in real world corporate networks.