Open Weather Map API Key and Environment Variables

I’m trying to build a React weather app using Open Weather Map’s API. In concurrence with best practices, I want to store the API key in an environment variable (in a .env file). I also installed dotenv and called the environment variable:

import React from 'react';
//import logo from './logo.svg';
import './App.css';

require('dotenv').config();

class App extends React.Component {
  constructor(props) {
    super(props);

    this.openWeatherMapCall = this.openWeatherMapCall.bind(this);
  }

  openWeatherMapCall() {
    fetch(`https://cors-anywhere.herokuapp.com/https://api.openweathermap.org/data/2.5/forecast?id=5206379&APPID=${process.env.APP_ID}`)
      .then(res => res.json())
      .then(data => {console.log(data)});
  }

  render() {
    this.openWeatherMapCall();
    return (
      <code>
        {this.openWeatherMapCall()}
      </code>
    )
  }
}

export default App;

However, I’m getting a weird 401 error that says I’m using an invalid API key (I doubled-checked for misspellings and found nothing):

I went to the FAQ section on their site about 401s but didn’t really find anything that could help me.

Any ideas on what I’m doing wrong? FWIW, the .env is in the main branch of the project’s direction (not inside of the src folder).

Thanks-in-advance!

Try adding console.log(process.env.APP_ID) on the line before the fetch in the openWeatherMapCall method. Do you see your APP_ID?

Nope. It’s undefined. And I found this thread on Stack Overflow and it said it’s undefined because " the Node.js execution environment does not know the newly added [APP_ID]."

So I tried the steps they suggested in the thread by exporting APP_ID from the .bash_profile but it’s still undefined. :frowning_face:

hi @Dusch4593
if your are using react with create react app then , you should prefixe your API key name in .env file with REACT_APP_{YOUR_API_KEY_NAME} , because create react app will ignore all env variables not staring with it

Just tried that, actually! I’m still getting undefined. I changed it to REACT_APP_API_KEY.

You really should not be adding the API key to the React app anyway. You want that to be hidden from the browser. If you still want to use one locally, you can also do something like the following on the command line

REACT_APP_APP_ID=123456 yarn start

Then in your App.js file, you would reference process.env.REACT_APP_APP_ID.

1 Like

What’s the safe way to do it?

You want a proxy server. You would have your own API that makes the fetch call on the server using the API key so the browser never sees it. Your React app would make a request to your API instead.

@Dusch4593 You should already be familiar with discussion from this other thread.

Oh ok, so I need to make a backend server that works with the API key separate from the frontend (like I did with the Goodreads clone)?

That is what I recommend, but you do not have to do that. You just run the risk of someone else using your key for there own site and maximizing out the requests/hour limit for the free version of the API. If you already have a backend for the other project, it is as simple as adding another route.

1 Like

I’m gonna work on that next chance I get with the computer. Thanks, Randell!

So I began to work on the backend server but I’m running into a really confusing situation: I’m getting a successful fetch, but when I try to log the response, I’m getting this message on my terminal:

Missing required request header. Must specify one of: origin,x-requested-with

Again, according to my local server, the fetch is successful:

This is the route I made for making the call:

//Open Weather Map Route
backend.get("/", async (req, res) => {
	try {
		// Using node-fetch with Pittsburgh's city ID on Open Weather Map along with API Key (APP_ID)
		const response = await fetch(`https://cors-anywhere.herokuapp.com/https://api.openweathermap.org/data/2.5/forecast?id=5206379&APPID=${process.env.REACT_APP_API_KEY}`);

		// The API returns stuff we don't care about, so we may as well strip out
		// everything except the results:
		console.log(await response.text());
		return res.json({
            success: true,
        })
	} catch (err) {
		return res.status(500).json({
			success: false,
			message: err.message,
		})
	}
})

I looked online for an explanation of why I’m getting this message on my terminal (I’m getting it in Postman, too) but I can’t understand why?

Do you have a link to your full project code, so I can test a few things?

Also, why are you using cors-anywhere.herokuapp.com. That should not be necessary since you are fetching from the backend.

Whether you intended it or not, you’ve answered my question by asking me why I was still using cors-anywhere.herokuapp.com :wink: Now I’m seeing the data logging to my terminal!

1 Like

So just to recap:

If I’m fetching data from the front-end, use cors-anywhere.herokuapp.com.

If I’m fetching from the backend (which seems to be the safest way), then use the regular api url to make the fetch.

Sounds right?

If you have a backend server, you can make your fetch call (from the front-end) to your back-end API that would make the actual request to the Open Weather Map API. This is what you already did in the other project.