Exposed API key checker

Paste your app URL. We scan your HTML and JavaScript bundles for OpenAI, Anthropic, Stripe, AWS, GitHub, Slack and Supabase secret keys, the same way an attacker with DevTools would.

Passive check: we only fetch public pages and scripts. Only scan sites you own or are authorized to test.

How keys end up in the browser

Anything your frontend can read, your visitors can read. When an AI editor wires up "call OpenAI from my app", the fastest code puts the key in a variable the browser bundle can see. Build tools make it easy to do by accident: in Vite, any variable prefixed VITE_ is inlined into the JavaScript; in Next.js it's NEXT_PUBLIC_; in Expo, EXPO_PUBLIC_. Rename OPENAI_API_KEY to VITE_OPENAI_API_KEY to "fix an undefined error" and the key ships to every visitor.

Minification does not hide it. Bots scrape public sites and GitHub for key patterns continuously, and a leaked OpenAI or Anthropic key can be drained within hours. A leaked Stripe live secret key is worse: it can issue refunds, read customer data and create charges.

What this checker looks for

  • OpenAI (sk-proj-…, sk-svcacct-…) and Anthropic (sk-ant-…) API keys
  • Stripe live secret and restricted keys (sk_live_, rk_live_). Publishable pk_live_ keys are meant to be public and aren't flagged.
  • AWS access key IDs, GitHub tokens, Slack tokens, SendGrid keys and PEM private key blocks
  • Supabase service_role JWTs (decoded, so we only flag the dangerous role)
  • Google API keys, reported as informational: they are normal in Firebase and Maps configs but should be restricted.

We fetch your page and up to 25 same-site script bundles, the same files a browser downloads. Matches are masked in the results (first 8 and last 4 characters) and we never publish key values. Expect some limits: keys fetched at runtime from an API, or loaded from third-party domains, won't be seen, and pattern matching can occasionally misfire on random strings.

Found a key? Do this in order

  1. Revoke or rotate it first. Deleting it from your code does not help; the old bundle is cached on CDNs and in scrapers' databases. Go to the provider dashboard and create a new key.
  2. Check usage and billing for unexpected calls since the key was deployed. Set spending limits where the provider supports them.
  3. Move the call server-side. Create an API route, serverless function, or Supabase Edge Function that holds the key in an environment variable without a public prefix, and have your frontend call that route instead.
  4. Protect the new route. A proxy that forwards any prompt to OpenAI for anyone is still an open wallet. Require a signed-in user and add rate limits.
  5. Purge the history. If the key was committed to a public repo, rotating it is the fix; rewriting git history is optional cleanup.
  6. Re-scan to confirm the new build is clean.

Prevent it next time

Treat public env prefixes as "this will be printed on a billboard". Keep a short list of what may be public (Supabase anon key, Firebase web config, Stripe publishable key, analytics IDs) and keep everything else server-only. Add a secret scanner like gitleaks or GitHub push protection to your repo. Before launch, run grep -rE "sk-|sk_live_|service_role" dist/ on your built output. And if you'd rather have it automated, ShipSniffer's full scan and source-code scan check your built site and your repo together.

Check everything in one scan.

Leaked keys, database exposure, headers, SEO, performance and broken links, with a copy-paste fix prompt for Cursor or Lovable on every issue. Free to run.

Run the full free scan →

FAQ

Can people really see API keys in my JavaScript?

Yes. Every JavaScript file your site loads is downloadable by anyone, and minification does not hide string values. Open DevTools, go to Sources, and search for "sk-" to see for yourself.

Is my Stripe publishable key a leak?

No. Keys starting with pk_live_ or pk_test_ are designed to be in the browser. Only secret (sk_live_) and restricted (rk_live_) keys must stay on the server.

Is a Firebase or Google API key in my frontend a problem?

Firebase web API keys are public identifiers, not secrets. Protect your data with Firebase security rules, and restrict the key to your domains and required APIs in Google Cloud Console.

I deleted the key from my code. Am I safe?

Not until you revoke or rotate it at the provider. Old bundles stay cached, and automated scrapers may have already copied it.

More free tools