Find places

Learn how to search for coffee shops, gas stations, restaurants and other nearby places with the geocoding service.

Place finding is the process of searching for a place name or POI to find its address and location. You can use the geocoding service to find places such as coffee shops, gas stations, or restaurants for any geographic location around the world. You can search for places by name or by using categories. You can search near a location or you can search globally.

In this tutorial, you use ArcGIS REST JS to access the geocoding service and find places by place category.

Prerequisites

You need a free ArcGIS developer account to access your dashboard and API keys. The API key must be scoped to access the services used in this tutorial.

Steps

Create a new pen

  1. To get started, either complete the Display a map tutorial or .

Set the API key

To access ArcGIS location services, you need an API key.

  1. Go to your dashboard to get an API key.

  2. In CodePen, update apiKey to use your key.

    Change line
        
    const apiKey = "YOUR-API-KEY";
    const basemapId = "ArcGIS:Streets";
    const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey;
    olms(map, basemapURL);
    

Add references to ArcGIS REST JS

This tutorial uses ArcGIS REST JS for place finding.

  1. In the <head> element, add references to the ArcGIS REST JS library.

    Add line.
                                                                                                                                           
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
        <title>OpenLayers Tutorials: Find Places</title>
    
        <style>
          html,
          body,
          #map {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 14px;
            color: #323232;
          }
        </style>
    
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" />
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-geocoding@3.0.0/dist/umd/geocoding.umd.js"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script>
    
      </head>
    
      <body>
    
        <div id="map"></div>
    
        <select id="places-select" style="right: 20px; top: 20px; position: absolute; font-size: 16px; padding: 4px 8px;">
          <option value="">Choose a place type...</option>
          <option value="Coffee shop">Coffee shops</option>
          <option value="Gas station">Gas stations</option>
          <option value="Food">Food</option>
          <option value="Hotel">Hotels</option>
          <option value="Parks and Outdoors">Parks and Outdoors</option>
        </select>
    
        <script>
    
          const apiKey = "YOUR-API-KEY";
    
          const map = new ol.Map({
            target: "map"
          });
    
          const view = new ol.View({
    
            center: ol.proj.fromLonLat([-122.4194,37.7749]), // San Francisco
    
            zoom: 14
          });
          map.setView(view);
    
          const basemapId = "ArcGIS:Navigation";
    
          const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey;
    
          olms(map, basemapURL).then(function (map) {
    
            const placesLayer = new ol.layer.Vector({
              source: new ol.source.Vector(),
    
              style: (feature) =>
                new ol.style.Style({
                  image: new ol.style.Circle({
                    radius: 5,
                    fill: new ol.style.Fill({ color: "white" }),
                    stroke: new ol.style.Stroke({ color: "hsl(220, 80%, 40%)", width: 2 })
                  }),
                  text: new ol.style.Text({
                    font: "14px sans-serif",
                    textAlign: "left",
                    text: feature.get("PlaceName"),
                    offsetX: 8, // move text to the right to avoid overlapping circle
                    offsetY: 2, // move down to align with circle's center
                    fill: new ol.style.Fill({ color: "hsl(220, 80%, 40%)" }),
                    stroke: new ol.style.Stroke({ color: "white" })
                  })
                }),
              declutter: true
    
            });
    
            map.addLayer(placesLayer);
    
            function showPlaces() {
    
              const authentication = new arcgisRest.ApiKey({
                key: apiKey
              });
              const category = document.getElementById("places-select").value;
              arcgisRest
                .geocode({
                  authentication,
                  outFields: "Place_addr,PlaceName", // attributes to be returned
    
                  params: {
                    category,
                    location: ol.proj.toLonLat(view.getCenter()),
                    maxLocations: 25
                  }
                })
    
                .then((response) => {
                  const features = new ol.format.GeoJSON({ featureProjection: view.getProjection() }).readFeatures(response.geoJson);
                  placesLayer.getSource().clear();
                  placesLayer.getSource().addFeatures(features);
                })
    
                .catch((error) => {
                  alert("There was a problem using the geocoder. See the console for details.");
                  console.error(error);
                });
    
            }
    
            document.getElementById("places-select").addEventListener("change", showPlaces);
    
          });
    
        </script>
    
      </body>
    
    </html>

Update the map

A navigation basemap layer is typically used in geocoding and routing applications. Update the basemap layer to use ArcGIS:Navigation.

  1. Update the basemap and the map initialization to center on location [-122.4194,37.7749], San Francisco.

    Change lineChange line
                                                                                                                                           
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
        <title>OpenLayers Tutorials: Find Places</title>
    
        <style>
          html,
          body,
          #map {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 14px;
            color: #323232;
          }
        </style>
    
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" />
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-geocoding@3.0.0/dist/umd/geocoding.umd.js"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script>
    
      </head>
    
      <body>
    
        <div id="map"></div>
    
        <select id="places-select" style="right: 20px; top: 20px; position: absolute; font-size: 16px; padding: 4px 8px;">
          <option value="">Choose a place type...</option>
          <option value="Coffee shop">Coffee shops</option>
          <option value="Gas station">Gas stations</option>
          <option value="Food">Food</option>
          <option value="Hotel">Hotels</option>
          <option value="Parks and Outdoors">Parks and Outdoors</option>
        </select>
    
        <script>
    
          const apiKey = "YOUR-API-KEY";
    
          const map = new ol.Map({
            target: "map"
          });
    
          const view = new ol.View({
    
            center: ol.proj.fromLonLat([-122.4194,37.7749]), // San Francisco
    
            zoom: 14
          });
          map.setView(view);
    
          const basemapId = "ArcGIS:Navigation";
    
          const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey;
    
          olms(map, basemapURL).then(function (map) {
    
            const placesLayer = new ol.layer.Vector({
              source: new ol.source.Vector(),
    
              style: (feature) =>
                new ol.style.Style({
                  image: new ol.style.Circle({
                    radius: 5,
                    fill: new ol.style.Fill({ color: "white" }),
                    stroke: new ol.style.Stroke({ color: "hsl(220, 80%, 40%)", width: 2 })
                  }),
                  text: new ol.style.Text({
                    font: "14px sans-serif",
                    textAlign: "left",
                    text: feature.get("PlaceName"),
                    offsetX: 8, // move text to the right to avoid overlapping circle
                    offsetY: 2, // move down to align with circle's center
                    fill: new ol.style.Fill({ color: "hsl(220, 80%, 40%)" }),
                    stroke: new ol.style.Stroke({ color: "white" })
                  })
                }),
              declutter: true
    
            });
    
            map.addLayer(placesLayer);
    
            function showPlaces() {
    
              const authentication = new arcgisRest.ApiKey({
                key: apiKey
              });
              const category = document.getElementById("places-select").value;
              arcgisRest
                .geocode({
                  authentication,
                  outFields: "Place_addr,PlaceName", // attributes to be returned
    
                  params: {
                    category,
                    location: ol.proj.toLonLat(view.getCenter()),
                    maxLocations: 25
                  }
                })
    
                .then((response) => {
                  const features = new ol.format.GeoJSON({ featureProjection: view.getProjection() }).readFeatures(response.geoJson);
                  placesLayer.getSource().clear();
                  placesLayer.getSource().addFeatures(features);
                })
    
                .catch((error) => {
                  alert("There was a problem using the geocoder. See the console for details.");
                  console.error(error);
                });
    
            }
    
            document.getElementById("places-select").addEventListener("change", showPlaces);
    
          });
    
        </script>
    
      </body>
    
    </html>

Add controls

Use a select element to create the drop-down element. Each category is an option element inside it. The select element needs to have absolute positioning in order to appear in front of the map element.

  1. Add a select control, with options for "Coffee shop", "Gas station", "Food", "Hotel", "Parks and outdoors". Use inline styling to position the control.

    The option values have special meaning to the geocoding service so ensure the spelling is correct. See the ArcGIS REST API documentation for details.

    Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.
                                                                                                                                           
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
        <title>OpenLayers Tutorials: Find Places</title>
    
        <style>
          html,
          body,
          #map {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 14px;
            color: #323232;
          }
        </style>
    
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" />
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-geocoding@3.0.0/dist/umd/geocoding.umd.js"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script>
    
      </head>
    
      <body>
    
        <div id="map"></div>
    
        <select id="places-select" style="right: 20px; top: 20px; position: absolute; font-size: 16px; padding: 4px 8px;">
          <option value="">Choose a place type...</option>
          <option value="Coffee shop">Coffee shops</option>
          <option value="Gas station">Gas stations</option>
          <option value="Food">Food</option>
          <option value="Hotel">Hotels</option>
          <option value="Parks and Outdoors">Parks and Outdoors</option>
        </select>
    
        <script>
    
          const apiKey = "YOUR-API-KEY";
    
          const map = new ol.Map({
            target: "map"
          });
    
          const view = new ol.View({
    
            center: ol.proj.fromLonLat([-122.4194,37.7749]), // San Francisco
    
            zoom: 14
          });
          map.setView(view);
    
          const basemapId = "ArcGIS:Navigation";
    
          const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey;
    
          olms(map, basemapURL).then(function (map) {
    
            const placesLayer = new ol.layer.Vector({
              source: new ol.source.Vector(),
    
              style: (feature) =>
                new ol.style.Style({
                  image: new ol.style.Circle({
                    radius: 5,
                    fill: new ol.style.Fill({ color: "white" }),
                    stroke: new ol.style.Stroke({ color: "hsl(220, 80%, 40%)", width: 2 })
                  }),
                  text: new ol.style.Text({
                    font: "14px sans-serif",
                    textAlign: "left",
                    text: feature.get("PlaceName"),
                    offsetX: 8, // move text to the right to avoid overlapping circle
                    offsetY: 2, // move down to align with circle's center
                    fill: new ol.style.Fill({ color: "hsl(220, 80%, 40%)" }),
                    stroke: new ol.style.Stroke({ color: "white" })
                  })
                }),
              declutter: true
    
            });
    
            map.addLayer(placesLayer);
    
            function showPlaces() {
    
              const authentication = new arcgisRest.ApiKey({
                key: apiKey
              });
              const category = document.getElementById("places-select").value;
              arcgisRest
                .geocode({
                  authentication,
                  outFields: "Place_addr,PlaceName", // attributes to be returned
    
                  params: {
                    category,
                    location: ol.proj.toLonLat(view.getCenter()),
                    maxLocations: 25
                  }
                })
    
                .then((response) => {
                  const features = new ol.format.GeoJSON({ featureProjection: view.getProjection() }).readFeatures(response.geoJson);
                  placesLayer.getSource().clear();
                  placesLayer.getSource().addFeatures(features);
                })
    
                .catch((error) => {
                  alert("There was a problem using the geocoder. See the console for details.");
                  console.error(error);
                });
    
            }
    
            document.getElementById("places-select").addEventListener("change", showPlaces);
    
          });
    
        </script>
    
      </body>
    
    </html>
  2. At the top right, click Run to verify that the select control is created and contains the different categories.

Add a places layer

To display places from the geocoding service on the map, you will add a vector layer, containing a vector source. Small blue circles is the default styling used.

  1. Add a map load handler to the initial olms function call. Inside, create a new vector layer containing a vector source. Store it in a placesLayer, and add it to the map with map.addLayer;

    Add line.Add line.Add line.Add line.Add line.Add line.
                                                                                                                                           
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
        <title>OpenLayers Tutorials: Find Places</title>
    
        <style>
          html,
          body,
          #map {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 14px;
            color: #323232;
          }
        </style>
    
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" />
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-geocoding@3.0.0/dist/umd/geocoding.umd.js"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script>
    
      </head>
    
      <body>
    
        <div id="map"></div>
    
        <select id="places-select" style="right: 20px; top: 20px; position: absolute; font-size: 16px; padding: 4px 8px;">
          <option value="">Choose a place type...</option>
          <option value="Coffee shop">Coffee shops</option>
          <option value="Gas station">Gas stations</option>
          <option value="Food">Food</option>
          <option value="Hotel">Hotels</option>
          <option value="Parks and Outdoors">Parks and Outdoors</option>
        </select>
    
        <script>
    
          const apiKey = "YOUR-API-KEY";
    
          const map = new ol.Map({
            target: "map"
          });
    
          const view = new ol.View({
    
            center: ol.proj.fromLonLat([-122.4194,37.7749]), // San Francisco
    
            zoom: 14
          });
          map.setView(view);
    
          const basemapId = "ArcGIS:Navigation";
    
          const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey;
    
          olms(map, basemapURL).then(function (map) {
    
            const placesLayer = new ol.layer.Vector({
              source: new ol.source.Vector(),
    
              style: (feature) =>
                new ol.style.Style({
                  image: new ol.style.Circle({
                    radius: 5,
                    fill: new ol.style.Fill({ color: "white" }),
                    stroke: new ol.style.Stroke({ color: "hsl(220, 80%, 40%)", width: 2 })
                  }),
                  text: new ol.style.Text({
                    font: "14px sans-serif",
                    textAlign: "left",
                    text: feature.get("PlaceName"),
                    offsetX: 8, // move text to the right to avoid overlapping circle
                    offsetY: 2, // move down to align with circle's center
                    fill: new ol.style.Fill({ color: "hsl(220, 80%, 40%)" }),
                    stroke: new ol.style.Stroke({ color: "white" })
                  })
                }),
              declutter: true
    
            });
    
            map.addLayer(placesLayer);
    
            function showPlaces() {
    
              const authentication = new arcgisRest.ApiKey({
                key: apiKey
              });
              const category = document.getElementById("places-select").value;
              arcgisRest
                .geocode({
                  authentication,
                  outFields: "Place_addr,PlaceName", // attributes to be returned
    
                  params: {
                    category,
                    location: ol.proj.toLonLat(view.getCenter()),
                    maxLocations: 25
                  }
                })
    
                .then((response) => {
                  const features = new ol.format.GeoJSON({ featureProjection: view.getProjection() }).readFeatures(response.geoJson);
                  placesLayer.getSource().clear();
                  placesLayer.getSource().addFeatures(features);
                })
    
                .catch((error) => {
                  alert("There was a problem using the geocoder. See the console for details.");
                  console.error(error);
                });
    
            }
    
            document.getElementById("places-select").addEventListener("change", showPlaces);
    
          });
    
        </script>
    
      </body>
    
    </html>

Call the geocoding service

To find places near a location, you can use the arcgisRest.geocode. Use the center of the map view.getCenter with proj.toLonLat to get the point in longitude and latitude. Provide the category selected by the user using document.getElementById to get the control, then use its value property.

  1. Create a function called showPlaces. Inside, create a new arcgisRest.ApiKey to access the geocoding service. Call arcgisRest.geocode() to set the API key and to call the service endpoint. Pass location and category, and specify Place_addr and PlaceName as the fields to be returned. Request a maximum of 25 places.

    Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.
                                                                                                                                           
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
        <title>OpenLayers Tutorials: Find Places</title>
    
        <style>
          html,
          body,
          #map {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 14px;
            color: #323232;
          }
        </style>
    
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" />
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-geocoding@3.0.0/dist/umd/geocoding.umd.js"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script>
    
      </head>
    
      <body>
    
        <div id="map"></div>
    
        <select id="places-select" style="right: 20px; top: 20px; position: absolute; font-size: 16px; padding: 4px 8px;">
          <option value="">Choose a place type...</option>
          <option value="Coffee shop">Coffee shops</option>
          <option value="Gas station">Gas stations</option>
          <option value="Food">Food</option>
          <option value="Hotel">Hotels</option>
          <option value="Parks and Outdoors">Parks and Outdoors</option>
        </select>
    
        <script>
    
          const apiKey = "YOUR-API-KEY";
    
          const map = new ol.Map({
            target: "map"
          });
    
          const view = new ol.View({
    
            center: ol.proj.fromLonLat([-122.4194,37.7749]), // San Francisco
    
            zoom: 14
          });
          map.setView(view);
    
          const basemapId = "ArcGIS:Navigation";
    
          const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey;
    
          olms(map, basemapURL).then(function (map) {
    
            const placesLayer = new ol.layer.Vector({
              source: new ol.source.Vector(),
    
              style: (feature) =>
                new ol.style.Style({
                  image: new ol.style.Circle({
                    radius: 5,
                    fill: new ol.style.Fill({ color: "white" }),
                    stroke: new ol.style.Stroke({ color: "hsl(220, 80%, 40%)", width: 2 })
                  }),
                  text: new ol.style.Text({
                    font: "14px sans-serif",
                    textAlign: "left",
                    text: feature.get("PlaceName"),
                    offsetX: 8, // move text to the right to avoid overlapping circle
                    offsetY: 2, // move down to align with circle's center
                    fill: new ol.style.Fill({ color: "hsl(220, 80%, 40%)" }),
                    stroke: new ol.style.Stroke({ color: "white" })
                  })
                }),
              declutter: true
    
            });
    
            map.addLayer(placesLayer);
    
            function showPlaces() {
    
              const authentication = new arcgisRest.ApiKey({
                key: apiKey
              });
              const category = document.getElementById("places-select").value;
              arcgisRest
                .geocode({
                  authentication,
                  outFields: "Place_addr,PlaceName", // attributes to be returned
    
                  params: {
                    category,
                    location: ol.proj.toLonLat(view.getCenter()),
                    maxLocations: 25
                  }
                })
    
                .then((response) => {
                  const features = new ol.format.GeoJSON({ featureProjection: view.getProjection() }).readFeatures(response.geoJson);
                  placesLayer.getSource().clear();
                  placesLayer.getSource().addFeatures(features);
                })
    
                .catch((error) => {
                  alert("There was a problem using the geocoder. See the console for details.");
                  console.error(error);
                });
    
            }
    
            document.getElementById("places-select").addEventListener("change", showPlaces);
    
          });
    
        </script>
    
      </body>
    
    </html>

Display results

When the query completes, the geoJson property of the response object contains a GeoJSON feature collection of points. You can use this to update the data of your places source. You will need to use a GeoJSON feature format to read the data, and also reproject it to the map's projection. Use an exception handler to detect problems accessing the service. This could happen due to network disruption or a problem with your API key, for instance.

  1. Add a response handler. Inside, use a new GeoJSON feature format to read the geoJson property and reproject the data. Clear the places source with clear and add the new features with addFeatures

    Add line.Add line.Add line.Add line.Add line.
                                                                                                                                           
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
        <title>OpenLayers Tutorials: Find Places</title>
    
        <style>
          html,
          body,
          #map {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 14px;
            color: #323232;
          }
        </style>
    
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" />
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-geocoding@3.0.0/dist/umd/geocoding.umd.js"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script>
    
      </head>
    
      <body>
    
        <div id="map"></div>
    
        <select id="places-select" style="right: 20px; top: 20px; position: absolute; font-size: 16px; padding: 4px 8px;">
          <option value="">Choose a place type...</option>
          <option value="Coffee shop">Coffee shops</option>
          <option value="Gas station">Gas stations</option>
          <option value="Food">Food</option>
          <option value="Hotel">Hotels</option>
          <option value="Parks and Outdoors">Parks and Outdoors</option>
        </select>
    
        <script>
    
          const apiKey = "YOUR-API-KEY";
    
          const map = new ol.Map({
            target: "map"
          });
    
          const view = new ol.View({
    
            center: ol.proj.fromLonLat([-122.4194,37.7749]), // San Francisco
    
            zoom: 14
          });
          map.setView(view);
    
          const basemapId = "ArcGIS:Navigation";
    
          const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey;
    
          olms(map, basemapURL).then(function (map) {
    
            const placesLayer = new ol.layer.Vector({
              source: new ol.source.Vector(),
    
              style: (feature) =>
                new ol.style.Style({
                  image: new ol.style.Circle({
                    radius: 5,
                    fill: new ol.style.Fill({ color: "white" }),
                    stroke: new ol.style.Stroke({ color: "hsl(220, 80%, 40%)", width: 2 })
                  }),
                  text: new ol.style.Text({
                    font: "14px sans-serif",
                    textAlign: "left",
                    text: feature.get("PlaceName"),
                    offsetX: 8, // move text to the right to avoid overlapping circle
                    offsetY: 2, // move down to align with circle's center
                    fill: new ol.style.Fill({ color: "hsl(220, 80%, 40%)" }),
                    stroke: new ol.style.Stroke({ color: "white" })
                  })
                }),
              declutter: true
    
            });
    
            map.addLayer(placesLayer);
    
            function showPlaces() {
    
              const authentication = new arcgisRest.ApiKey({
                key: apiKey
              });
              const category = document.getElementById("places-select").value;
              arcgisRest
                .geocode({
                  authentication,
                  outFields: "Place_addr,PlaceName", // attributes to be returned
    
                  params: {
                    category,
                    location: ol.proj.toLonLat(view.getCenter()),
                    maxLocations: 25
                  }
                })
    
                .then((response) => {
                  const features = new ol.format.GeoJSON({ featureProjection: view.getProjection() }).readFeatures(response.geoJson);
                  placesLayer.getSource().clear();
                  placesLayer.getSource().addFeatures(features);
                })
    
                .catch((error) => {
                  alert("There was a problem using the geocoder. See the console for details.");
                  console.error(error);
                });
    
            }
    
            document.getElementById("places-select").addEventListener("change", showPlaces);
    
          });
    
        </script>
    
      </body>
    
    </html>
  2. If there is an exception accessing the geocoding service, alert the user and log the error.

    Add line.Add line.Add line.Add line.
                                                                                                                                           
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
        <title>OpenLayers Tutorials: Find Places</title>
    
        <style>
          html,
          body,
          #map {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 14px;
            color: #323232;
          }
        </style>
    
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" />
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-geocoding@3.0.0/dist/umd/geocoding.umd.js"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script>
    
      </head>
    
      <body>
    
        <div id="map"></div>
    
        <select id="places-select" style="right: 20px; top: 20px; position: absolute; font-size: 16px; padding: 4px 8px;">
          <option value="">Choose a place type...</option>
          <option value="Coffee shop">Coffee shops</option>
          <option value="Gas station">Gas stations</option>
          <option value="Food">Food</option>
          <option value="Hotel">Hotels</option>
          <option value="Parks and Outdoors">Parks and Outdoors</option>
        </select>
    
        <script>
    
          const apiKey = "YOUR-API-KEY";
    
          const map = new ol.Map({
            target: "map"
          });
    
          const view = new ol.View({
    
            center: ol.proj.fromLonLat([-122.4194,37.7749]), // San Francisco
    
            zoom: 14
          });
          map.setView(view);
    
          const basemapId = "ArcGIS:Navigation";
    
          const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey;
    
          olms(map, basemapURL).then(function (map) {
    
            const placesLayer = new ol.layer.Vector({
              source: new ol.source.Vector(),
    
              style: (feature) =>
                new ol.style.Style({
                  image: new ol.style.Circle({
                    radius: 5,
                    fill: new ol.style.Fill({ color: "white" }),
                    stroke: new ol.style.Stroke({ color: "hsl(220, 80%, 40%)", width: 2 })
                  }),
                  text: new ol.style.Text({
                    font: "14px sans-serif",
                    textAlign: "left",
                    text: feature.get("PlaceName"),
                    offsetX: 8, // move text to the right to avoid overlapping circle
                    offsetY: 2, // move down to align with circle's center
                    fill: new ol.style.Fill({ color: "hsl(220, 80%, 40%)" }),
                    stroke: new ol.style.Stroke({ color: "white" })
                  })
                }),
              declutter: true
    
            });
    
            map.addLayer(placesLayer);
    
            function showPlaces() {
    
              const authentication = new arcgisRest.ApiKey({
                key: apiKey
              });
              const category = document.getElementById("places-select").value;
              arcgisRest
                .geocode({
                  authentication,
                  outFields: "Place_addr,PlaceName", // attributes to be returned
    
                  params: {
                    category,
                    location: ol.proj.toLonLat(view.getCenter()),
                    maxLocations: 25
                  }
                })
    
                .then((response) => {
                  const features = new ol.format.GeoJSON({ featureProjection: view.getProjection() }).readFeatures(response.geoJson);
                  placesLayer.getSource().clear();
                  placesLayer.getSource().addFeatures(features);
                })
    
                .catch((error) => {
                  alert("There was a problem using the geocoder. See the console for details.");
                  console.error(error);
                });
    
            }
    
            document.getElementById("places-select").addEventListener("change", showPlaces);
    
          });
    
        </script>
    
      </body>
    
    </html>

Add a change event handler

To update the map when the user chooses a category, you must add an event handler for the change event on the <select> control.

  1. After the map initialization code, add showPlaces as the change event handler to the <select> control.

    Add line.
                                                                                                                                           
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
        <title>OpenLayers Tutorials: Find Places</title>
    
        <style>
          html,
          body,
          #map {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 14px;
            color: #323232;
          }
        </style>
    
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" />
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-geocoding@3.0.0/dist/umd/geocoding.umd.js"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script>
    
      </head>
    
      <body>
    
        <div id="map"></div>
    
        <select id="places-select" style="right: 20px; top: 20px; position: absolute; font-size: 16px; padding: 4px 8px;">
          <option value="">Choose a place type...</option>
          <option value="Coffee shop">Coffee shops</option>
          <option value="Gas station">Gas stations</option>
          <option value="Food">Food</option>
          <option value="Hotel">Hotels</option>
          <option value="Parks and Outdoors">Parks and Outdoors</option>
        </select>
    
        <script>
    
          const apiKey = "YOUR-API-KEY";
    
          const map = new ol.Map({
            target: "map"
          });
    
          const view = new ol.View({
    
            center: ol.proj.fromLonLat([-122.4194,37.7749]), // San Francisco
    
            zoom: 14
          });
          map.setView(view);
    
          const basemapId = "ArcGIS:Navigation";
    
          const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey;
    
          olms(map, basemapURL).then(function (map) {
    
            const placesLayer = new ol.layer.Vector({
              source: new ol.source.Vector(),
    
              style: (feature) =>
                new ol.style.Style({
                  image: new ol.style.Circle({
                    radius: 5,
                    fill: new ol.style.Fill({ color: "white" }),
                    stroke: new ol.style.Stroke({ color: "hsl(220, 80%, 40%)", width: 2 })
                  }),
                  text: new ol.style.Text({
                    font: "14px sans-serif",
                    textAlign: "left",
                    text: feature.get("PlaceName"),
                    offsetX: 8, // move text to the right to avoid overlapping circle
                    offsetY: 2, // move down to align with circle's center
                    fill: new ol.style.Fill({ color: "hsl(220, 80%, 40%)" }),
                    stroke: new ol.style.Stroke({ color: "white" })
                  })
                }),
              declutter: true
    
            });
    
            map.addLayer(placesLayer);
    
            function showPlaces() {
    
              const authentication = new arcgisRest.ApiKey({
                key: apiKey
              });
              const category = document.getElementById("places-select").value;
              arcgisRest
                .geocode({
                  authentication,
                  outFields: "Place_addr,PlaceName", // attributes to be returned
    
                  params: {
                    category,
                    location: ol.proj.toLonLat(view.getCenter()),
                    maxLocations: 25
                  }
                })
    
                .then((response) => {
                  const features = new ol.format.GeoJSON({ featureProjection: view.getProjection() }).readFeatures(response.geoJson);
                  placesLayer.getSource().clear();
                  placesLayer.getSource().addFeatures(features);
                })
    
                .catch((error) => {
                  alert("There was a problem using the geocoder. See the console for details.");
                  console.error(error);
                });
    
            }
    
            document.getElementById("places-select").addEventListener("change", showPlaces);
    
          });
    
        </script>
    
      </body>
    
    </html>
  2. At the top right, click Run. When you choose a place category, circles should be shown for places.

Display labels

In order to show the name of each place on the map, you will modify the layer definition to include a style property. You provide a function that takes a feature and returns a Style. It will include a Text style to display the labels, using the text property to determine which is text is displayed. Use the PlaceName property of the feature for this. You will also set properties such as textAlign and font to control the appearance of the labels. The style will also include a Circle style to draw a circle at the place location.

By default, the labels would overlap each other and be hard to read. You use the declutter property on the Vector layer to prevent this.

  1. Add a style property to the placesLayer definition. Make this function return a new Style which includes a Circle style and a Text style for the image and text properties. Enable the declutter setting.

    Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.
                                                                                                                                           
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
        <title>OpenLayers Tutorials: Find Places</title>
    
        <style>
          html,
          body,
          #map {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 14px;
            color: #323232;
          }
        </style>
    
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" type="text/css" />
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/ol-mapbox-style@6.1.4/dist/olms.js" type="text/javascript"></script>
        <script src="https://unpkg.com/@esri/arcgis-rest-request@3.0.0/dist/umd/request.umd.js"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-geocoding@3.0.0/dist/umd/geocoding.umd.js"></script>
    
        <script src="https://unpkg.com/@esri/arcgis-rest-auth@3.0.0/dist/umd/auth.umd.js"></script>
    
      </head>
    
      <body>
    
        <div id="map"></div>
    
        <select id="places-select" style="right: 20px; top: 20px; position: absolute; font-size: 16px; padding: 4px 8px;">
          <option value="">Choose a place type...</option>
          <option value="Coffee shop">Coffee shops</option>
          <option value="Gas station">Gas stations</option>
          <option value="Food">Food</option>
          <option value="Hotel">Hotels</option>
          <option value="Parks and Outdoors">Parks and Outdoors</option>
        </select>
    
        <script>
    
          const apiKey = "YOUR-API-KEY";
    
          const map = new ol.Map({
            target: "map"
          });
    
          const view = new ol.View({
    
            center: ol.proj.fromLonLat([-122.4194,37.7749]), // San Francisco
    
            zoom: 14
          });
          map.setView(view);
    
          const basemapId = "ArcGIS:Navigation";
    
          const basemapURL = "https://basemaps-api.arcgis.com/arcgis/rest/services/styles/" + basemapId + "?type=style&apiKey=" + apiKey;
    
          olms(map, basemapURL).then(function (map) {
    
            const placesLayer = new ol.layer.Vector({
              source: new ol.source.Vector(),
    
              style: (feature) =>
                new ol.style.Style({
                  image: new ol.style.Circle({
                    radius: 5,
                    fill: new ol.style.Fill({ color: "white" }),
                    stroke: new ol.style.Stroke({ color: "hsl(220, 80%, 40%)", width: 2 })
                  }),
                  text: new ol.style.Text({
                    font: "14px sans-serif",
                    textAlign: "left",
                    text: feature.get("PlaceName"),
                    offsetX: 8, // move text to the right to avoid overlapping circle
                    offsetY: 2, // move down to align with circle's center
                    fill: new ol.style.Fill({ color: "hsl(220, 80%, 40%)" }),
                    stroke: new ol.style.Stroke({ color: "white" })
                  })
                }),
              declutter: true
    
            });
    
            map.addLayer(placesLayer);
    
            function showPlaces() {
    
              const authentication = new arcgisRest.ApiKey({
                key: apiKey
              });
              const category = document.getElementById("places-select").value;
              arcgisRest
                .geocode({
                  authentication,
                  outFields: "Place_addr,PlaceName", // attributes to be returned
    
                  params: {
                    category,
                    location: ol.proj.toLonLat(view.getCenter()),
                    maxLocations: 25
                  }
                })
    
                .then((response) => {
                  const features = new ol.format.GeoJSON({ featureProjection: view.getProjection() }).readFeatures(response.geoJson);
                  placesLayer.getSource().clear();
                  placesLayer.getSource().addFeatures(features);
                })
    
                .catch((error) => {
                  alert("There was a problem using the geocoder. See the console for details.");
                  console.error(error);
                });
    
            }
    
            document.getElementById("places-select").addEventListener("change", showPlaces);
    
          });
    
        </script>
    
      </body>
    
    </html>

Run the app

In CodePen, run your code to display the map.

When you choose a place category, you should see the name of each place shown as a label, next to a white circle with a blue outline.

What's next?

Learn how to use additional ArcGIS location services in these tutorials: