Why You Shouldn’t Put Private API Keys in Your React .env File (And What to Do Instead)

Table of contents

I recently needed to use the Gemini API in a React project, and my Friend said, "Put your API key in a .env file." At first, I thought that was safe. But after looking into it, I learned something important: .env files in frontend projects DON'T actually hide your secrets. Let me explain what I found out..
1. What Is a .env File in React?
A .env
file is just a text file where you store config stuff, like:
GEMINI_API_KEY=123456abcdef
VITE_API_URL=https://api.example.com
In React (when using Vite), you can use your variables like this:
import.meta.env.VITE_API_KEY
It sounds cool because your code stays tidy, and you don't write secrets directly in your components.
But here’s the problem…
2. React Is a Frontend App = Everything Is Public
Here’s something I didn't realize at first:
React runs in the browser.
So, when you build your project:
All your files (including what’s in
.env
) get bundled into JavaScript.The browser downloads those files.
Anyone can open DevTools, check the sources, and see those "secret" keys.
So even if you do:
const apiKey = import.meta.env.VITE_GEMINI_KEY;
Anyone can:
Open DevTools
Go to the Sources/Network tab
Find your JS Bundle
See your API key 😬
If the browser can access it, the user can access it too.
3. When Is It Okay to Put API Keys in the Frontend?
Sometimes it’s totally fine because some keys are supposed to be public, like:
- Google Maps public keys
Even then, putting them in .env
is just so you can switch between different environments (dev, production, etc.), not for security.
4. When You Should NOT Put Keys in the Frontend
Private keys like:
Stripe secret keys
Database passwords
AWS Secret keys
Gemini API keys (if they're not public!)
If someone gets one of these:
They could use up your quota.
You might get a big bill.
Your API account could even get banned.
NEVER put these in frontend code, even in .env
.
5. The Right Way: Use a Backend
So, how do you keep your keys safe?
You need a backend (or serverless function) as a middleman.
Here’s what happens:
React talks to your backend.
Backend reads the real key from its own secret
.env
.Backend talks to the real API (like Gemini).
Backend sends just the results to your frontend.
The API key never leaves the server!
Now, if someone looks at your network requests, all they see is your backend endpoint, not the real key.
6. Quick Example (My Experience)
So here’s what I did at first (don’t do this 😅)
❌ Insecure: Frontend Call
const response = await fetch(
`https://gemini.googleapis.com/v1?key=${import.meta.env.VITE_GEMINI_KEY}`
);
I thought this was fine, but wow, I was wrong! Anyone can open DevTools in their browser, see your JS code, and just copy that VITE_GEMINI_KEY
. That’s really not safe at all.
✅ The Safe Way: Backend Call
Here’s what I learned that finally made it click for me.
Frontend (React) just sends stuff to the backend:
const res = await fetch("/api/gemini", {
method: "POST",
body: JSON.stringify({ prompt: "Hello Gemini" }),
});
Backend (Node.js/Express) actually talks to the Gemini API using the real key:
app.post("/api/gemini", async (req, res) => {
const prompt = req.body.prompt;
const result = await fetch("https://gemini.googleapis.com/v1", {
headers: {
Authorization: `Bearer ${process.env.GEMINI_API_KEY}`,
},
body: JSON.stringify({ prompt }),
});
const data = await result.json();
res.json(data);
});
The big point: the GEMINI_API_KEY only exists on the backend. The frontend (browser) never sees the real key. If someone checks network requests from the browser, they just see your backend endpoint, not your secret API key.
So yeah, next time you think about putting any private API key in your React .env
, just remember: it’s like hiding money under your pillow at home. Anyone living in the house (your browser) can find it easily. If you want that money to be truly safe, you have to use a real bank vault (the backend).
Hope this helps!
Subscribe to my newsletter
Read articles from Habibur Rahman directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Habibur Rahman
Habibur Rahman
Hi! I’m an aspiring Full-Stack Web Developer currently pursuing my Bachelor of Computer Applications (LPU). With a solid foundation in C++, Data Structures & Algorithms, and a growing skill set in web technologies.