The Gemini API reads its credentials from two environment variables — GEMINI_API_KEY and GOOGLE_API_KEY — and if you set both, the unified google-genai SDK silently picks GOOGLE_API_KEY and logs a warning you will probably never read. Get this wrong and your code authenticates with the key you did not mean to ship, or one env var (GOOGLE_GENAI_USE_VERTEXAI=true) flips the entire auth model from a single key to Google Cloud project credentials. The old google-generativeai and @google/generative-ai packages hit permanent end-of-life on November 30, 2025; in 2026 the only supported path is the unified SDK, and its environment-variable behavior is the part most code-gen models still get wrong.
TL;DR
- Set exactly one key var. The SDK auto-reads
GEMINI_API_KEYorGOOGLE_API_KEY; if both are set,GOOGLE_API_KEYwins. PreferGEMINI_API_KEYto keep intent explicit. - The precedence warning fires even when you pass the key explicitly —
genai.Client(api_key=...)still inspects the env vars (open bug python-genai#1760). - One variable swaps the backend.
GOOGLE_GENAI_USE_VERTEXAI=truemoves you off the API key and ontoGOOGLE_CLOUD_PROJECT+GOOGLE_CLOUD_LOCATION+ Application Default Credentials. - Legacy SDKs are dead.
google-generativeai/@google/generative-aireached end-of-life 2025-11-30. Migrate togoogle-genai/@google/genai. - Never ship the key client-side. Google's own docs say keys in browser or mobile code can be extracted — keep it server-side.
Which environment variables does the Gemini API actually read?
The unified Google Gen AI SDK (Python google-genai, JS/TS @google/genai, Go, Java) resolves configuration from a small set of environment variables. Which ones matter depends entirely on whether you are calling the Gemini Developer API (an AI Studio key) or the Gemini API on Vertex AI (a Google Cloud project).
| Variable | Backend | What it does |
|---|---|---|
| GEMINI_API_KEY | Developer API | Primary key var. Auto-read by the SDK if no key is passed in code. |
| GOOGLE_API_KEY | Developer API / Vertex express | Also auto-read. Takes precedence over GEMINI_API_KEY if both are set. |
| GOOGLE_GENAI_USE_VERTEXAI | Vertex AI | Set to true/1 to switch the SDK backend to Vertex AI. |
| GOOGLE_CLOUD_PROJECT | Vertex AI | GCP project ID. Required when using Vertex. |
| GOOGLE_CLOUD_LOCATION | Vertex AI | Region, e.g. us-central1 or global. |
| GOOGLE_APPLICATION_CREDENTIALS | Vertex AI | Path to a service-account JSON key for Application Default Credentials. |
| GOOGLE_GENAI_USE_ENTERPRISE | Enterprise | 2026 rebrand path: Gemini Enterprise Agent Platform (previously Vertex AI API). |
That last row is new. Google is rebranding the Vertex AI API surface to the Gemini Enterprise Agent Platform, and the SDK now exposes GOOGLE_GENAI_USE_ENTERPRISE alongside the older Vertex flag. Set both with conflicting values and the Python client raises a ValueError rather than guessing.
GEMINI_API_KEY vs GOOGLE_API_KEY — which one wins?
Both are auto-detected. The official key documentation states it verbatim: “It's recommended that you set only one of those variables, but if both are set, GOOGLE_API_KEY takes precedence.” This is consistent across the Python, JS/TS, Go, and Java SDKs. The trap: a stray GOOGLE_API_KEY in your shell profile from an unrelated Google Cloud tool will quietly override the GEMINI_API_KEY your project actually intends to use, and the only signal is a log line.
Both GOOGLE_API_KEY and GEMINI_API_KEY are set. Using GOOGLE_API_KEY.There is a sharper edge here. Even when you pass the key explicitly — genai.Client(api_key="...") — the Python SDK still runs the environment-variable resolution and emits that same warning. It is tracked as open issue googleapis/python-genai#1760. If you see the warning in logs for a service that hard-codes its key from a secret manager, this is why — it is noise, not a misconfiguration. The opinionated fix: standardize on GEMINI_API_KEY everywhere and never set GOOGLE_API_KEY for Gemini work, so the two can never collide.
How do you set GEMINI_API_KEY for the SDK?
Export the variable, then construct the client with no arguments. The SDK reads the environment for you — you do not call configure() anymore (that was the dead legacy API).
# Gemini Developer API — one variable, that is it
export GEMINI_API_KEY="your-aistudio-key"# Python — google-genai (>= 1.0, GA since May 2025)
from google import genai
client = genai.Client() # picks up GEMINI_API_KEY from the environment
resp = client.models.generate_content(
model="gemini-2.5-flash",
contents="One sentence on why env vars beat hard-coded keys.",
)
print(resp.text)// Node.js — @google/genai
import { GoogleGenAI } from '@google/genai';
// The Node SDK auto-reads GEMINI_API_KEY / GOOGLE_API_KEY for the Developer API.
// In the browser or with the REST API you MUST pass the key explicitly.
const ai = new GoogleGenAI({});
const resp = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: 'One sentence on why env vars beat hard-coded keys.',
});
console.log(resp.text);For local development, keep the key in a .env file rather than your shell profile, and load it with the runtime's own loader. In Python use python-dotenv (see the Python env variables guide); in Node use the built-in --env-file flag (see the Node.js env variables guide). The exact quoting and multi-line rules for that file are covered in the .env guide.
How do you switch to Vertex AI with one environment variable?
GOOGLE_GENAI_USE_VERTEXAI=true changes the SDK backend from the Gemini Developer API to the Gemini API on Vertex AI. This is not a tweak — it changes the entire authentication model. The API key is no longer used; the SDK authenticates with Application Default Credentials and needs a project and a location instead.
# Vertex AI — no API key; uses Application Default Credentials
export GOOGLE_GENAI_USE_VERTEXAI=true
export GOOGLE_CLOUD_PROJECT="your-project-id"
export GOOGLE_CLOUD_LOCATION="us-central1"
# Provide ADC: either a logged-in gcloud session...
gcloud auth application-default login
# ...or a service-account key file
export GOOGLE_APPLICATION_CREDENTIALS="/secrets/sa.json"from google import genai
# Reads GOOGLE_GENAI_USE_VERTEXAI / project / location from the environment.
# Or be explicit and ignore the env entirely:
client = genai.Client(vertexai=True, project="your-project-id", location="us-central1")Explicit constructor arguments always override the environment, which is the right call for production: pin the backend in code so a leaked GOOGLE_GENAI_USE_VERTEXAI in a shared CI runner cannot reroute traffic. The 2026 wrinkle: the Vertex API is being rebranded to the Gemini Enterprise Agent Platform, with a parallel GOOGLE_GENAI_USE_ENTERPRISE=true / enterprise=True path. Setting enterprise and vertexai to conflicting values raises a ValueError instead of silently picking one.
What changed when the legacy SDKs reached end-of-life?
The old packages — google-generativeai (Python) and @google/generative-ai (JS) — were deprecated as of November 30, 2025 and no longer receive even critical bug fixes. They never exposed Live API or Veo. The unified google-genai SDK has been GA across Python, JS/TS, Go, and Java since May 2025. If you are reading a tutorial that calls genai.configure(api_key=...) followed by genai.GenerativeModel(...), that tutorial targets the dead SDK.
| Legacy (EOL 2025-11-30) | Unified (use this in 2026) |
|---|---|
| pip install google-generativeai | pip install google-genai |
| npm i @google/generative-ai | npm i @google/genai |
| genai.configure(api_key=...) | genai.Client() (reads the env) |
Both SDK docs ship a blunt warning worth repeating: code-generation models are often unaware of recent SDK changes and will confidently emit legacy google-generativeai code. Paste Google's codegen instructions into your AI tool, or pin the model to the unified API explicitly. This is the single most common Gemini integration bug in 2026, and it is caused by stale training data, not by you.
How does the Gemini CLI handle these env vars?
The Gemini CLI reuses the same variables but adds its own resolution rules worth knowing:
- It loads the first
.gemini/.envit finds searching up from the current directory, then falls back to~/.gemini/.env. - For project ID it checks
GOOGLE_CLOUD_PROJECTfirst, then falls back toGOOGLE_CLOUD_PROJECT_ID. - To switch from API-key auth to OAuth login you must explicitly
unset GOOGLE_API_KEY GEMINI_API_KEY— a lingering key var keeps the CLI on key-based auth. - Vertex AI “express mode” accepts a
GOOGLE_API_KEY; if you also set project and location, project + location win.
That .gemini/.env discovery is a quiet footgun: a forgotten key in a parent directory's .gemini/.env can shadow the one in your repo. Keep project keys in the project's own .gemini/.env and add it to .gitignore.
How do you keep the key out of client code and git?
Google's own guidance is explicit: “Never expose API keys on the client-side. Do not use your API key directly in web or mobile apps in production. Keys in client-side code (including our JavaScript/TypeScript libraries and REST calls) can be extracted.” A Gemini key in a shipped React bundle is a public key — assume it is scraped within hours and bill-capped or abused. Route browser traffic through a server endpoint that holds GEMINI_API_KEY server-side.
# .gitignore — never commit the real values
.env
.env.local
.gemini/.env
# Commit a placeholder so teammates know what is required
# .env.example
GEMINI_API_KEY=your-key-hereThe same rules that apply to any secret apply here — short-lived where possible, never in version control, scoped per environment. The environment variable security guide covers leak detection and rotation, and sharing .env files securely covers getting the key to teammates without Slack-pasting it. For where the Gemini key sits among the other LLM provider APIs, see LLM APIs for developers.
When should you not rely on these environment variables?
- Browser or REST calls — the SDK does not auto-read the env in the browser, and it should not. Pass a short-lived token from your backend instead of an env-injected key.
- Multi-tenant or per-request keys — a single process-wide env var cannot represent per-customer keys. Construct a client per key in code and skip the env entirely.
- Production backend selection — do not let
GOOGLE_GENAI_USE_VERTEXAIdecide your backend implicitly. Pinvertexai=Truein code so an environment leak cannot reroute traffic. - When GOOGLE_API_KEY already exists for something else — if your environment uses
GOOGLE_API_KEYfor Maps or another Google service, do not reuse it; the precedence rule will silently feed it to Gemini.
References
- Using Gemini API keys — official source for the GEMINI_API_KEY / GOOGLE_API_KEY precedence rule and the client-side security warning.
- Google Gen AI Python SDK docs — env-var setup for both the Developer API and Vertex AI, including the exact export examples.
- Migrate to the Google GenAI SDK — the official old-to-new mapping (configure() → Client()) and the codegen caveat.
- Gemini API libraries — states the legacy libraries are deprecated as of November 30, 2025 and lists the unified package names.
- googleapis/js-genai — official TypeScript/JavaScript SDK; quickstarts for Developer API, Vertex, and Enterprise auth.
- python-genai#1760 — open issue: the env-var precedence warning fires even when api_key is passed explicitly.
- Gemini CLI authentication — the CLI's .gemini/.env discovery order and the unset-to-use-OAuth rule.
Check your .env file for syntax errors before it reaches the Gemini SDK with the env validator, or read the env variable security guide for rotation and leak detection.