<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: MinPin Proxy</title>
    <description>The latest articles on DEV Community by MinPin Proxy (@minpin_proxy).</description>
    <link>https://dev.to/minpin_proxy</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4241282%2F7f2d8c3e-147c-48c8-a56e-2c92a48175b3.png</url>
      <title>DEV Community: MinPin Proxy</title>
      <link>https://dev.to/minpin_proxy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/minpin_proxy"/>
    <language>en</language>
    <item>
      <title>Your script's HTTPS calls don't show up in your debugging proxy. Here's why, per runtime.</title>
      <dc:creator>MinPin Proxy</dc:creator>
      <pubDate>Thu, 12 Nov 2026 14:25:38 +0000</pubDate>
      <link>https://dev.to/minpin_proxy/your-scripts-https-calls-dont-show-up-in-your-debugging-proxy-heres-why-per-runtime-51h8</link>
      <guid>https://dev.to/minpin_proxy/your-scripts-https-calls-dont-show-up-in-your-debugging-proxy-heres-why-per-runtime-51h8</guid>
      <description>&lt;p&gt;You start a debugging proxy, your browser and your iOS Simulator traffic show up fine, and then you run a Node script or a Python job and... nothing. Or you get &lt;code&gt;UNABLE_TO_VERIFY_LEAF_SIGNATURE&lt;/code&gt; / &lt;code&gt;CERTIFICATE_VERIFY_FAILED&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On macOS the proxy sets the &lt;em&gt;system&lt;/em&gt; proxy, and apps built on Apple's networking follow it. Most things you launch from a terminal don't. A request only shows up in a proxy when the program:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;sends it to the proxy, and&lt;/li&gt;
&lt;li&gt;trusts the proxy's certificate authority.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every runtime has its own switch for both. Examples below assume a proxy on &lt;code&gt;127.0.0.1:8080&lt;/code&gt; that serves its CA as a PEM file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 0: one bundle, not just the proxy's CA
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cat /etc/ssl/cert.pem ~/proxy-ca.pem &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/proxy-bundle.pem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This one bit me. &lt;code&gt;curl --cacert&lt;/code&gt; and Python's &lt;code&gt;REQUESTS_CA_BUNDLE&lt;/code&gt; &lt;em&gt;replace&lt;/em&gt; the trusted list. If you point them at the proxy CA alone, every host the proxy is only tunnelling (not decrypting) now fails verification, because those hosts present their real certificate. A bundle of the normal roots plus the proxy CA works for both.&lt;/p&gt;

&lt;h2&gt;
  
  
  curl
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl -x http://127.0.0.1:8080 --cacert ~/proxy-bundle.pem https://api.example.com/v1/me
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the environment, curl reads &lt;code&gt;https_proxy&lt;/code&gt;, but for plain HTTP it only reads &lt;strong&gt;lowercase&lt;/strong&gt; &lt;code&gt;http_proxy&lt;/code&gt;. That's deliberate (CGI &lt;code&gt;HTTP_PROXY&lt;/code&gt; header injection). Export both spellings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="kd"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;http_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://127.0.0.1:8080 &lt;span class="nv"&gt;https_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://127.0.0.1:8080
&lt;span class="kd"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;HTTP_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$http_proxy&lt;/span&gt; &lt;span class="nv"&gt;HTTPS_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$https_proxy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And please don't reach for &lt;code&gt;-k&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Node.js
&lt;/h2&gt;

&lt;p&gt;Node's built-in &lt;code&gt;http&lt;/code&gt;, &lt;code&gt;https&lt;/code&gt; and &lt;code&gt;fetch&lt;/code&gt; ignore &lt;code&gt;HTTPS_PROXY&lt;/code&gt;. Node 24+ lets you opt in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="kd"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;HTTPS_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://127.0.0.1:8080 &lt;span class="nv"&gt;HTTP_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://127.0.0.1:8080
&lt;span class="kd"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;NODE_USE_ENV_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;span class="kd"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;NODE_EXTRA_CA_CERTS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;~/proxy-ca.pem
node server.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;NODE_EXTRA_CA_CERTS&lt;/code&gt; &lt;em&gt;adds&lt;/em&gt; to Node's roots, so the CA file alone is right here (no bundle needed). It's read once at startup.&lt;/p&gt;

&lt;p&gt;On older Node, use undici in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;ProxyAgent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setGlobalDispatcher&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'undici'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;setGlobalDispatcher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ProxyAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'http://127.0.0.1:8080'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;axios: pass an &lt;code&gt;https-proxy-agent&lt;/code&gt; as &lt;code&gt;httpsAgent&lt;/code&gt; &lt;strong&gt;and&lt;/strong&gt; &lt;code&gt;proxy: false&lt;/code&gt;, or axios layers its own proxy handling on top.&lt;/p&gt;

&lt;p&gt;Next.js: export the variables before &lt;code&gt;next dev&lt;/code&gt;. That covers server-side fetches only; browser calls follow the browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Python
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;requests&lt;/code&gt; and &lt;code&gt;urllib&lt;/code&gt; read the proxy variables already. Point them at the bundle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="kd"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;HTTPS_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://127.0.0.1:8080 &lt;span class="nv"&gt;HTTP_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://127.0.0.1:8080
&lt;span class="kd"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;REQUESTS_CA_BUNDLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;~/proxy-bundle.pem   &lt;span class="c"&gt;# requests&lt;/span&gt;
&lt;span class="kd"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;SSL_CERT_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;~/proxy-bundle.pem        &lt;span class="c"&gt;# ssl / urllib&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not &lt;code&gt;verify=False&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go
&lt;/h2&gt;

&lt;p&gt;The easy one. The default client reads &lt;code&gt;HTTPS_PROXY&lt;/code&gt;, and on macOS Go verifies against the system keychain. Trust the proxy CA in Keychain Access, then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;HTTPS_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://127.0.0.1:8080 go run .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you build your own &lt;code&gt;http.Transport&lt;/code&gt;, set &lt;code&gt;Proxy: http.ProxyFromEnvironment&lt;/code&gt; or the variable is ignored.&lt;/p&gt;

&lt;h2&gt;
  
  
  Still nothing?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Calling localhost?&lt;/strong&gt; Most clients skip the proxy for &lt;code&gt;localhost&lt;/code&gt;/&lt;code&gt;127.0.0.1&lt;/code&gt;, and &lt;code&gt;NO_PROXY&lt;/code&gt; often lists them. Use the Mac's hostname or LAN IP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stale &lt;code&gt;NO_PROXY&lt;/code&gt;?&lt;/strong&gt; &lt;code&gt;env | grep -i proxy&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You see a CONNECT but no body?&lt;/strong&gt; The proxy reached the host but isn't decrypting it. Turn on SSL decoding for that host in your proxy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The program has no proxy setting at all?&lt;/strong&gt; A normal HTTP proxy can't see it. Nothing to do short of a transparent/VPN-style setup.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Disclosure: I build MinPin, a macOS debugging proxy. Its Tools menu has an "Open Terminal with Proxy" item that exports the variables above, but everything here works with any proxy.&lt;/p&gt;

</description>
      <category>node</category>
      <category>python</category>
      <category>debugging</category>
      <category>macos</category>
    </item>
  </channel>
</rss>
