Can I call the OpenAI API directly from my React app?
No, not with your own OpenAI key. Anything in your frontend bundle is readable by every visitor. Here's how to move the call to a server or edge function.
Check your live site
Run the free ShipLatch scan on your own site without leaving this page.
Uses 1 of your 3 free scans today; a site scanned in the last 24 hours answers from that scan. Passive and read-only: we only look at what any browser can see. Only check sites you own or may test.
No, not with your own OpenAI API key. Any key your React, Vite or Next.js frontend sends to OpenAI has to be in the JavaScript every visitor downloads, and OpenAI's own guidance is to never deploy your key in a browser and to route requests through your own backend instead (OpenAI Help Center).
That is why OpenAI's official JavaScript library refuses to run in a browser unless you set dangerouslyAllowBrowser: true. Its README says that option "exposes your secret API credentials in the client-side code" (openai-node README).
Not sure your key is already in your live JavaScript? Scan free, no signup.
Why it's a problem
- Anyone can copy the key. OpenAI says a key exposed in a browser lets other people "make requests on your behalf", which can lead to unexpected charges or compromise of account data (OpenAI Help Center).
- A
.envfile doesn't hide it. In Vite, any variable starting withVITE_is bundled into your client code at build time, and Vite's docs say these variables should not contain API keys (Vite docs). If your AI builder named itVITE_OPENAI_API_KEY, it is public.
When the README says browser use can be OK
The openai-node README lists narrow cases: internal tools used only by trusted people, keys with very limited scope, or short-lived keys for development that aren't used in production (openai-node README). A public app that uses your own paid key is none of these. Apps where each user pastes in their own key ("bring your own key") are a different case: the key in the browser belongs to that user.
How to fix it (plain steps)
- Create a server-side function that calls OpenAI. If you're on Supabase, an Edge Function works: Supabase's docs show storing a secret with
supabase secrets set(or the dashboard) and reading it in the function withDeno.env.get(...)(Supabase docs). - Put the key there, not in the frontend. Use a name with no
VITE_/NEXT_PUBLIC_prefix. Supabase also says to add every.envfile to.gitignore, because a committed.envexposes every secret in it (Supabase docs). - Have the browser call your function, not
api.openai.com. Check the user is signed in inside the function so strangers can't use it as a free proxy. - Remove
dangerouslyAllowBrowser: trueand the old key from your client code, then redeploy. - If the key was ever live in your site, rotate it. OpenAI says to rotate immediately from the API Keys page if you think a key leaked (OpenAI Help Center). Removing it from the code does not make the old key safe.
- Set a spend limit. OpenAI recommends monthly spend limits with hard enforcement to cap the damage from a leaked key, and notes alerts alone don't stop traffic (OpenAI Help Center).
Move every OpenAI API call out of the frontend. Create a server-side (or Supabase Edge) function that reads OPENAI_API_KEY from server secrets, checks the user is signed in, and calls OpenAI. The browser should only call my function. Remove dangerouslyAllowBrowser and any VITE_/NEXT_PUBLIC_ OpenAI key. List every file you changed.
FAQ
My key is in .env, not in my code. Is that enough?
Only if the variable has no public prefix. Vite bundles every VITE_ variable into client code (Vite docs).
I only use the key in a "hidden" admin page. Is that OK?
No. The JavaScript for that page is still downloadable by anyone who finds it. Keep the key on a server.
What does dangerouslyAllowBrowser actually do?
It turns off the library's browser safety block. The README explains the risk: anyone with access to the browser can inspect and extract the credentials (openai-node README).
I moved the key. Do I still need to rotate it?
Yes, if it was ever deployed. A re-scan can prove the key is gone from your live site, but it can't prove the old key was revoked. Rotate it yourself in the OpenAI dashboard (OpenAI Help Center).
Does this apply to Anthropic, Groq and other AI keys?
Treat any secret AI provider key the same way: keep it on a server, never in the bundle.
Check yours
ShipLatch's free scan looks for OpenAI and other AI provider keys in your page, JavaScript and public source maps, and notes SDK code that sets dangerouslyAllowBrowser to true. Passive and read-only, no signup. Scan your app free at shiplatch.com
Related: Leaked OpenAI API key: what to do · Are VITE_ variables public?
Sources (all fetched 2026-10-28)
- OpenAI Help Center, Best practices for API key safety: https://help.openai.com/en/articles/5112595-best-practices-for-api-key-safety
- openai-node README: https://github.com/openai/openai-node#requirements
- Vite, Env Variables and Modes: https://vite.dev/guide/env-and-mode
- Supabase, Edge Function secrets: https://supabase.com/docs/guides/functions/secrets
Want the whole pre-launch process in one place? Get App Security for Vibe Coders, our $9 PDF playbook. See what's inside.