I made a weather app in Create React App (create-react-app
). How do I hide the API key so that I can commit to GitHub?
Right now, the key is in App.js:
const API_KEY = "123456";
I made a weather app in Create React App (create-react-app
). How do I hide the API key so that I can commit to GitHub?
Right now, the key is in App.js:
const API_KEY = "123456";
Unfortunately, keeping any key in your React client, even if you are using gitignore and an .env
file, is not secure. As pointed out by Claudiu Creanga, React environment variables are embedded in the build and are publicly accessible.
You should really only save API keys or secrets in your backend such as Node.js or Express.js. You can have your client send a request to your backend API, which can then make the actual API call with the API key and send the data back to your client.
Disclaimer
WARNING: 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.
The following answer provides a correct way to store non-secret data in environment variables. Remember that secret data is accessible through developer tools, making it unsafe to store as environment variables. If you want to store some secret data then storing in the backend is the better option and if the client wants to access secret data, it can be accessed by making a request to the server. (Refer to Antonia's answer for more details on storing secret data.)
As it turns out, create-react-app has some built-in functionality to help you with that. Thank you George Karametas for this insight. To access that functionality, you need to:
.env
in the root of your project's directory.- your_project_folder
- node_modules
- public
- src
- .env <-- create it here
- .gitignore
- package-lock.json
- package.json
.env
file, prepend REACT_APP_
to your API key name of choice and assign it.The create-react-app
tool uses REACT_APP_
to identify these variables. If you don't start your API key name with it, create-react-app
won't see it.
// .env
REACT_APP_API_KEY=your_api_key <-- yes
API_KEY=your_api_key <-- no
// Example (from 이준형's response):
REACT_APP_WEATHER_API_KEY=123456
.env
file to your .gitignore
file.After you add the line below, save the .gitignore
file and do a git status
to make sure your .env
file does not appear as a new file in git.
// .gitignore
# api keys
.env <-- add this line
# dependencies
/node_modules
...
process.env
object.To check that you can access your API key, go to your App.js file and add a console.log at the top below the require
statements. After saving the file and reloading the page, if the console log does not show your API key, try restarting the react server. Be sure to remove the console log line before committing your code.
// src/App.js
import React, { Component } from 'react';
import './App.css';
console.log(process.env.REACT_APP_WEATHER_API_KEY)
class App extends Component {
...
undefined
back. >Note: You need to restart the development server after changing .env files. source: create-react-app.dev/docs/adding-custom-environment-variables –
Madonia process is not defined
–
Utrillo Unless you're making tutorial applications, don't put secrets such as API keys in client-side source code (e.g., a React app). From Create React App's documentation:
WARNING: 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.
First, create an .env file in the root of your project, i.e., where you would run react-scripts start
(or yarn start
) outside of your source folder.
Then, add
REACT_APP_WEATHER_API_KEY=123456
Before commit, you should exclude this .env file, so find the .gitignore file and add .env.
The name of the variable needs to begin with REACT_APP_
which protects you from accidentally including secrets with your build.
Don't forget to add .env in the .gitignore file.
To use the environment variables in your code:
const API_KEY = process.env.REACT_APP_WEATHER_API_KEY;
In order to read environment variables after having added them to .env
, restart your server.
From the React documentation:
WARNING: 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.
Although the question has already been answered by Antonia Blair, I would like to through some more light on some basic rules.
1: Most of the answers are suggesting to make use of the .env file. I would like to make it clear for once and all that .env is not here to add any security layer. The .env as the name depicts is only here to set up an environment at build time. e.g. by using the environment variables you set some global values at build time and can access these values in your application at runtime.
2: React is simply a framework running your JavaScript code in the client browser. So the client has complete access to the JavaScript (React) code. Nothing is secure on the client-side. So never think of making something secure or hidden from the client by just keeping all your code client-side. Whenever you need to hide something from the client, there is something server-side which you need to incorporate. Only the server-side code is secure from the client-side.
3: So what you do is, you will keep your secure keys on the server-side.
Suppose the purpose of your secure keys is to make a cookie for your client. so the client needs the cookie not the secure keys, right? So the client-side makes a request to the server for a cookie, the server makes the cookie by using the secure keys and returns the cookie to the client. After all the client is only here to eat the cookie and not to know how do we make a cookie right?
4: So the thumb rule is that wherever you have some confidential data, you will keep it on the server. The server will use this confidential data and return the result data to be exposed to the client.
A user has asked for a coding example, so I have put up a real-time scenario which I have handled using the above described technique.
Here is my use case:
I have a React app which submits a public form to non public API.
The non public API is Harvest API hosted by:
https://www.greenhouse.io/
This API requires an authentication header for making requests with it. I have subscribed with the API owner and received a secret token from them which I can use with my requests to get access to their API
Af course, I want to keep my token personal and do not expose it to public users
I have used the Axios client to communicate with the API
I have two ways to perform the above described scenario:
The Incorrect Method
I am making requests to the API directly from my React application
Let’s say below is the API endpoint which I want to hit
apiURL = https://boardsapi.greenhouse.io/v1/boards/xyz/jobs/" + jobId + ""
The above API endpoint requires an authorization header, and I will provide my secret token in it.
const config = {
headers: {
"Authorization": "Basic ####MySecretCode#####",
} };
Suppose I want to post some form data with this request
let formData = MyFormData
I can now send my request using the Axios client like below
let result = await axios.post(apiURL, formData, config);
Using the above technique, I can successfully post my form data to the Harvest API.
But like I said, that it's an incorrect way to communicate with this API. Because I have exposed my secret token on the client side.
The Correct Way
I built an API on Node.js and hosted it publicly.
Suppose I want to post some form data to the Harvest API
let formData = MyFormData
I am not going to hit the Harvest API directly from my client application. And instead I have exposed and endpoint in my middleware API to handle this.
Let’s say the below is the endpoint URL of my middleware API which I want to hit
apiURL = https://proxy-server/apply
The above API endpoint does not requires an authorization header. So I can send a post requests using the Axios client like below:
let result = await axios.post(apiURL, formData);
The difference is clear. I have not supplied the secret token this time in my request. Because this is not a direct request to the Harvest API and instead it's a request to a middle-ware API which is developed and hosted by me.
I receive this request in my middle-ware API, add my secret token with it and forward it to the Harvest API. The response from Harvest API is returned to our middle_ware API and hence forward back to our React client application.
The secret token now resides on my server-side API and safe from external users.
Here's what worked for me:
I created the .env file in the root folder. Within that folder I added my key:
REACT_APP_API_KEY_YT = "key"
// I added 'YT' for YouTube which is where my API key is from
Then I went to .gitignore. Or create a .gitignore file in your root directory if you don't have it. Within .gitignore, I added .env
# API key
.env
Then I went back to the root of my App js file. For me, that was index.js. For others, it is probably App.js.
There I created a const API_KEY
const API_KEY =`${process.env.REACT_APP_API_KEY_YT}`
I checked if it was working by console logging it.
console.log("API", API_KEY)
I was getting undefined
.
I stopped the server (Ctrl + C) and restarted the server.
Afterwards I was able to see the key.
Here is an example of finding the API key in code even when you attempt to hide it in an environment variable.
I built a very simple app using the NewsAPI, which required me to register for an API key. Here is my fetch to the NewsAPI endpoint using the API key as an environment variable.
fetch(`https://newsapi.org/v2/top-headlines?q=${keyword}&apiKey=${process.env.REACT_APP_API_KEY}`)
.then(res => res.json())
.then(
(result) => {
setIsLoaded(true);
setArticles(result.articles);
})
However, when I inspected the network request with Chrome dev tools, you will be able to see the actual value of the API key. I hope this helps folks see how somebody could find an API key on the client even if you store it as an environment variable.
How one could hide an API key:
You could make the HTTP request from your server side logic, so you can safely hide an API key in the .env file. In the below example I created an enpoint to /top-headlines/:searchTerm. Once a request to that endpoint is received, then I send the Axios request to the news API using the "NEWS_API_KEY" environment variable which is stored in my .env file.
route.get("/top-headlines/:searchTerm", async (req, res) => {
const { searchTerm } = req.params;
try {
const articlesResponse = await axios.get(
`https://newsapi.org/v2/top-headlines?q=${searchTerm}&apiKey=${process.env.NEWS_API_KEY}`
);
const articlesData = articlesResponse.data;
res.send(articlesData);
} catch (error) {
console.log(error);
}
});
Be advised! If you put any credentials in a React client, they are not secure, even if you are using gitignore and an .env file. Still they are not secure.
You should really only save API keys or secrets in your backend, such as Node.js or Express.js. Use a proxy, send the request from the front end to the backend and then the backend will make a request for fetching data to front end.
If you are in production, then you cannot use environment variable directly there for frontend (React). You need to follow the instructions on How to implement runtime environment variables with create-react-app, Docker, and Nginx in order to achieve this goal if you want to access environment variables in production.
If you use the API key for local development purposes, put it under the .env.development file and Git ignore it. Credentials in the .env file will be picked up by the build process, which will expose the data in production.
For details, see What other .env files can be used?
follow these steps :
Install env-cmd package from npm (npm i env-cmd)
Make file .env in your root
Inside the .env file , add varibles with prefix (REACT_APP)
eg : REACT_APP_APIKEY="yourapikeyhere"
go inside package.json and change the "scripts" as
"scripts": {
"start": "env-cmd -f .env react-scripts start",
"build": "env-cmd -f .env react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
}
use the variable as key = process.env.REACT_APP_APIKEY
Note: After each modification in env file, stop the server and start it again, otherwise it wont read your new changes.
The secure key/secret should never be sent to the client side. Say, you want to download a file from S3 down on the client machine via your app (running in a browser).
Make a call to the server to obtain a ephemeral token (which expires with time)
the server (which has the secret and everything) makes the token and sends it back
the client uses the token to access S3
The token itself is not a secret and it's useless once it expires.
No answer helped me, rather I figured on my own. For the latest React 18.2.0
you will have to name all the env variables like:
REACT_APP_VARIABLE
This is the only working format, and make sure you globally install dotenv.
Good luck!
Creating a .env file is helpful as stated in previous answers. But one point to notice here is that:
If you are using API_KEY
in your URL as state
like this,
this.state = {
url:`http://newsapi.org/v2/everything&apiKey=${process.env.REACT_APP_API_KEY}`
}
then it will be visible in React developer tool.
Instead, you can put your API_KEY
directly at the location of fetch. For example,
fetch(`http://newsapi.org/v2/everything?&apiKey=${process.env.REACT_APP_API_KEY}`)
© 2022 - 2025 — McMap. All rights reserved.