How to Secure API Keys in React Apps Without Backend Knowledge


Join thousands of professionals and get the latest insight on Compliance & Cybersecurity.
You've built an amazing React application that needs to connect to a third-party API. But then you hit that dreaded roadblock: where do you safely put your API key? You've heard horror stories about exposed keys leading to security breaches and unexpected bills, but you don't have backend experience to properly secure them.
"If you make a call from the frontend, then anyone opening the page can see the API key," warns a concerned developer on Reddit. This common frustration leaves many frontend developers feeling stuck between exposing sensitive credentials and venturing into unfamiliar backend territory.
The truth is undeniable: there are no secrets in the UI. Any code, variables, or keys in your frontend build are inherently public and accessible. However, this doesn't mean you're helpless. This guide will walk you through practical, step-by-step solutions that even pure frontend developers can implement to secure their API keys—without becoming backend experts.
Why You Can't Just "Hide" an API Key in React


Before diving into solutions, let's understand why this problem exists in the first place.
An API key is an alphanumeric string that acts as an authentication token, granting your application access to a third-party service. Think of it as a special password that identifies your application and authorizes its requests.
When you build a React application, all of your code—including any embedded API keys—gets compiled into JavaScript files that are sent to the user's browser. This means that anyone can:
- Open your website
- Press F12 to access developer tools
- Check the Network tab to see all API requests (and your key in the URL or headers)
- Inspect your JavaScript bundle to find hardcoded keys
The consequences of exposed API keys can be severe:
- Unauthorized Data Access: Attackers can use your key to access sensitive information through the API.
- Financial Consequences: Many APIs charge based on usage. If someone steals your key and makes thousands of requests, you'll be footing the bill.
- API Misuse: Bad actors can use your key for malicious purposes, potentially getting your access revoked.
- Regulatory Non-Compliance: Exposing keys that access personal data could violate regulations like GDPR or CCPA.
As one Reddit user bluntly puts it: "Everything in the front end should be assumed to be unsecure. You should assume it will be used maliciously. End of story."
The First Line of Defense: Environment Variables (and Their Critical Limits)
The most common first step developers take is using environment variables. While this approach doesn't truly hide your keys, it does offer some important benefits:
- It keeps your keys out of your source code
- It prevents your keys from being committed to version control
- It follows the best practice of configuration separation
Here's how to set it up in a Create React App project:
- Create a
.envfile in the root of your project:REACT_APP_API_KEY=your-secret-api-key - Add it to your
.gitignorefile to ensure it's never committed:# .gitignore .env - Access the key in your React component:
const apiKey = process.env.REACT_APP_API_KEY; fetch(`https://api.example.com/data?key=${apiKey}`) .then(response => response.json()) .then(data => console.log(data)); - Restart your development server for the changes to take effect.
CRITICAL WARNING: Environment variables in React are not actually secure! As the Create React App documentation explicitly states: "Do not store any secrets (such as private API keys) in your React app! Environment variables are embedded into the build, meaning anyone can view them by inspecting your app's files."
So when is using environment variables acceptable? Only in these scenarios:
- For public keys that are more like identifiers (e.g., some Firebase keys)
- For keys accessing non-sensitive, public data (e.g., a movie database API)
- When combined with additional protective measures:
Additional Protective Measures
If you must use an environment variable for a public API key, always add these layers of protection:
- Domain Restriction (Whitelisting): Many API providers (like Google Maps) allow you to restrict key usage to specific domains. In your API provider's dashboard, whitelist only your website's domain to prevent the key from being used elsewhere.
- Quota Limits: Set tight usage quotas to mitigate financial damage if the key is somehow abused. This doesn't prevent theft, but it limits the potential damage.
As one Reddit user cautions: "Once you expose your key to the client, you cannot guarantee its security from malicious use." That's why for truly sensitive APIs, we need a more robust solution.


The "No Backend" Backend: Using Serverless Functions as a Secure Proxy
The gold standard for securing API keys is the proxy pattern: your React app calls your own secure endpoint, which then calls the third-party API using the sensitive key. The key never leaves your server.
But what if you don't have a traditional backend? This is where serverless functions come in—they're perfect for frontend developers because they provide backend-like security without requiring you to manage a traditional server.
Platforms like Netlify and Vercel make this incredibly easy, enabling you to deploy your React app and secure serverless functions together. Here's how to implement this with Netlify Functions:
- Setup: Create a
netlify/functionsdirectory in your project. - Store the Secret: Go to your Netlify site settings and add your sensitive API key as an environment variable (e.g.,
THIRD_PARTY_API_KEY). Unlike frontend environment variables, these are genuinely secure and never exposed to the browser. - Create the Function: Create a file like
netlify/functions/fetch-data.js:// This code runs in a secure server environment, not the browser. exports.handler = async function(event, context) { const API_SECRET = process.env.THIRD_PARTY_API_KEY; const API_URL = 'https://api.example.com/data'; try { const response = await fetch(`${API_URL}?key=${API_SECRET}`); const data = await response.json(); return { statusCode: 200, body: JSON.stringify(data), }; } catch (error) { return { statusCode: 500, body: JSON.stringify({ error: 'Failed fetching data' }), }; } }; - Call from React: Now your React component calls your own endpoint, with no key in sight:
// In your React component async function getData() { try { const response = await fetch('/.netlify/functions/fetch-data'); const data = await response.json(); // use the data... return data; } catch (error) { console.error('Error:', error); } }
The magic here is that the THIRD_PARTY_API_KEY is never exposed to the client. The browser only sees the request to /.netlify/functions/fetch-data, while the actual API key is safely used on Netlify's servers.
As recommended in countless developer discussions: "You need to write a simple proxy server (just a backend code) to fetch the api data using the api key and then pass it to the client." Serverless functions make this recommendation accessible to frontend developers without requiring traditional backend knowledge.
The Easiest Route: Third-Party API Gateway Services
For developers who want an even simpler, managed solution, third-party API gateway services can be a game-changer. These services act as a secure proxy between your frontend and third-party APIs, managing all the security concerns for you.
One such example is KOR Connect, which aims to simplify the process:
- Register on the service's platform.
- Connect Your API: Securely provide your third-party API endpoint and your secret key to the service.
- Receive a Secure URL: The service generates a new, public-safe URL for you to use in your frontend application.
- Implement in React: Use the new URL in your
fetchcalls:fetch("https://your-secure-gateway-url.example.com/covid-19/v1/countries", { "method": "GET", "headers": { "x-rapidapi-key": "your-public-api-key" // This is a safe key provided by the service } }) .then(response => { console.log(response); }) .catch(err => { console.error(err); });
The benefits of this approach include:
- No code to write for the proxy
- Managed infrastructure (no serverless deployment to configure)
- Often includes extra security features like bot detection
Choosing the Right Strategy for Your Project


To recap, here are your options from least to most secure:
- Environment Variables (with domain restrictions and quotas): Use ONLY for non-sensitive, public keys or when you're just getting started and need a quick solution.
- Serverless Functions: The best all-around solution for frontend developers needing to protect sensitive keys. It gives you full control without the overhead of a traditional backend.
- Third-Party Services: The fastest and easiest option, ideal for rapid prototyping or for developers who want a fully managed solution.
Regardless of which method you choose, follow these universal API key best practices:
- Rotate API Keys Regularly: Limit the window of opportunity for attackers if a key is ever compromised.
- Use Granular Permissions: Only grant keys the minimum permissions they need to function (Principle of Least Privilege).
- Monitor Usage: Keep an eye on your API dashboards to detect anomalous activity early.
As a frontend developer, you now have the tools to properly secure your API keys without becoming a backend expert. Remember, the fundamental principle remains: "There are no secrets in the UI"—but with these approaches, you can build secure applications that keep your sensitive credentials where they belong: server-side.


Frequently Asked Questions
Why can't I just hide my API key in a .env file in React?
You cannot truly hide an API key in a .env file in a standard React application because environment variables (like REACT_APP_API_KEY) are embedded directly into the final JavaScript build files. This means anyone can find the key by inspecting your website's source code in their browser. While .env files are essential for keeping secrets out of version control (like Git), they offer no protection on the client-side.
What is the most secure way to manage API keys for a frontend application?
The most secure way is to use a server-side proxy. Your frontend application makes a request to your own backend endpoint (the proxy), which then securely adds the API key and forwards the request to the third-party API. This ensures the API key is never exposed to the user's browser. Serverless functions are an excellent, low-maintenance way for frontend developers to implement this pattern.
How do serverless functions help secure API keys?
Serverless functions act as a secure intermediary between your React app and the third-party API. Your secret API key is stored as a secure environment variable on the serverless platform (like Netlify or Vercel), completely inaccessible from the browser. Your React app calls your serverless function endpoint without any key, and the function then adds the secret key on the server before making the final call to the API.
Is it ever safe to expose an API key on the client-side?
It is only safe to expose an API key on the client-side if it is a public, non-sensitive key that is not tied to a billing account and does not grant access to private data. Even in these cases, you should always implement additional security measures offered by the API provider, such as restricting the key's usage to your specific domain (whitelisting) and setting strict usage quotas to prevent abuse.
What is an API proxy and why do I need one?
An API proxy is a server that acts as a go-between for your client application and a third-party API. You need one to protect sensitive credentials like API keys. Instead of your React app calling the third-party API directly and exposing the key, it calls your proxy. The proxy, running in a secure server environment, then adds the secret key to the request and forwards it to the third-party service, keeping the key safe.
How are server-side environment variables different from client-side ones?
Client-side environment variables (used in tools like Create React App) are embedded into the JavaScript code that gets sent to the user's browser, making them public. Server-side environment variables (used in serverless functions or traditional backends) exist only on the server and are never exposed to the browser. This fundamental difference is why you must use a server-side component to protect sensitive keys.