Security

Securing API Keys in Client-Side JavaScript Applications

SyncTonight Team7 min read2 views0 likes

Here's the uncomfortable truth that a lot of tutorials gloss over: any API key embedded in client-side JavaScript is visible to anyone who opens their browser's developer tools, no matter how you try to obscure it. Minifying the code, Base64-encoding the key, or splitting it across multiple variables doesn't hide it — it just adds a trivial extra step for anyone determined to find it.

This matters because a genuinely secret API key — one that grants access to a paid service, a database, or an account with real permissions — should never be shipped to the browser at all, full stop, regardless of how it's obfuscated. If your application currently embeds a secret key in frontend code, that key should be treated as already compromised, because it effectively is the moment it's public.

The correct architecture is to keep the real secret key on your own server and have the frontend talk to your server instead of the third-party API directly. Your server, which the public can't inspect, holds the actual secret key and makes the authenticated request to the third-party service on the frontend's behalf, then returns just the data the frontend needs.

This is exactly why services like Stripe distinguish between a 'publishable' key (safe to embed in frontend code, deliberately designed for that purpose, with very limited permissions) and a 'secret' key (which must only ever live on your server). If a service you're integrating with only issues one type of key, and it says 'secret' or 'private' anywhere in its name or documentation, that's your signal it must never appear in frontend code.

For APIs you don't control that only offer a single API key with no public/private split, and you genuinely need to call them from client-side code, the practical fix is to build a small server-side proxy endpoint of your own — the frontend calls your endpoint, your server attaches the real key and forwards the request, and the response comes back through your server. The key never reaches the browser at any point.

Rate limiting and usage restrictions on the key itself are a valuable second layer, not a replacement for keeping it server-side. Many API providers let you restrict a key to specific origins, IP ranges, or usage caps — enabling these restrictions limits the damage if a key does leak, but it doesn't make embedding a genuinely secret key in frontend code acceptable in the first place.

If you're auditing an existing codebase for this issue, search your frontend source for common patterns like 'sk_', 'secret', 'api_key =', and similar, and check version control history too — a key that was in the code and later removed may still exist in an old commit, publicly visible if the repository is public, and should be rotated regardless of whether it's still in the current code.

Found this helpful?

SyncTonight's tools and guides are free and always will be. If this post saved you some debugging time, a coffee goes a long way — no pressure, just appreciated.

☕ Buy me a coffee

Keep Reading

Also available

We also build websites.

Need a landing page, a full product site, or a custom web app built? We design and develop those too — same speed and no-nonsense approach you see here. Let us know what you're building.

Landing pagesFull websitesWeb appsSaaS MVPsDashboards
Let's talk about your project