44

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

4
  • 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. Commented Feb 11, 2017 at 20:36
  • It does but I am too dumb to make any sense of it developers.google.com/api-client-library/javascript/features/…
    – Ryan Mc
    Commented Feb 11, 2017 at 20:41
  • 2
    I'm not sure why this was marked as a duplicate. It's clearly not.
    – vhs
    Commented Jun 11, 2017 at 6:05
  • If you came here, you should probably read about CORS. To resolve your specific error with the google places API, read the answer below: Commented Apr 23, 2019 at 7:42

5 Answers 5

48

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

4
  • 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
    Commented Feb 12, 2017 at 9: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
    Commented Feb 12, 2017 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
    Commented Feb 12, 2017 at 11:23
  • 9
    @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
    Commented Mar 11, 2019 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': '' }
      }
    }
  }
}
1
  • 5
    but, how do you make this work in production the cors security is here too Commented Apr 23, 2020 at 10:05
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))
1

We have found that direct requests with Javascript are not allowed because of CORS issues against this API

https://maps.googleapis.com/maps/api/place/details/

This is a legacy API endpoint designed to work with server-side calls, not browser-based calls that are done with Javascript.

The new approach is to use the Places feature through the Google Maps JS library.

To do so

Add the library to your HTML

<script>
  (g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({
    key: "YOUR_API_KEY",
    v: "weekly",
    // Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).
    // Add other bootstrap parameters as needed, using camel case.
  });
</script>

In your script file. Load the place library and look up your place details.

  const {Place} = await google.maps.importLibrary("places");
  const place = new Place({
    id: "ChIJN5Nz71W3j4ARhx5bwpTQEGg",
    requestedLanguage: "en", // optional
  });

  // Call fetchFields, passing the desired data fields.
  await place.fetchFields({
    fields: ["displayName", "formattedAddress", "location"],
  });
  // Log the result
  console.log(place.displayName);
  console.log(place.formattedAddress);
  

References:

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);
});

Not the answer you're looking for? Browse other questions tagged or ask your own question.