"It worked on my MacBook at home, but the moment I tried it on the company-issued Windows laptop on Monday morning, the script just hung." That was me, and it took an entire day to track down the actual cause. The error messages did not help — sometimes it was SSLError: SSL: CERTIFICATE_VERIFY_FAILED, sometimes a silent timeout with no output at all. When the symptoms shift around like that, it is hard to know where to even start digging.
This article walks through how to isolate the layer where Gemini API calls are actually breaking when you are behind a corporate proxy or some other unusual network setup, and how to get back to a working state with concrete Python and Node.js code. Most of these issues are network plumbing rather than Gemini-specific, but the SDKs have a few quirks worth knowing about.
The Three Layers to Check First
When Gemini API calls fail from a managed network, the cause almost always lives in one of three layers: (1) DNS and basic reachability, (2) the HTTP proxy, or (3) TLS certificate validation. Before adding logging to your Python application, the fastest path is to drop down to curl and confirm what the raw HTTP layer is actually seeing. Application-level stack traces tend to obscure the underlying network state, so I prefer to confirm the network is healthy before chasing SDK behavior.
# (1) DNS resolution and basic reachability
curl -v https://generativelanguage.googleapis.com/v1beta/models -m 10
# (2) Reachability via the corporate proxy
curl -v -x http://proxy.example.com:8080 https://generativelanguage.googleapis.com/v1beta/models -m 10
# (3) Inspect the certificate chain you are actually receiving
openssl s_client -connect generativelanguage.googleapis.com:443 -showcerts < /dev/null 2>&1 | head -30If step (1) returns Could not resolve host, the problem is DNS. Connection timed out points at a firewall. SSL certificate problem means a certificate trust issue. Narrowing down which layer is broken at the curl level is faster than chasing application-side stack traces. Save the output of step (3) somewhere — if the issuer field is your company's internal CA rather than Google Trust Services, that single line of evidence tells you you are dealing with a TLS-terminating proxy.
The HTTP_PROXY / HTTPS_PROXY Pitfalls
Almost every corporate connection goes through a proxy, and SDKs like google-genai will pick up the standard proxy environment variables automatically. There are a handful of subtle places this goes wrong.
First, the value of HTTPS_PROXY should still start with http://, not https://. The connection to the proxy itself is plain HTTP, and the SSL tunnel to the destination is established through CONNECT. Setting https://proxy.example.com:8080 and wondering why nothing works is a surprisingly common one-day rabbit hole.
Second, set both upper- and lower-case versions of the variable. Several Linux libraries only check http_proxy (lowercase). The duplication looks redundant, but it is the most reliable way to make every library in your dependency tree happy.
export HTTP_PROXY="http://user:pass@proxy.example.com:8080"
export HTTPS_PROXY="http://user:pass@proxy.example.com:8080"
export http_proxy="$HTTP_PROXY"
export https_proxy="$HTTPS_PROXY"
export NO_PROXY="localhost,127.0.0.1,.internal.corp"Third, URL-encode special characters in passwords. Bare @ or # in a credential will silently break the parser, and the failure surfaces as a generic auth error rather than a parsing error. In Python, urllib.parse.quote(password, safe="") is the safe way to do this.
Make sure NO_PROXY covers your internal hosts as well, otherwise calls to local APIs will needlessly attempt to exit through the proxy. The default behavior is to send everything through the proxy, including localhost, which can cause local development servers to mysteriously timeout when you also run them on the same machine.
SSL Certificate Errors — Trust the CA, Don't Disable Verification
The SSL error is the layer most likely to send you down the wrong path. Many corporate networks run a TLS-terminating proxy that re-encrypts traffic on the fly. Unless that proxy's self-signed CA is in your OS trust store, you will get CERTIFICATE_VERIFY_FAILED from any HTTPS client.
Please do not "fix" this by setting verify=False. It looks like it works because the request now succeeds, but you have just disabled MITM protection everywhere — including outside the corporate network when the same code runs on a laptop in a coffee shop. This is exactly the kind of shortcut that ships to production by accident and turns into a security incident later.
The right fix is to add the corporate CA certificate (your IT department should have a .pem or .crt file you can ask for) to the trust bundle that Python or Node.js uses. The most portable approach is via environment variables.
# Trust the corporate CA at the process level
export REQUESTS_CA_BUNDLE=/path/to/corporate-ca.pem
export SSL_CERT_FILE=/path/to/corporate-ca.pem
# If the app uses certifi, you can append the CA to certifi's bundle directly
python -c "import certifi; print(certifi.where())"
# Append the contents of corporate-ca.pem to that pathFor Node.js, setting NODE_EXTRA_CA_CERTS=/path/to/corporate-ca.pem is enough. Both fetch and https.request will pick it up, and the official @google/genai SDK works without any additional configuration. On Windows, also make sure the same CA is installed in the system Certificate Store, otherwise tools like winget and pip will continue to fail even after the application starts working.
Working Code — Routing google-genai Through the Proxy
Python's google-genai SDK uses httpx under the hood, so it picks up the proxy environment variables automatically. If you want to specify the proxy directly in code (for example, to switch between multiple egress paths in the same process), you can inject a custom HTTP client.
# pip install google-genai httpx
import os
import httpx
from google import genai
# Explicit proxy with authentication, set in code
proxy_url = "http://user:pass@proxy.example.com:8080"
http_client = httpx.Client(
proxy=proxy_url,
verify=os.environ.get("REQUESTS_CA_BUNDLE", True),
timeout=30.0,
)
client = genai.Client(
api_key=os.environ["GEMINI_API_KEY"],
http_options={"client_args": {"transport": httpx.HTTPTransport(proxy=proxy_url)}},
)
response = client.models.generate_content(
model="gemini-2.5-flash",
contents="Connection test from the corporate network.",
)
print(response.text)
# Expected output: a short confirmation response from GeminiFor Node.js, the cleanest solution is to install a global dispatcher from undici. The @google/genai SDK is fetch-based, so it inherits the dispatcher transparently.
// npm install @google/genai undici
import { GoogleGenAI } from "@google/genai";
import { ProxyAgent, setGlobalDispatcher } from "undici";
setGlobalDispatcher(new ProxyAgent("http://user:pass@proxy.example.com:8080"));
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
const result = await ai.models.generateContent({
model: "gemini-2.5-flash",
contents: "Connection test from the corporate network.",
});
console.log(result.text);
// Expected output: a short response string from GeminiAdd the corporate CA via NODE_EXTRA_CA_CERTS and the SDK code stays focused on the proxy concern alone. If you also use streaming responses, watch out for proxies that buffer the entire body before forwarding — chunked transfer encoding gets defeated, and what should feel like a typewriter response arrives all at once after a long wait. That is a proxy configuration issue, not a Gemini issue, and it is usually fixable by enabling streaming pass-through on the proxy.
When None of the Above Works
If you have walked through all three layers and the requests still fail, the cause is usually somewhere a little more obscure. Here are the issues I have hit, roughly in order of frequency.
The most common one is firewall rules pinned to IP addresses rather than hostnames. Google's frontends behind generativelanguage.googleapis.com rotate their IPs, so any IP-pinned allowlist will eventually fall behind. Ask the network team to allowlist by hostname, or by Google's ASN, instead. The same applies to aiplatform.googleapis.com if you are using Vertex AI.
Next is expired session tokens on an authenticated proxy. If your browser passes through transparently with SSO but a CLI request returns 407 Proxy Authentication Required, that is almost always the cause. For NTLM-based proxies, an authentication bridge such as cntlm running on localhost is a reliable workaround that lets command-line tools speak basic auth to localhost while the bridge speaks NTLM upstream.
A subtle one: pip install itself often cannot reach PyPI through the proxy. Either pass pip --proxy http://... explicitly, or write the proxy into ~/.pip/pip.conf under [global]. If the SDK never installs in the first place, fixing your application code obviously will not help. The same applies to npm — set npm config set proxy and npm config set https-proxy separately.
One more: the Live API uses WebSockets, not plain HTTPS, and many corporate proxies either do not support CONNECT for WebSocket upgrades or strip the upgrade header. If chat and generation work but live.connect() fails, suspect this layer specifically.
For related troubleshooting, Authentication errors with Gemini API, by category and Diagnosing recurring 503 Service Unavailable errors cover the cases that look like network problems but turn out to be authentication or upstream issues.
Corporate-network problems usually come in layers, and a clean root cause is rare on the first try. But if you walk through curl → environment variables → certificates → SDK in that order, you can almost always isolate the failing layer within a few hours. I hope today's debugging session ends a little sooner because of this.