39

I really do NOT understand how I'm supposed to make this work:

var requestURL = 'https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJN1t_tDeuEmsRUsoyG83frY4&key=AIzaSyAW4CQp3KxwYkrHFZERfcGSl--rFce4tNw';

console.log(requestURL);

$.getJSON( requestURL, function( data ) {
  // data
  console.log(data);
});

and my HTML file:

  <body>

        <script
  src="https://code.jquery.com/jquery-2.2.4.min.js"
  integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
  crossorigin="anonymous"></script>
        <script src="main.js" charset="utf-8"></script>   
  </body>

I always get the No 'Access-Control-Allow-Origin' header is present on the requested resource. message... even though if I go to https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJN1t_tDeuEmsRUsoyG83frY4&key=AIzaSyAW4CQp3KxwYkrHFZERfcGSl--rFce4tNw in my browser I get the proper JSON returned.

I am lead to believe that CORS can help me here. I don't understand CORS. Please, can anyone help me in plain simple terms? What should I change to make this work??

Thanks

Ryan Mc
  • 833
  • 1
  • 8
  • 25
  • The first thing to do is see if Google Places support CORS. If not, there's no point. My guess is they only support JSONP, but check the documentation. – Kevin Christopher Henry Feb 11 '17 at 20:36
  • It does but I am too dumb to make any sense of it https://developers.google.com/api-client-library/javascript/features/cors – Ryan Mc Feb 11 '17 at 20:41
  • 2
    I'm not sure why this was marked as a duplicate. It's clearly not. – vhs Jun 11 '17 at 06:05
  • If you came here, you should probably read about [CORS](https://stackoverflow.com/questions/14681292/same-origin-policy-and-cors-cross-origin-resource-sharing). To resolve your specific error with the google places API, read the answer below: – Jonas Wilms Apr 23 '19 at 07:42

4 Answers4

46

You are trying to use the Google Places API Web Service on client side whereas it is designed for server side applications. That's probably why appropriate CORS response headers are not set by the server.

As explained in the Notes at the beginning of the Place Details documentation, you should use the Places Library in the Google Maps JavaScript API:

If you're building a client-side application, take a look at the Google Places API for Android, the Google Places API for iOS, and the Places Library in the Google Maps JavaScript API.

Note: you will need to enable the Google Maps JavaScript API in your Google Developer Console first.

Here is a way you can proceed to get place details (based on the example from the documentation):

<head>
    <script type="text/javascript">
        function logPlaceDetails() {
          var service = new google.maps.places.PlacesService(document.getElementById('map'));
          service.getDetails({
            placeId: 'ChIJN1t_tDeuEmsRUsoyG83frY4'
          }, function (place, status) {
            console.log('Place details:', place);
          });
        }
    </script>
    <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAW4CQp3KxwYkrHFZERfcGSl--rFce4tNw&libraries=places&callback=logPlaceDetails"></script>
</head>
<body>
    <div id="map"></div>
</body>

Google Place details output to the console

rd3n
  • 4,440
  • 1
  • 33
  • 45
  • 1
    This seems good but a few things: 1) You're using ES6 (I dont understand ES6 yet), 2) it doesnt work for me, 3) I dont want a map, I just want to return the object of the place so I can output the data in anyway I choose. Thanks for your help – Ryan Mc Feb 12 '17 at 09:19
  • 1) I have just replaced `const` by `var` and `(place, status) =>` by `function(place, status)` so there is no more ES6, 2) Can you elaborate? Do you have an error in the console? 3) I am not a Google Maps expert but it seems you can provide a Dom node instead of a map instance to the `PlacesService`, so no map is rendered. I have tested and updated the code accordingly – rd3n Feb 12 '17 at 10:46
  • I finally got this to work by modyfying the example on the Google documentation. Thanks, your answer pointed me in the right direction. – Ryan Mc Feb 12 '17 at 11:23
  • 8
    @RyanMc since rd3n's answer did not answer your question, can you post your modified code as an answer? I am interested to see what you did. – rmutalik Mar 11 '19 at 23:47
3

@rd3n already answered about why to use Google Maps' SDK, but if you really need to use the API instead of SDK on a web app (reuse code, for exemple), you can bypass CORS using proxy parameter from Webpack's DevServer.

const GMAPS_PLACES_AUTOCOMPLETE_URL = (
  process.env.NODE_ENV === 'production'
    ? 'https://maps.googleapis.com/maps/api/place/autocomplete/json'
    : 'place-api' // on development, we'll use the Webpack's dev server to redirect the request

const urlParams = new URLSearchParams([
  ...
])

const response = await fetch(
  `${GMAPS_PLACES_AUTOCOMPLETE_URL}?${urlParams}`,
  { method: 'GET' }
)

And on your webpack.config.js...

module.exports = {
  devServer: {
    proxy: {
      '/place-api': {
        target: 'https://maps.googleapis.com/maps/api/place/autocomplete/json',
        changeOrigin: true,
        pathRewrite: { '^/place-api': '' }
      }
    }
  }
}
macabeus
  • 4,156
  • 5
  • 37
  • 66
1

I know this is an old question, and this might not be a direct answer to this question, but just in case someone could use this trick, I always like to go around this issue using PHP to create my own API, then fetch the newly created API using JavaScript:

1# Create an api.php file:

<?php
$google_URL = 'https://maps.googleapis.com/maps/api/place/details/json';
$api = 'YOUR_GOOGLE_API';
$place = 'PLACE_ID';    
$field = [
    'user_ratings_total',
    'rating'
];
    
$fields =  join(",", $field);
$result_url = $google_URL.'?placeid='.$place.'&fields='.$fields.'&key='.$api;
$result_content = file_get_contents($result_url);
$json_data = json_decode($result_content, true);

if ( isset($json_data) && $json_data['status'] === 'OK' ) {
    echo json_encode($json_data['result']);
}else {
    echo json_encode($json_data['error_message']);
}

header("content-type: application/json");

2# Create a script.js file:

const url = './api.php';
fetch(url)
.then(res => res.json())
.then(data => console.log(data))
.catch(error => console.log(error))
nourhomsi
  • 323
  • 1
  • 11
0

Using the same url you provided, this is for pure front-end (React), but a less secure solution:

var requestURL = 'https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJN1t_tDeuEmsRUsoyG83frY4&key=AIzaSyAW4CQp3KxwYkrHFZERfcGSl--rFce4tNw';

Cut out the following from url: 'https://maps.googleapis.com/maps/api/place' and create a proxy line in your package.json:

"proxy": "https://maps.googleapis.com/maps/api/place"

Then following google documentations you'll be left with the following code (wherever you're fetching the api):

var axios = require('axios');

var config = {
  method: 'get',
  url: '/details/json?placeid=ChIJN1t_tDeuEmsRUsoyG83frY4&key=AIzaSyAW4CQp3KxwYkrHFZERfcGSl--rFce4tNw', //the rest of your url
  secure: false //important
};

axios(config)
.then(function (response) {
  console.log(JSON.stringify(response.data));
})
.catch(function (error) {
  console.log(error);
});
Mahan Mashoof
  • 141
  • 1
  • 5