Skip to the content.

Places (New) Autocomplete - JavaScript Library

npm version License: MIT Google Maps Platform Awards 2025

A flexible and customisable vanilla JavaScript library for frontend web applications, leveraging the Google Maps Places (New) Autocomplete API. Winner of the Google Maps Platform Awards 2025, recognising excellence in Google Maps Platform development. This library provides a user-friendly way to search for and retrieve detailed address and location information in any web application.

It handles API loading, session tokens for cost-effective usage, fetching suggestions with debouncing, keyboard navigation, highlighting matched text, and requesting place details, allowing you to focus on integrating the results into your application.

Live Demo

Explore interactive examples of the Google Places Autocomplete JS library:

A quick, editable sandbox to experiment with the core functionality:

See a more comprehensive live demo of the library in action: pacservice.uk

A video demonstrating the Places Autocomplete JavaScript component in action, showing address suggestions and selection.

Features

Benefits

Recognition

🏆 Google Maps Platform Awards 2025 Winner

Google Maps Platform Awards 2025 Winner

This library has been recognised as a winner of the Google Maps Platform Awards 2025 by the Google Developer Program. This award celebrates outstanding projects that demonstrate exceptional use of Google Maps Platform APIs, innovation, and contribution to the developer community.

Learn more about the Google Maps Platform Awards

Requirements

Installation & Usage

This library can be used in two primary ways: by installing it as an npm package for use with a bundler (like Vite or Webpack), or by linking to it directly from a CDN in a static HTML file.

This is the recommended approach for modern web applications.

Step 1: Install the package

npm install places-autocomplete-js
# or
yarn add places-autocomplete-js

Step 2: Import and initialise the component

In your main JavaScript or TypeScript file, import both the library and its stylesheet.

import { PlacesAutocomplete } from 'places-autocomplete-js';
import 'places-autocomplete-js/places-autocomplete.css'; // Import the default stylesheet

document.addEventListener('DOMContentLoaded', () => {
  try {
    const autocomplete = new PlacesAutocomplete({
      containerId: 'autocomplete-container',
      googleMapsApiKey: 'YOUR_GOOGLE_MAPS_API_KEY', // Replace with your key
      onResponse: (placeDetails) => {
        console.log('Place Selected:', placeDetails);
        // Your code to handle the selected place...
      },
      onError: (error) => {
        console.error('Autocomplete Error:', error.message || error);
      }
    });
  } catch (error) {
    console.error("Failed to initialise PlacesAutocomplete:", error.message);
  }
});

Then, add the container element to your HTML:

<div id="autocomplete-container"></div>

For quick prototyping or use in projects without a build step, you can use a CDN like jsDelivr.

Step 1: Add the stylesheet and script to your HTML

Add the following lines to your HTML file. The stylesheet goes in the <head> and the script goes at the end of the <body>.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Places Autocomplete Demo</title>
  
  <!-- 1. Link to the stylesheet -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/places-autocomplete-js@latest/dist/places-autocomplete.css">
  
</head>
<body>

  <!-- 2. Add the container for the component -->
  <div id="autocomplete-container"></div>

  <!-- 3. Link to the library's script -->
  <script type="module">
    // 4. Import the class from the script
    import { PlacesAutocomplete } from 'https://cdn.jsdelivr.net/npm/places-autocomplete-js@latest/dist/places-autocomplete.js';

    document.addEventListener('DOMContentLoaded', () => {
      try {
        const autocomplete = new PlacesAutocomplete({
          containerId: 'autocomplete-container',
          googleMapsApiKey: 'YOUR_GOOGLE_MAPS_API_KEY', // Replace with your key
          onResponse: (placeDetails) => {
            console.log('Place Selected:', placeDetails);
          }
        });
      } catch (error) {
        console.error("Failed to initialise PlacesAutocomplete:", error.message);
      }
    });
  </script>

</body>
</html>

Note for Production: For stability, it’s recommended to pin the CDN links to a specific version instead of using @latest. For example: .../places-autocomplete-js@1.1.8/...

Configuration

The PlacesAutocomplete class is initialised with a configuration object.

Parameter Type Required Description
containerId string Yes The ID of the HTML element where the autocomplete widget will be rendered.
googleMapsApiKey string Yes Your Google Maps API Key with the Places API (New) enabled.
googleMapsApiVersion string No The version of the Google Maps API to load (e.g., “weekly”, “quarterly”, “beta”). Defaults to “weekly”.
onResponse function No Callback for selected place details. Receives JSON by default (options.response_type: 'json') or a Google Place instance when options.response_type: 'place'.
onError function No Callback function triggered when an error occurs. Receives an Error object or string. Default logs to console.
options object No Object to customise UI behavior and appearance. See “UI & Behavior Options” below.
requestParams object No Object to customise the parameters sent to the Google Places Autocomplete API. See “API Request Parameters” below.
fetchFields array No Array of Place Data Fields to request when a place is selected. Affects API cost. Default ['formattedAddress', 'addressComponents']

UI & Behavior Options (options)

Passed within the main configuration object under the options key.

Option Type Default Description
placeholder string "Start typing your address ..." Placeholder text for the input field.
debounce number 100 Delay in milliseconds before triggering an API request after user stops typing. Set to 0 to disable.
distance boolean false Whether to attempt to show distance in suggestions (requires origin in requestParams).
distance_units 'km' \| 'miles' 'km' Units to display distance in if distance is true.
label string "" Optional label text displayed above the input field.
autofocus boolean false If true, automatically focuses the input field on initialisation.
autocomplete string 'off' Standard HTML autocomplete attribute for the input field.
classes object (See default classes below) Object to override default CSS classes for styling. See “Styling” section.
clear_input boolean false If true, clears the input field after a suggestion is selected. If false (default), the input field retains the formattedAddress of the selected place.
response_type 'json' \| 'place' 'json' Return format: 'json' for plain JSON object (default), 'place' for full Google Maps Place instance with method access.
show_place_type boolean false Whether to display icons representing the place type (🏪, 🍽️, etc.). Mutually exclusive with distance.

Styling

The component is built with flexibility in mind and can be styled in two ways. The default appearance is based on Tailwind CSS, but you are not required to use Tailwind in your project.

A standalone CSS file is included in the package and contains all necessary styles for the component to work correctly out-of-the-box.

For bundler-based projects:

import 'places-autocomplete-js/style.css';

For CDN usage:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/places-autocomplete-js@latest/dist/places-autocomplete.css">

2. Custom CSS Classes (options.classes)

You can customise the appearance by providing your own CSS classes via the options.classes object. This allows you to override default styles or integrate with your own design system.

Available Class Keys:

Class Key Default CSS Class Description
section pac-section Main container section
container pac-container Div containing the input and suggestions list
label N/A Label element (if options.label is provided)
input pac-input Main text input element
icon_container pac-icon-container Container for the search icon
icon N/A SVG string for the search icon
ul pac-ul Suggestions list (<ul> element)
li pac-li Individual suggestion item
li_current pac-li-current Class for the currently highlighted suggestion
li_button pac-li-button Button element within each suggestion
li_button_current pac-li-button-current Class for the button in the highlighted suggestion
li_div_container pac-li-div-container Container div within the button
li_div_one pac-li-div-one First inner div (contains place name and icon)
li_div_one_p pac-li-div-one-p Paragraph containing the main suggestion text
li_div_two pac-li-div-two Second inner div (contains distance)
li_div_two_p pac-li-div-two-p Paragraph containing the distance text
kbd_container pac-kbd-container Container for keyboard hint keys
kbd_escape pac-kbd-escape Escape key hint
kbd_up pac-kbd-up Up arrow key hint
kbd_down pac-kbd-down Down arrow key hint
kbd_active pac-kbd-active Class applied when a keyboard key is pressed
li_div_two_p_place_type pac-li-div-two-p-place_type Container for place type display
li_div_two_p_place_type_icon pac-li-div-two-p-place_type-icon The place type icon element
li_div_two_p_place_type_label pac-li-div-two-p-place_type-label The place type label text
highlight pac-highlight Class for matched text highlighting

Example:

const autocomplete = new PlacesAutocomplete({
  containerId: 'autocomplete-container',
  googleMapsApiKey: 'YOUR_API_KEY',
  options: {
    classes: {
      input: 'my-custom-input',
      ul: 'my-dropdown',
      li_current: 'active',
      highlight: 'text-highlight',
    },
  },
});

Then define these classes in your stylesheet:

.my-custom-input {
  padding: 0.75rem;
  border: 1px solid #d1d5db;
  border-radius: 0.375rem;
}

.my-dropdown {
  max-height: 20rem;
  overflow-y: auto;
}

.active {
  background-color: #4f46e5;
  color: white;
}

.text-highlight {
  font-weight: 600;
  color: #4f46e5;
}

API Request Parameters (requestParams)

Passed within the main configuration object under the requestParams key. These parameters are sent to the Google Places Autocomplete API. Refer to the AutocompleteRequest documentation for all available options.

Common Parameters:

Parameter Type Description
input string Automatically handled by the library (user’s typed value)
language string Language code for returned results (e.g., "en", "fr", "de")
region string Region code as ccTLD two-character value (e.g., "GB", "US")
includedRegionCodes string[] Array of up to 5 CLDR region codes to restrict results
locationBias google.maps.places.LocationBias Area to bias results towards
locationRestriction google.maps.places.LocationRestriction Area to strictly restrict results to
origin google.maps.LatLngLiteral Origin point for distance calculations (requires options.distance: true)
sessionToken AutocompleteSessionToken Automatically managed by the library

Example:

const autocomplete = new PlacesAutocomplete({
  containerId: 'autocomplete-container',
  googleMapsApiKey: 'YOUR_API_KEY',
  requestParams: {
    language: 'en-GB',
    region: 'GB',
    includedRegionCodes: ['GB'],
    origin: { lat: 51.5074, lng: -0.1278 }, // London
  },
});

Fetch Fields (fetchFields)

The fetchFields option specifies which place data fields to retrieve when a user selects a suggestion. This helps optimise API costs by only fetching necessary information.

Default fields: ['formattedAddress', 'addressComponents']

See Place Class Data Fields for all available fields and their billing impact.

Example:

// In constructor
const autocomplete = new PlacesAutocomplete({
  containerId: 'autocomplete-container',
  googleMapsApiKey: 'YOUR_API_KEY',
  fetchFields: ['formattedAddress', 'addressComponents', 'displayName', 'types'],
});

// Or update dynamically
autocomplete.setFetchFields(['formattedAddress', 'location', 'viewport']);

## Public Methods

The `PlacesAutocomplete` instance provides the following methods for dynamic control:

### `clear()`

Clears the input field, removes visible suggestions, and refreshes the session token.

```javascript
autocomplete.clear();

destroy()

Removes event listeners and cleans up DOM elements. Use this when the component is no longer needed (e.g., when unmounting a view in SPAs).

autocomplete.destroy();

focus()

Sets focus on the autocomplete text input field.

autocomplete.focus();

setInputValue(latitude, longitude)

Sets the input by finding and selecting a place for the given coordinates. Performs reverse geocoding to convert lat/lng to a place, then triggers onResponse using the configured options.response_type. Requires Geocoding API to be enabled.

// Set location to Eiffel Tower
await autocomplete.setInputValue(48.8584, 2.2945);

setFetchFields(fields)

Dynamically updates the Place Data Fields to fetch on selection. The provided fields are merged with the library’s default fields (formattedAddress, addressComponents).

Parameters:

autocomplete.setFetchFields(['displayName', 'types', 'location']);

getFetchFields()

Retrieves the current array of Place Data Fields that will be requested.

Returns: Array<string>

const fields = autocomplete.getFetchFields();
console.log('Current fields:', fields);
// Output: ['formattedAddress', 'addressComponents', 'displayName', 'types', 'location']

setRequestParams(params)

Dynamically updates the Google Places API request parameters. Useful for changing search criteria after initialisation.

Parameters:

// Change region and language
autocomplete.setRequestParams({
  region: 'FR',
  language: 'fr',
  includedRegionCodes: ['FR'],
});

// Set origin for distance calculations
autocomplete.setRequestParams({
  origin: { lat: 48.8566, lng: 2.3522 }, // Paris
});

getRequestParams()

Retrieves the current API request parameters.

Returns: object

const params = autocomplete.getRequestParams();
console.log('Current request params:', params);

setOptions(options)

Dynamically updates UI behaviour and appearance options.

Parameters:

// Update placeholder and debounce
autocomplete.setOptions({
  placeholder: 'Enter your postcode...',
  debounce: 250,
});

// Update CSS classes
autocomplete.setOptions({
  classes: {
    input: 'custom-input',
    ul: 'custom-dropdown',
  },
});

getOptions()

Retrieves the current UI and behaviour options.

Returns: object

const options = autocomplete.getOptions();
console.log('Current options:', options);

Google Places API & Billing

This library uses the Google Maps JavaScript API (Places library). Usage is subject to Google’s terms and pricing.

Requirements

Cost Optimisation

The library automatically implements several cost-saving measures:

  1. Session Tokens: Autocomplete requests are grouped using session tokens, significantly reducing costs compared to per-request billing. See Session Token Pricing.

  2. Minimal Default Fields: By default, only formattedAddress and addressComponents are fetched, minimising costs. Additional fields can be requested via fetchFields, but be mindful of Place Data Fields Pricing.

  3. Debounced Requests: Input is debounced by default (100ms) to reduce unnecessary API calls while typing.

Testing

This project includes both unit tests (using Vitest) and end-to-end tests (using Playwright).

Unit Tests

Unit tests are located in the tests/ directory and are run using Vitest. To execute the unit tests, use the following command:

npm run test:vitest

End-to-End Tests

End-to-end tests are located in the e2e/ directory and are run using Playwright. The Playwright config starts the Vite dev server automatically via webServer, so you can run:

npm run test:e2e

Contributing

Contributions are welcome! Please feel free to open an issue or submit a pull request.

License

MIT