Skip to main content

API keys in your front end: safe or not

Some keys are meant to be public and some can empty your account. How to tell them apart, and what to do when one leaks.

6 minute read

Everything in your front end is public

Your front end is the part of your app that runs in the visitor's browser: the page and its JavaScript. To run it, the browser has to download all of it, so anything inside it can be read by anyone, with nothing more than the browser's own tools. Compressing or scrambling the code does not change that.

So the question for every key in your app is not "is it hidden?" but "what could someone do with it?"

Two kinds of key

Public keys identify your app to a service. They are made to be seen, and the service protects you in other ways: by checking which website the request comes from, by rules you set, or by only allowing harmless actions.

Secret keys prove that a request comes from you. Whoever holds one can act as you: spend your money, read your customers' data, or run up a bill. They belong on a server, never in the browser.

The same service often gives you one of each, and they can look alike. Read the service's documentation for which is which, and when in doubt, treat a key as secret.

Common keys, one by one

  • Stripe. Publishable keys (pk_live_, pk_test_) are made for the browser. Secret keys (sk_live_) and restricted keys (rk_live_) are not: with a secret key someone can read payments and customers and issue refunds.
  • Supabase. The anon or publishable key is public by design, and your safety depends on row level security. The service role or secret key bypasses every rule and must stay on your server.
  • Firebase. The apiKey in a Firebase web config identifies your project rather than granting access; what protects your data is your Firebase security rules. Make sure those rules do not leave your database or storage open. A survey reports a Firebase config it finds so you can check them.
  • Google Maps and similar browser APIs. These keys are used in the browser, so the protection is a restriction you set in the provider's console, such as the websites allowed to use the key. Without one, someone can use your key on their site and you pay.
  • OpenAI, Anthropic and other AI providers. These are secret keys. Anyone holding one can run up charges on your account. Call the AI from a server-side function and keep the key there.

The variable names that publish a key

Most front-end build tools only put a setting into the browser code if its name starts with a special prefix, such as VITE_ for Vite, NEXT_PUBLIC_ for Next.js or REACT_APP_ for Create React App. That prefix is the tool's way of saying "this value will be public".

So a setting named something like VITE_OPENAI_API_KEY or NEXT_PUBLIC_STRIPE_SECRET is a warning sign: the name says it is secret, and the prefix says it is published. A survey lists the setting names it can see in your code and flags the ones that sound secret.

If a secret key has leaked

Assume it has been copied, even if nothing has happened yet. Automated tools look for leaked keys all the time.

  • Create a new key in the provider's dashboard.
  • Move the code that needs it to the server side, and put the new key there.
  • Revoke the old key, so the copy that leaked stops working.
  • Check the provider's logs or billing for anything you did not do.

Removing the key from your code without replacing it is not enough: the old version of your page, and any copy someone made, still has it. A free survey checks your public pages for secret keys, and shows only the first and last four characters of anything it finds.

Check your own app

A free survey looks for the problems a visitor's browser can see, with nothing to install and no account needed. See a full example in the sample report first if you like.