Place Autocomplete Data API

  • The Place Autocomplete Data API allows you to fetch place predictions for autocomplete experiences, even without a map (but if a map is used, it must be a Google Map).

  • You can constrain predictions by location, area, and place type using parameters like locationRestriction, origin, and includedPrimaryTypes.

  • Obtaining detailed information about a place requires calling toPlace() on a prediction, followed by fetchFields() on the resulting Place object to get details like name and address.

  • Session tokens are essential for managing billing; they group related queries and selections into a single billable request, and should be generated uniquely for each user session.

  • Billing is based on queries and selections within a session, with selections incurring a charge for Place data while queries are generally free unless no selection is made within a few minutes.

European Economic Area (EEA) developers

The Place Autocomplete Data API lets you fetch place predictions programmatically, to create customized autocomplete experiences with a finer degree of control than is possible with the autocomplete widget. In this guide you will learn how to use the Place Autocomplete Data API to make autocomplete requests based on user queries.

The following example shows a simplified type-ahead integration. Enter your search query, such as "pizza" or "poke", then click to select the result you want.

Autocomplete requests

An autocomplete request takes a query input string and returns a list of place predictions. To make an autocomplete request, call fetchAutocompleteSuggestions() and pass a request with the needed properties. The input property contains the string to search; in a typical application this value would be updated as the user types a query. The request should include a sessionToken, which is used for billing purposes.

The following snippet shows creating a request body and adding a session token, then calling fetchAutocompleteSuggestions() to get a list of PlacePredictions.

// Add an initial request body.
let request = {
    input: 'Tadi',
    locationRestriction: {
        west: -122.44,
        north: 37.8,
        east: -122.39,
        south: 37.78,
    },
    origin: { lat: 37.7893, lng: -122.4039 },
    includedPrimaryTypes: ['restaurant'],
    language: 'en-US',
    region: 'us',
};
// Create a session token.
const token = new AutocompleteSessionToken();
// Add the token to the request.
// @ts-ignore
request.sessionToken = token;

Constrain Autocomplete predictions

By default, Place Autocomplete presents all place types, biased for predictions near the user's location, and fetches all available data fields for the user's selected place. Set Place Autocomplete options to present more relevant predictions, by restricting or biasing results.

Restricting results causes the Autocomplete widget to ignore any results that are outside of the restriction area. A common practice is to restrict results to the map bounds. Biasing results makes the Autocomplete widget show results within the specified area, but some matches may be outside of that area.

Use the origin property to specify the origin point from which to calculate geodesic distance to the destination. If this value is omitted, distance is not returned.

Use the includedPrimaryTypes property to specify up to five place types. If no types are specified, places of all types will be returned.

See the API reference

Get place details

To return a Place object from a place prediction result, first call toPlace(), then call fetchFields() on the resulting Place object (the session ID from the place prediction is automatically included). Calling fetchFields() ends the autocomplete session.

let place = suggestions[0].placePrediction.toPlace(); // Get first predicted place.
await place.fetchFields({
    fields: ['displayName', 'formattedAddress'],
});
const placeInfo = document.getElementById('prediction');
placeInfo.textContent = `First predicted place: ${place.displayName}: ${place.formattedAddress}`;

Session tokens

Session tokens group the query and selection phases of a user autocomplete search into a discrete session for billing purposes. The session begins when the user starts typing. The session is concluded when the user selects a place and a call to Place Details is made.

To create a new session token and add it to a request, create an instance of AutocompleteSessionToken, then set the sessionToken property of the request to use the tokens as shown in the following snippet:

// Create a session token.
const token = new AutocompleteSessionToken();
// Add the token to the request.
// @ts-ignore
request.sessionToken = token;

A session is concluded when fetchFields() is called. After creating the Place instance, you don't need to pass the session token to fetchFields() as this is handled automatically.

await place.fetchFields({
    fields: ['displayName', 'formattedAddress'],
});

Make a session token for the next session by creating a new instance of AutocompleteSessionToken.

Session token recommendations:

  • Use session tokens for all Place Autocomplete calls.
  • Generate a fresh token for each session.
  • Pass a unique session token for each new session. Using the same token for more than one session will result in each request being billed individually.

You can optionally omit the autocomplete session token from a request. If the session token is omitted, each request is billed separately, triggering the Autocomplete - Per Request SKU. If you reuse a session token, the session is considered invalid and the requests are charged as if no session token was provided.

Example

As the user types a query, an autocomplete request is called every few keystrokes (not per-character), and a list of possible results is returned. When the user makes a selection from the result list, the selection counts as a request, and all of the requests made during the search are bundled and counted as a single request. If the user selects a place, the search query is available at no charge, and only the Place data request is charged. If the user does not make a selection within a few minutes of the beginning of the session, only the search query is charged.

From the perspective of an app, the flow of events goes like this:

  1. A user begins typing a query to search for "Paris, France".
  2. Upon detecting user input, the app creates a new session token, "Token A".
  3. As the user types, the API makes an autocomplete request every few characters, displaying a new list of potential results for each:
    "P"
    "Par"
    "Paris,"
    "Paris, Fr"
  4. When the user makes a selection:
    • All requests resulting from the query are grouped and added to the session represented by "Token A", as a single request.
    • The user's selection is counted as a Place Detail request, and added to the session represented by "Token A".
  5. The session is concluded, and the app discards "Token A".
Learn about how sessions are billed

Complete example code

This section contains complete examples showing how to use the Place Autocomplete Data API .

Place autocomplete predictions

The following example demonstrates calling fetchAutocompleteSuggestions() for the input "Tadi", then calling toPlace() on the first prediction result, followed by a call to fetchFields() to get place details.

TypeScript

async function init() {
    const { Place, AutocompleteSessionToken, AutocompleteSuggestion } =
        (await google.maps.importLibrary(
            'places'
        )) as google.maps.PlacesLibrary;

    // Add an initial request body.
    let request = {
        input: 'Tadi',
        locationRestriction: {
            west: -122.44,
            north: 37.8,
            east: -122.39,
            south: 37.78,
        },
        origin: { lat: 37.7893, lng: -122.4039 },
        includedPrimaryTypes: ['restaurant'],
        language: 'en-US',
        region: 'us',
    };

    // Create a session token.
    const token = new AutocompleteSessionToken();
    // Add the token to the request.
    // @ts-ignore
    request.sessionToken = token;
    // Fetch autocomplete suggestions.
    const { suggestions } =
        await AutocompleteSuggestion.fetchAutocompleteSuggestions(request);

    const title = document.getElementById('title') as HTMLElement;
    title.appendChild(
        document.createTextNode(
            'Query predictions for "' + request.input + '":'
        )
    );

    const resultsElement = document.getElementById('results') as HTMLElement;

    for (let suggestion of suggestions) {
        const placePrediction = suggestion.placePrediction;

        // Create a new list element.
        const listItem = document.createElement('li');

        listItem.appendChild(
            document.createTextNode(placePrediction!.text.toString())
        );
        resultsElement.appendChild(listItem);
    }

    let place = suggestions[0].placePrediction!.toPlace(); // Get first predicted place.
    await place.fetchFields({
        fields: ['displayName', 'formattedAddress'],
    });

    const placeInfo = document.getElementById('prediction') as HTMLElement;
    placeInfo.textContent = `First predicted place: ${place.displayName}: ${place.formattedAddress}`;
}

init();

JavaScript

async function init() {
    const { Place, AutocompleteSessionToken, AutocompleteSuggestion } = (await google.maps.importLibrary('places'));
    // Add an initial request body.
    let request = {
        input: 'Tadi',
        locationRestriction: {
            west: -122.44,
            north: 37.8,
            east: -122.39,
            south: 37.78,
        },
        origin: { lat: 37.7893, lng: -122.4039 },
        includedPrimaryTypes: ['restaurant'],
        language: 'en-US',
        region: 'us',
    };
    // Create a session token.
    const token = new AutocompleteSessionToken();
    // Add the token to the request.
    // @ts-ignore
    request.sessionToken = token;
    // Fetch autocomplete suggestions.
    const { suggestions } = await AutocompleteSuggestion.fetchAutocompleteSuggestions(request);
    const title = document.getElementById('title');
    title.appendChild(document.createTextNode('Query predictions for "' + request.input + '":'));
    const resultsElement = document.getElementById('results');
    for (let suggestion of suggestions) {
        const placePrediction = suggestion.placePrediction;
        // Create a new list element.
        const listItem = document.createElement('li');
        listItem.appendChild(document.createTextNode(placePrediction.text.toString()));
        resultsElement.appendChild(listItem);
    }
    let place = suggestions[0].placePrediction.toPlace(); // Get first predicted place.
    await place.fetchFields({
        fields: ['displayName', 'formattedAddress'],
    });
    const placeInfo = document.getElementById('prediction');
    placeInfo.textContent = `First predicted place: ${place.displayName}: ${place.formattedAddress}`;
}
init();

CSS

/* 
 * Always set the map height explicitly to define the size of the div element
 * that contains the map. 
 */
#map {
    height: 100%;
}

/* 
 * Optional: Makes the sample page fill the window. 
 */
html,
body {
    height: 100%;
    margin: 0;
    padding: 0;
}

HTML

<html>
    <head>
        <title>Place Autocomplete Data API Predictions</title>

        <link rel="stylesheet" type="text/css" href="https://developers.google.com/style.css" />
        <script type="module" src="https://developers.google.com/index.js"></script>
        <!-- prettier-ignore -->
        <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: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "weekly"});</script>
    </head>
    <body>
        <div id="title"></div>
        <ul id="results"></ul>
        <p><span id="prediction"></span></p>
        <img
            class="powered-by-google"
            src="https://developers.google.com/powered_by_google_on_white.png"
            alt="Powered by Google" />
    </body>
</html>

Try Sample

Place autocomplete type-ahead with sessions

This example demonstrates the following concepts:

  • Calling fetchAutocompleteSuggestions() based on user queries and showing a list of predicted places in response.
  • Using session tokens to group a user query with the final Place Details request.
  • Retrieving place details for the selected place and displaying a marker.
  • Using control slotting to nest UI elements in the gmp-map element.

TypeScript

const mapElement = document.querySelector('gmp-map') as google.maps.MapElement;
let innerMap: google.maps.Map;
let marker: google.maps.marker.AdvancedMarkerElement;
let titleElement = document.querySelector('.title') as HTMLElement;
let resultsContainerElement = document.querySelector('.results') as HTMLElement;
let inputElement = document.querySelector('input') as HTMLInputElement;
let tokenStatusElement = document.querySelector('.token-status') as HTMLElement;
let newestRequestId = 0;
let tokenCount = 0;

// Create an initial request body.
const request: google.maps.places.AutocompleteRequest = {
    input: '',
    includedPrimaryTypes: [
        'restaurant',
        'cafe',
        'museum',
        'park',
        'botanical_garden',
    ],
};

async function init() {
    await google.maps.importLibrary('maps');
    innerMap = mapElement.innerMap;
    innerMap.setOptions({
        mapTypeControl: false,
    });

    // Update request center and bounds when the map bounds change.
    google.maps.event.addListener(innerMap, 'bounds_changed', async () => {
        request.locationRestriction = innerMap.getBounds();
        request.origin = innerMap.getCenter();
    });

    inputElement.addEventListener('input', makeAutocompleteRequest);
}

async function makeAutocompleteRequest(inputEvent) {
    // To avoid race conditions, store the request ID and compare after the request.
    const requestId = ++newestRequestId;

    const { AutocompleteSuggestion } = (await google.maps.importLibrary(
        'places'
    )) as google.maps.PlacesLibrary;

    if (!inputEvent.target?.value) {
        titleElement.textContent = '';
        resultsContainerElement.replaceChildren();
        return;
    }

    // Add the latest char sequence to the request.
    request.input = (inputEvent.target as HTMLInputElement).value;

    // Fetch autocomplete suggestions and show them in a list.
    const { suggestions } =
        await AutocompleteSuggestion.fetchAutocompleteSuggestions(request);

    // If the request has been superseded by a newer request, do not render the output.
    if (requestId !== newestRequestId) return;

    titleElement.innerText = `Place predictions for "${request.input}"`;

    // Clear the list first.
    resultsContainerElement.replaceChildren();

    for (const suggestion of suggestions) {
        const placePrediction = suggestion.placePrediction;

        if (!placePrediction) {
            continue;
        }

        // Create a link for the place, add an event handler to fetch the place.
        // We are using a button element to take advantage of its a11y capabilities.
        const placeButton = document.createElement('button');
        placeButton.addEventListener('click', () => {
            onPlaceSelected(placePrediction.toPlace());
        });
        placeButton.textContent = placePrediction.text.toString();
        placeButton.classList.add('place-button');

        // Create a new list item element.
        const li = document.createElement('li');
        li.appendChild(placeButton);
        resultsContainerElement.appendChild(li);
    }
}

// Event handler for clicking on a suggested place.
async function onPlaceSelected(place: google.maps.places.Place) {
    const { AdvancedMarkerElement } = (await google.maps.importLibrary(
        'marker'
    )) as google.maps.MarkerLibrary;

    await place.fetchFields({
        fields: ['displayName', 'formattedAddress', 'location'],
    });

    resultsContainerElement.textContent = `${place.displayName}: ${place.formattedAddress}`;
    titleElement.textContent = 'Selected Place:';
    inputElement.value = '';

    await refreshToken();

    // Remove the previous marker, if it exists.
    if (marker) {
        marker.remove();
    }

    // Create a new marker.
    marker = new AdvancedMarkerElement({
        map: innerMap,
        position: place.location,
        title: place.displayName,
    });

    // Center the map on the selected place.
    if (place.location) {
        innerMap.setCenter(place.location);
        innerMap.setZoom(15);
    }
}

// Helper function to refresh the session token.
async function refreshToken() {
    const { AutocompleteSessionToken } = (await google.maps.importLibrary(
        'places'
    )) as google.maps.PlacesLibrary;

    // Increment the token counter.
    tokenCount++;

    // Create a new session token and add it to the request.
    request.sessionToken = new AutocompleteSessionToken();
    tokenStatusElement.textContent = `Session token count: ${tokenCount}`;
}

init();

JavaScript

const mapElement = document.querySelector('gmp-map');
let innerMap;
let marker;
let titleElement = document.querySelector('.title');
let resultsContainerElement = document.querySelector('.results');
let inputElement = document.querySelector('input');
let tokenStatusElement = document.querySelector('.token-status');
let newestRequestId = 0;
let tokenCount = 0;
// Create an initial request body.
const request = {
    input: '',
    includedPrimaryTypes: [
        'restaurant',
        'cafe',
        'museum',
        'park',
        'botanical_garden',
    ],
};
async function init() {
    await google.maps.importLibrary('maps');
    innerMap = mapElement.innerMap;
    innerMap.setOptions({
        mapTypeControl: false,
    });
    // Update request center and bounds when the map bounds change.
    google.maps.event.addListener(innerMap, 'bounds_changed', async () => {
        request.locationRestriction = innerMap.getBounds();
        request.origin = innerMap.getCenter();
    });
    inputElement.addEventListener('input', makeAutocompleteRequest);
}
async function makeAutocompleteRequest(inputEvent) {
    // To avoid race conditions, store the request ID and compare after the request.
    const requestId = ++newestRequestId;
    const { AutocompleteSuggestion } = (await google.maps.importLibrary('places'));
    if (!inputEvent.target?.value) {
        titleElement.textContent = '';
        resultsContainerElement.replaceChildren();
        return;
    }
    // Add the latest char sequence to the request.
    request.input = inputEvent.target.value;
    // Fetch autocomplete suggestions and show them in a list.
    const { suggestions } = await AutocompleteSuggestion.fetchAutocompleteSuggestions(request);
    // If the request has been superseded by a newer request, do not render the output.
    if (requestId !== newestRequestId)
        return;
    titleElement.innerText = `Place predictions for "${request.input}"`;
    // Clear the list first.
    resultsContainerElement.replaceChildren();
    for (const suggestion of suggestions) {
        const placePrediction = suggestion.placePrediction;
        if (!placePrediction) {
            continue;
        }
        // Create a link for the place, add an event handler to fetch the place.
        // We are using a button element to take advantage of its a11y capabilities.
        const placeButton = document.createElement('button');
        placeButton.addEventListener('click', () => {
            onPlaceSelected(placePrediction.toPlace());
        });
        placeButton.textContent = placePrediction.text.toString();
        placeButton.classList.add('place-button');
        // Create a new list item element.
        const li = document.createElement('li');
        li.appendChild(placeButton);
        resultsContainerElement.appendChild(li);
    }
}
// Event handler for clicking on a suggested place.
async function onPlaceSelected(place) {
    const { AdvancedMarkerElement } = (await google.maps.importLibrary('marker'));
    await place.fetchFields({
        fields: ['displayName', 'formattedAddress', 'location'],
    });
    resultsContainerElement.textContent = `${place.displayName}: ${place.formattedAddress}`;
    titleElement.textContent = 'Selected Place:';
    inputElement.value = '';
    await refreshToken();
    // Remove the previous marker, if it exists.
    if (marker) {
        marker.remove();
    }
    // Create a new marker.
    marker = new AdvancedMarkerElement({
        map: innerMap,
        position: place.location,
        title: place.displayName,
    });
    // Center the map on the selected place.
    if (place.location) {
        innerMap.setCenter(place.location);
        innerMap.setZoom(15);
    }
}
// Helper function to refresh the session token.
async function refreshToken() {
    const { AutocompleteSessionToken } = (await google.maps.importLibrary('places'));
    // Increment the token counter.
    tokenCount++;
    // Create a new session token and add it to the request.
    request.sessionToken = new AutocompleteSessionToken();
    tokenStatusElement.textContent = `Session token count: ${tokenCount}`;
}
init();

CSS

/* 
 * Always set the map height explicitly to define the size of the div element
 * that contains the map. 
 */
gmp-map {
    height: 100%;
}

/* 
 * Optional: Makes the sample page fill the window. 
 */
html,
body {
    height: 100%;
    margin: 0;
    padding: 0;
}

.place-button {
    height: 3rem;
    width: 100%;
    background-color: transparent;
    text-align: left;
    border: none;
    cursor: pointer;
}

.place-button:focus-visible {
    outline: 2px solid #0056b3;
    border-radius: 2px;
}

.input {
    width: 300px;
    font-size: small;
    margin-bottom: 1rem;
}

/* Styles for the floating panel */
.controls {
    background-color: #fff;
    border-radius: 8px;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
    font-family: sans-serif;
    font-size: small;
    margin: 12px;
    padding: 1rem;
}

.title {
    font-weight: bold;
    margin-top: 1rem;
    margin-bottom: 0.5rem;
}

.results {
    list-style-type: none;
    margin: 0;
    padding: 0;
}

.results li:not(:last-child) {
    border-bottom: 1px solid #ddd;
}

.results li:hover {
    background-color: #eee;
}

HTML

<html>
    <head>
        <title>Place Autocomplete Data API Session</title>

        <link rel="stylesheet" type="text/css" href="https://developers.google.com/style.css" />
        <script type="module" src="https://developers.google.com/index.js"></script>
        <!-- prettier-ignore -->
        <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: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "weekly"});</script>
    </head>
    <body>
        <gmp-map center="37.7893, -122.4039" zoom="12" map-id="DEMO_MAP_ID">
            <div class="controls" slot="control-inline-start-block-start">
                <input
                    type="text"
                    class="input"
                    placeholder="Search for a place..."
                    autocomplete="off" /><!-- Turn off the input's own autocomplete (not supported by all browsers).-->
                <div class="token-status"></div>
                <div class="title"></div>
                <ol class="results"></ol>
            </div>
        </gmp-map>
    </body>
</html>

Try Sample

Autocomplete (New) optimization

This section describes best practices to help you make the most of the Autocomplete (New) service.

Here are some general guidelines:

  • The quickest way to develop a working user interface is to use the Maps JavaScript API Autocomplete (New) widget, Places SDK for Android Autocomplete (New) widget, or Places SDK for iOS Autocomplete (New) widget.
  • Understand essential Autocomplete (New) data fields from the start.
  • Location biasing and location restriction fields are optional but can have a significant impact on autocomplete performance.
  • Use error handling to make sure your app degrades gracefully if the API returns an error.
  • Make sure your app handles when there is no selection and offers users a way to continue.

Cost optimization best practices

Basic cost optimization

To optimize the cost of using the Autocomplete (New) service, use field masks in Place Details (New) and Autocomplete (New) widgets to return only the Autocomplete (New) data fields you need.

Advanced cost optimization

Consider programmatic implementation of Autocomplete (New) in order to access SKU: Autocomplete Request pricing and request Geocoding API results about the selected place instead of Place Details (New). Per-request pricing paired with Geocoding API is more cost-effective than per-session (session-based) pricing if both of the following conditions are met:

  • If you only need the latitude/longitude or address of the user's selected place, the Geocoding API delivers this information for less than a Place Details (New) call.
  • If users select an autocomplete prediction within an average of four Autocomplete (New) predictions requests or fewer, per-request pricing may be more cost-effective than per-session pricing.
For help selecting the Autocomplete (New) implementation that fits your needs, select the tab that corresponds to your answer to the following question.

Does your application require any information other than the address and latitude/longitude of the selected prediction?

Yes, needs more details

Use session-based Autocomplete (New) with Place Details (New).
Since your application requires Place Details (New), such as the place name, business status, or opening hours, your implementation of Autocomplete (New) should use a session token (programmatically or built into the JavaScript, Android, or iOS widgets) per session plus applicable Places SKUs, depending on which place data fields you request.1

Widget implementation
Session management is automatically built into the JavaScript, Android, or iOS widgets. This includes both the Autocomplete (New) requests and the Place Details (New) request on the selected prediction. Be sure to specify the fields parameter in order to ensure you are only requesting the Autocomplete (New) data fields you need.

Programmatic implementation
Use a session token with your Autocomplete (New) requests. When requesting Place Details (New) about the selected prediction, include the following parameters:

  1. The place ID from the Autocomplete (New) response
  2. The session token used in the Autocomplete (New) request
  3. The fields parameter specifying the Autocomplete (New) data fields you need

No, needs only address and location

Geocoding API could be a more cost-effective option than Place Details (New) for your application, depending on the performance of your Autocomplete (New) usage. Every application's Autocomplete (New) efficiency varies depending on what users are entering, where the application is being used, and whether performance optimization best practices have been implemented.

In order to answer the following question, analyze how many characters a user types on average before selecting a Autocomplete (New) prediction in your application.

Do your users select a Autocomplete (New) prediction in four or fewer requests, on average?

Yes

Implement Autocomplete (New) programmatically without session tokens and call Geocoding API on the selected place prediction.
Geocoding API delivers addresses and latitude/longitude coordinates. Making four Autocomplete Requests requests plus a Geocoding API call about the selected place prediction is less than the per-session Autocomplete (New) cost per session.1

Consider employing performance best practices to help your users get the prediction they're looking for in even fewer characters.

No

Use session-based Autocomplete (New) with Place Details (New).
Since the average number of requests you expect to make before a user selects a Autocomplete (New) prediction exceeds the cost of per-session pricing, your implementation of Autocomplete (New) should use a session token for both the Autocomplete (New) requests and the associated Place Details (New) request per session. 1

Widget implementation
Session management is automatically built into the JavaScript, Android, or iOS widgets. This includes both the Autocomplete (New) requests and the Place Details (New) request on the selected prediction. Be sure to specify the fields parameter in order to ensure you are only requesting the fields you need.

Programmatic implementation
Use a session token with your Autocomplete (New) requests. When requesting Place Details (New) about the selected prediction, include the following parameters:

  1. The place ID from the Autocomplete (New) response
  2. The session token used in the Autocomplete (New) request
  3. The fields parameter specifying fields such as address and geometry

Consider delaying Autocomplete (New) requests
You can employ strategies such as delaying a Autocomplete (New) request until the user has typed in the first three or four characters so that your application makes fewer requests. For example, making Autocomplete (New) requests for each character after the user has typed the third character means that if the user types seven characters then selects a prediction for which you make one Geocoding API request, the total cost would be for 4 Autocomplete (New) Per Request + Geocoding.1

If delaying requests can get your average programmatic request below four, you can follow the guidance for performant Autocomplete (New) with Geocoding API implementation. Note that delaying requests can be perceived as latency by the user who might be expecting to see predictions with every new keystroke.

Consider employing performance best practices to help your users get the prediction they're looking for in fewer characters.

Performance best practices

The following guidelines describe ways to optimize Autocomplete (New) performance:

  • Add country restrictions, location biasing, and (for programmatic implementations) language preference to your Autocomplete (New) implementation. Language preference is not needed with widgets since they pick language preferences from the user's browser or mobile device.
  • If Autocomplete (New) is accompanied by a map, you can bias location by map viewport.
  • In situations when a user does not choose one of the Autocomplete (New) predictions, generally because none of those predictions are the result-address wanted, you can reuse the original user input to attempt to get more relevant results:
    • If you expect the user to enter only address information, reuse the original user input in a call to the Geocoding API.
    • If you expect the user to enter queries for a specific place by name or address, use a Place Details (New) request. If results are only expected in a specific region, use location biasing.
    Other scenarios when it's best to fall back to the Geocoding API include:
    • Users inputting subpremise addresses, such as addresses for specific units or apartments within a building. For example, the Czech address "Stroupežnického 3191/17, Praha" yields a partial prediction in Autocomplete (New).
    • Users inputting addresses with road-segment prefixes like "23-30 29th St, Queens" in New York City or "47-380 Kamehameha Hwy, Kaneohe" on the island of Kauai in Hawai'i.

Location biasing

Bias results to a specified area by passing a location parameter and a radius parameter. This instructs Autocomplete (New) to prefer showing results within the defined area. Results outside of the defined area may still be displayed. You can use the components parameter to filter results to show only those places within a specified country.

Location restricting

Restrict results to a specified area by passing a locationRestriction parameter.

You may also restrict results to the region defined by location and a radius parameter, by adding the locationRestriction parameter. This instructs Autocomplete (New) to return only results within that region.