<p dir="auto">On Windows, the proxy settings in Windows Registry will override the <code class="notranslate">proxies</code> attribute in <code class="notranslate">session</code> object. Here is a sample code:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import requests

url = 'https://finance.yahoo.com/quote/AAPL/history'
params = {'period1': 1648497600, 'period2': 1649793599, 'interval': '1d', 'frequency': '1d', 'filter': 'history'}
proxies = {'http': 'socks5h://127.0.0.1:10808', 'https': 'socks5h://127.0.0.1:10808'}
headers = {'User-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}

# using session
session = requests.Session()
session.headers.update(headers)
session.proxies.update(proxies)
# r1 = session.get(url, params=params)    # this line will raise exception
#
# Exception has occurred: SSLError
# HTTPSConnectionPool(host='finance.yahoo.com', port=443): Max retries exceeded with url: /quote/AAPL/history?period1=1648497600&amp;period2=1649793599&amp;interval=1d&amp;frequency=1d&amp;filter=history (Caused by SSLError(SSLEOFError(8, 'EOF occurred in violation of protocol (_ssl.c:1129)')))

# using requests.get
r2 = requests.get(url, params=params, headers=session.headers, proxies=session.proxies)   # OKAY
r3 = requests.get(url, params=params, headers=headers, proxies=proxies)            # OKAY
r4 = session.get(url, params=params, headers=headers, proxies=proxies)            # OKAY"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">requests</span>

<span class="pl-s1">url</span> <span class="pl-c1">=</span> <span class="pl-s">'https://finance.yahoo.com/quote/AAPL/history'</span>
<span class="pl-s1">params</span> <span class="pl-c1">=</span> {<span class="pl-s">'period1'</span>: <span class="pl-c1">1648497600</span>, <span class="pl-s">'period2'</span>: <span class="pl-c1">1649793599</span>, <span class="pl-s">'interval'</span>: <span class="pl-s">'1d'</span>, <span class="pl-s">'frequency'</span>: <span class="pl-s">'1d'</span>, <span class="pl-s">'filter'</span>: <span class="pl-s">'history'</span>}
<span class="pl-s1">proxies</span> <span class="pl-c1">=</span> {<span class="pl-s">'http'</span>: <span class="pl-s">'socks5h://127.0.0.1:10808'</span>, <span class="pl-s">'https'</span>: <span class="pl-s">'socks5h://127.0.0.1:10808'</span>}
<span class="pl-s1">headers</span> <span class="pl-c1">=</span> {<span class="pl-s">'User-agent'</span>: <span class="pl-s">'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15'</span>, <span class="pl-s">'Accept-Encoding'</span>: <span class="pl-s">'gzip, deflate'</span>, <span class="pl-s">'Accept'</span>: <span class="pl-s">'*/*'</span>, <span class="pl-s">'Connection'</span>: <span class="pl-s">'keep-alive'</span>}

<span class="pl-c"># using session</span>
<span class="pl-s1">session</span> <span class="pl-c1">=</span> <span class="pl-s1">requests</span>.<span class="pl-v">Session</span>()
<span class="pl-s1">session</span>.<span class="pl-s1">headers</span>.<span class="pl-en">update</span>(<span class="pl-s1">headers</span>)
<span class="pl-s1">session</span>.<span class="pl-s1">proxies</span>.<span class="pl-en">update</span>(<span class="pl-s1">proxies</span>)
<span class="pl-c"># r1 = session.get(url, params=params)    # this line will raise exception</span>
<span class="pl-c">#</span>
<span class="pl-c"># Exception has occurred: SSLError</span>
<span class="pl-c"># HTTPSConnectionPool(host='finance.yahoo.com', port=443): Max retries exceeded with url: /quote/AAPL/history?period1=1648497600&amp;period2=1649793599&amp;interval=1d&amp;frequency=1d&amp;filter=history (Caused by SSLError(SSLEOFError(8, 'EOF occurred in violation of protocol (_ssl.c:1129)')))</span>

<span class="pl-c"># using requests.get</span>
<span class="pl-s1">r2</span> <span class="pl-c1">=</span> <span class="pl-s1">requests</span>.<span class="pl-en">get</span>(<span class="pl-s1">url</span>, <span class="pl-s1">params</span><span class="pl-c1">=</span><span class="pl-s1">params</span>, <span class="pl-s1">headers</span><span class="pl-c1">=</span><span class="pl-s1">session</span>.<span class="pl-s1">headers</span>, <span class="pl-s1">proxies</span><span class="pl-c1">=</span><span class="pl-s1">session</span>.<span class="pl-s1">proxies</span>)   <span class="pl-c"># OKAY</span>
<span class="pl-s1">r3</span> <span class="pl-c1">=</span> <span class="pl-s1">requests</span>.<span class="pl-en">get</span>(<span class="pl-s1">url</span>, <span class="pl-s1">params</span><span class="pl-c1">=</span><span class="pl-s1">params</span>, <span class="pl-s1">headers</span><span class="pl-c1">=</span><span class="pl-s1">headers</span>, <span class="pl-s1">proxies</span><span class="pl-c1">=</span><span class="pl-s1">proxies</span>)            <span class="pl-c"># OKAY</span>
<span class="pl-s1">r4</span> <span class="pl-c1">=</span> <span class="pl-s1">session</span>.<span class="pl-en">get</span>(<span class="pl-s1">url</span>, <span class="pl-s1">params</span><span class="pl-c1">=</span><span class="pl-s1">params</span>, <span class="pl-s1">headers</span><span class="pl-c1">=</span><span class="pl-s1">headers</span>, <span class="pl-s1">proxies</span><span class="pl-c1">=</span><span class="pl-s1">proxies</span>)            <span class="pl-c"># OKAY</span></pre></div>
<h2 dir="auto">Expected Result</h2>
<p dir="auto">By setting <code class="notranslate">proxies</code> in <code class="notranslate">Session</code> object, the <code class="notranslate">r1</code> line should use this setting and return successfully, like <code class="notranslate">r2</code>, <code class="notranslate">r3</code> and <code class="notranslate">r4</code>.</p>
<h2 dir="auto">Actual Result</h2>
<p dir="auto"><code class="notranslate">r1 = session.get(url, params=params)</code> line raises exception, since it is not using the proxy as specified in my code.</p>
<p dir="auto">By tracing into the source code of <code class="notranslate">requests</code>, I found the <code class="notranslate">proxies</code> setting in <code class="notranslate">Session</code> object is override by Windows registry's proxy settings, hence an Exception is raised.</p>
<p dir="auto">Below I listed the relevant pieces of codes along with the variable content of proxies.</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="# my code
proxies = {'https': 'socks5h://127.0.0.1:10808'}
session.proxies.update(proxies)
r1 = session.get(url, params=params)

# requests &gt; sessions.py &gt; Session &gt; get
def get(self, url, **kwargs)
    #...
    return self.request('GET', url, **kwargs)

# requests &gt; sessions.py
class Session:
  # ...
  def request(...):
      #...
      proxies = proxies or {}
      # after this, proxies is {}
  
      settings = self.merge_environment_settings(
          prep.url, proxies, stream, verify, cert
      )
      # now settings['proxies'] is:
      #.    OrderedDict([('https', 'https://127.0.0.1:10809'), ('http', 'http://127.0.0.1:10809'), ('ftp', 'ftp://127.0.0.1:10809')])

  def merge_environment_settings(...):
      #...
      env_proxies = get_environ_proxies(url, no_proxy=no_proxy)
      # after this call, env_proxies ends to be: 
      #     {'http': 'http://127.0.0.1:10809', 'https': 'https://127.0.0.1:10809', 'ftp': 'ftp://127.0.0.1:10809'}
      #...
      # before entering merge_setting(), proxies=
      #     {'http': 'http://127.0.0.1:10809', 'https': 'https://127.0.0.1:10809', 'ftp': 'ftp://127.0.0.1:10809'}
      # self.proxies={'https': 'socks5h://127.0.0.1:10808'}
      proxies = merge_setting(proxies, self.proxies)
      # after exit of merge_setting(), proxies=
      #     OrderedDict([('https', 'https://127.0.0.1:10809'), ('http', 'http://127.0.0.1:10809'), ('ftp', 'ftp://127.0.0.1:10809')])
      # which is completely different from what I expected
      
# requests &gt; utils.py
def get_environ_proxies(url, no_proxy=None):
    #...
        return getproxies()

# urllib&gt; request.py
def get proxies():
     return getproxies_environment() or getproxies_registry()

# urllib&gt; request.py
def getproxies_registry():
    # ....
    return proxies                 # here, proxies ends to be: {'http': 'http://127.0.0.1:10809', 'https': 'https://127.0.0.1:10809', 'ftp': 'ftp://127.0.0.1:10809'}, which is taken from Windows Regsitry

# requests &gt; sessions.py
def merge_setting(request_setting, session_setting, dict_class=OrderedDict):
    # this function considers the first argument as setting (eg proxies) within request; however, with the study above,
    # it could be a setting from system registry. My take is that it is of the lower priority than session setting, which is lower
    # request setting.
"><pre class="notranslate"><span class="pl-c"># my code</span>
<span class="pl-s1">proxies</span> <span class="pl-c1">=</span> {<span class="pl-s">'https'</span>: <span class="pl-s">'socks5h://127.0.0.1:10808'</span>}
<span class="pl-s1">session</span>.<span class="pl-s1">proxies</span>.<span class="pl-en">update</span>(<span class="pl-s1">proxies</span>)
<span class="pl-s1">r1</span> <span class="pl-c1">=</span> <span class="pl-s1">session</span>.<span class="pl-en">get</span>(<span class="pl-s1">url</span>, <span class="pl-s1">params</span><span class="pl-c1">=</span><span class="pl-s1">params</span>)

<span class="pl-c"># requests &gt; sessions.py &gt; Session &gt; get</span>
<span class="pl-k">def</span> <span class="pl-s1">get</span>(<span class="pl-s1">self</span>, <span class="pl-s1">url</span>, <span class="pl-c1">**</span><span class="pl-s1">kwargs</span>)
    <span class="pl-c">#...</span>
    <span class="pl-k">return</span> <span class="pl-s1">self</span>.<span class="pl-en">request</span>(<span class="pl-s">'GET'</span>, <span class="pl-s1">url</span>, <span class="pl-c1">**</span><span class="pl-s1">kwargs</span>)

<span class="pl-c"># requests &gt; sessions.py</span>
<span class="pl-k">class</span> <span class="pl-v">Session</span>:
  <span class="pl-c"># ...</span>
  <span class="pl-k">def</span> <span class="pl-en">request</span>(...):
      <span class="pl-c">#...</span>
      <span class="pl-s1">proxies</span> <span class="pl-c1">=</span> <span class="pl-s1">proxies</span> <span class="pl-c1">or</span> {}
      <span class="pl-c"># after this, proxies is {}</span>
  
      <span class="pl-s1">settings</span> <span class="pl-c1">=</span> <span class="pl-s1">self</span>.<span class="pl-en">merge_environment_settings</span>(
          <span class="pl-s1">prep</span>.<span class="pl-s1">url</span>, <span class="pl-s1">proxies</span>, <span class="pl-s1">stream</span>, <span class="pl-s1">verify</span>, <span class="pl-s1">cert</span>
      )
      <span class="pl-c"># now settings['proxies'] is:</span>
      <span class="pl-c">#.    OrderedDict([('https', 'https://127.0.0.1:10809'), ('http', 'http://127.0.0.1:10809'), ('ftp', 'ftp://127.0.0.1:10809')])</span>

  <span class="pl-k">def</span> <span class="pl-en">merge_environment_settings</span>(...):
      <span class="pl-c">#...</span>
      <span class="pl-s1">env_proxies</span> <span class="pl-c1">=</span> <span class="pl-en">get_environ_proxies</span>(<span class="pl-s1">url</span>, <span class="pl-s1">no_proxy</span><span class="pl-c1">=</span><span class="pl-s1">no_proxy</span>)
      <span class="pl-c"># after this call, env_proxies ends to be: </span>
      <span class="pl-c">#     {'http': 'http://127.0.0.1:10809', 'https': 'https://127.0.0.1:10809', 'ftp': 'ftp://127.0.0.1:10809'}</span>
      <span class="pl-c">#...</span>
      <span class="pl-c"># before entering merge_setting(), proxies=</span>
      <span class="pl-c">#     {'http': 'http://127.0.0.1:10809', 'https': 'https://127.0.0.1:10809', 'ftp': 'ftp://127.0.0.1:10809'}</span>
      <span class="pl-c"># self.proxies={'https': 'socks5h://127.0.0.1:10808'}</span>
      <span class="pl-s1">proxies</span> <span class="pl-c1">=</span> <span class="pl-en">merge_setting</span>(<span class="pl-s1">proxies</span>, <span class="pl-s1">self</span>.<span class="pl-s1">proxies</span>)
      <span class="pl-c"># after exit of merge_setting(), proxies=</span>
      <span class="pl-c">#     OrderedDict([('https', 'https://127.0.0.1:10809'), ('http', 'http://127.0.0.1:10809'), ('ftp', 'ftp://127.0.0.1:10809')])</span>
      <span class="pl-c"># which is completely different from what I expected</span>
      
<span class="pl-c"># requests &gt; utils.py</span>
<span class="pl-k">def</span> <span class="pl-en">get_environ_proxies</span>(<span class="pl-s1">url</span>, <span class="pl-s1">no_proxy</span><span class="pl-c1">=</span><span class="pl-c1">None</span>):
    <span class="pl-c">#...</span>
        <span class="pl-k">return</span> <span class="pl-en">getproxies</span>()

<span class="pl-c"># urllib&gt; request.py</span>
<span class="pl-k">def</span> <span class="pl-s1">get</span> <span class="pl-en">proxies</span>():
     <span class="pl-k">return</span> <span class="pl-en">getproxies_environment</span>() <span class="pl-c1">or</span> <span class="pl-en">getproxies_registry</span>()

<span class="pl-c"># urllib&gt; request.py</span>
<span class="pl-k">def</span> <span class="pl-en">getproxies_registry</span>():
    <span class="pl-c"># ....</span>
    <span class="pl-k">return</span> <span class="pl-s1">proxies</span>                 <span class="pl-c"># here, proxies ends to be: {'http': 'http://127.0.0.1:10809', 'https': 'https://127.0.0.1:10809', 'ftp': 'ftp://127.0.0.1:10809'}, which is taken from Windows Regsitry</span>

<span class="pl-c"># requests &gt; sessions.py</span>
<span class="pl-k">def</span> <span class="pl-en">merge_setting</span>(<span class="pl-s1">request_setting</span>, <span class="pl-s1">session_setting</span>, <span class="pl-s1">dict_class</span><span class="pl-c1">=</span><span class="pl-v">OrderedDict</span>):
    <span class="pl-c"># this function considers the first argument as setting (eg proxies) within request; however, with the study above,</span>
    <span class="pl-c"># it could be a setting from system registry. My take is that it is of the lower priority than session setting, which is lower</span>
    <span class="pl-c"># request setting.</span></pre></div>
<h2 dir="auto">Reproduction Steps</h2>
<p dir="auto">Refer to the post above.</p>
<h2 dir="auto">System Information</h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="$ python -m requests.help"><pre class="notranslate"><code class="notranslate">$ python -m requests.help
</code></pre></div>
<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="{
  &quot;chardet&quot;: {
    &quot;version&quot;: null
  },
  &quot;charset_normalizer&quot;: {
    &quot;version&quot;: &quot;2.0.8&quot;
  },
  &quot;cryptography&quot;: {
    &quot;version&quot;: &quot;&quot;
  },
  &quot;idna&quot;: {
    &quot;version&quot;: &quot;3.3&quot;
  },
  &quot;implementation&quot;: {
    &quot;name&quot;: &quot;CPython&quot;,
    &quot;version&quot;: &quot;3.9.7&quot;
  },
  &quot;platform&quot;: {
    &quot;release&quot;: &quot;10&quot;,
    &quot;system&quot;: &quot;Windows&quot;
  },
  &quot;pyOpenSSL&quot;: {
    &quot;openssl_version&quot;: &quot;&quot;,
    &quot;version&quot;: null
  },
  &quot;requests&quot;: {
    &quot;version&quot;: &quot;2.27.1&quot;
  },
  &quot;system_ssl&quot;: {
    &quot;version&quot;: &quot;101010cf&quot;
  },
  &quot;urllib3&quot;: {
    &quot;version&quot;: &quot;1.26.7&quot;
  },
  &quot;using_charset_normalizer&quot;: true,
  &quot;using_pyopenssl&quot;: false
}"><pre class="notranslate">{
  <span class="pl-ent">"chardet"</span>: {
    <span class="pl-ent">"version"</span>: <span class="pl-c1">null</span>
  },
  <span class="pl-ent">"charset_normalizer"</span>: {
    <span class="pl-ent">"version"</span>: <span class="pl-s"><span class="pl-pds">"</span>2.0.8<span class="pl-pds">"</span></span>
  },
  <span class="pl-ent">"cryptography"</span>: {
    <span class="pl-ent">"version"</span>: <span class="pl-s"><span class="pl-pds">"</span><span class="pl-pds">"</span></span>
  },
  <span class="pl-ent">"idna"</span>: {
    <span class="pl-ent">"version"</span>: <span class="pl-s"><span class="pl-pds">"</span>3.3<span class="pl-pds">"</span></span>
  },
  <span class="pl-ent">"implementation"</span>: {
    <span class="pl-ent">"name"</span>: <span class="pl-s"><span class="pl-pds">"</span>CPython<span class="pl-pds">"</span></span>,
    <span class="pl-ent">"version"</span>: <span class="pl-s"><span class="pl-pds">"</span>3.9.7<span class="pl-pds">"</span></span>
  },
  <span class="pl-ent">"platform"</span>: {
    <span class="pl-ent">"release"</span>: <span class="pl-s"><span class="pl-pds">"</span>10<span class="pl-pds">"</span></span>,
    <span class="pl-ent">"system"</span>: <span class="pl-s"><span class="pl-pds">"</span>Windows<span class="pl-pds">"</span></span>
  },
  <span class="pl-ent">"pyOpenSSL"</span>: {
    <span class="pl-ent">"openssl_version"</span>: <span class="pl-s"><span class="pl-pds">"</span><span class="pl-pds">"</span></span>,
    <span class="pl-ent">"version"</span>: <span class="pl-c1">null</span>
  },
  <span class="pl-ent">"requests"</span>: {
    <span class="pl-ent">"version"</span>: <span class="pl-s"><span class="pl-pds">"</span>2.27.1<span class="pl-pds">"</span></span>
  },
  <span class="pl-ent">"system_ssl"</span>: {
    <span class="pl-ent">"version"</span>: <span class="pl-s"><span class="pl-pds">"</span>101010cf<span class="pl-pds">"</span></span>
  },
  <span class="pl-ent">"urllib3"</span>: {
    <span class="pl-ent">"version"</span>: <span class="pl-s"><span class="pl-pds">"</span>1.26.7<span class="pl-pds">"</span></span>
  },
  <span class="pl-ent">"using_charset_normalizer"</span>: <span class="pl-c1">true</span>,
  <span class="pl-ent">"using_pyopenssl"</span>: <span class="pl-c1">false</span>
}</pre></div>
<p dir="auto">See <a href="https://iscinumpy.dev/post/bound-version-constraints/" rel="nofollow">https://iscinumpy.dev/post/bound-version-constraints/</a> as for why this is a problem.<br>
This is a source of byzantine issues such as <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1527502457" data-permission-text="Title is private" data-url="https://github.com/nexB/scancode-toolkit/issues/3195" data-hovercard-type="issue" data-hovercard-url="/nexB/scancode-toolkit/issues/3195/hovercard" href="https://github.com/nexB/scancode-toolkit/issues/3195">nexB/scancode-toolkit#3195</a></p>