Skip to main content

Fixing 'This API project is not authorized to use this API' for Google Maps Places

 If you are integrating location features into a modern web application, encountering the message "This API project is not authorized to use this API" in your browser console is a standard rite of passage. This error typically surfaces when rendering a map works perfectly, but attempting to use the search box, autocomplete, or address resolution immediately throws a 403 Forbidden status.

This issue stems from a fundamental misunderstanding of how Google Cloud structures its location services. Google Maps is not a monolithic service; it is a collection of highly specific, isolated APIs. Fixing this error requires bridging the gap between your frontend JavaScript implementation and your Google Cloud project configuration.

Understanding the Root Cause of the 403 Error

When a browser console displays a Google Places API 403 error, the root cause is almost always a mismatch between the services enabled in the Google Cloud Console and the specific endpoints your frontend code is trying to reach.

Developers frequently load the standard Maps JavaScript API and assume it covers all location-based functionality. However, Google Cloud compartmentalizes these features to manage billing and security. If you append &libraries=places to your Maps script URL, or use a package like @googlemaps/js-api-loader to load the Places library, your application makes discrete network requests to the Google Places API infrastructure.

If the backend Places API is not toggled "on" in your specific Google Cloud project, the Google authentication servers reject the request, stating "This API project is not authorized."

The Three Most Confused Maps Services

To prevent recurring authorization issues, it is critical to understand the boundaries of the three most commonly conflated Google Maps Platform APIs:

  1. Maps JavaScript API: Responsible strictly for rendering the visual map tiles, handling pan/zoom interactions, and drawing basic markers or polygons. It does not know how to search for a restaurant.
  2. Places API: A database query service. It handles autocomplete suggestions, fetches specific details about a business (phone numbers, hours), and resolves Point of Interest (POI) data.
  3. Geocoding API: A translation service. It converts a raw string (e.g., "1600 Amphitheatre Parkway") into latitude/longitude coordinates, or vice versa (Reverse Geocoding).

Step-by-Step Resolution

To eliminate the "This API project is not authorized" error, you must align your Google Cloud Console configuration with your frontend codebase.

Step 1: Enable Places API Google Cloud Services

The first step is to activate the specific API your code requires. If you are building an autocomplete search box, you need the Places API.

  1. Navigate to the Google Cloud Console.
  2. Ensure you have selected the correct project from the top dropdown menu.
  3. In the left-hand navigation menu, go to APIs & Services > Library.
  4. In the search bar, type "Places API".
  5. Click on Places API (Note: If you are using the newer field-masked endpoint architecture, you may need to enable Places API (New). For standard JavaScript autocomplete widgets, the standard "Places API" is required).
  6. Click the blue Enable button.

Step 2: Configure Google Maps API Restrictions

Adding API keys directly to frontend code exposes them to the public. To secure these keys, developers apply restrictions. However, an improperly restricted key will trigger the exact same 403 error. If you previously restricted your API key to only the Maps JavaScript API, your Places requests will be rejected.

  1. In the Google Cloud Console, navigate to APIs & Services > Credentials.
  2. Click on the API Key your application is using.
  3. Scroll down to the API restrictions section.
  4. If "Restrict key" is selected, examine the dropdown list of allowed APIs.
  5. You must explicitly check Places API (and/or Geocoding API, depending on your usage) alongside the Maps JavaScript API.
  6. Click Save. Note that Google Cloud API restrictions can take up to 5 minutes to propagate across their global network.

Modern Implementation: React & Places Autocomplete

To demonstrate the correct usage of these APIs, below is a modern, production-ready implementation of a Google Places Autocomplete input using React.

This code avoids outdated <script> tags in the index.html file and instead relies on the official @googlemaps/js-api-loader. This pattern guarantees that the Places library is dynamically loaded only when needed, improving your Core Web Vitals.

import React, { useEffect, useRef, useState } from 'react';
import { Loader } from '@googlemaps/js-api-loader';

// Define the component props
interface PlaceAutocompleteProps {
  apiKey: string;
  onPlaceSelected: (place: google.maps.places.PlaceResult) => void;
}

export const PlaceAutocomplete: React.FC<PlaceAutocompleteProps> = ({ apiKey, onPlaceSelected }) => {
  const inputRef = useRef<HTMLInputElement>(null);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    // Initialize the official Google Maps JS API Loader
    const loader = new Loader({
      apiKey: apiKey,
      version: 'weekly',
      // CRITICAL: You must explicitly request the 'places' library here.
      // This requires the Places API to be enabled in Google Cloud Console.
      libraries: ['places'], 
    });

    loader.importLibrary('places')
      .then((googlePlaces) => {
        if (!inputRef.current) return;

        // Instantiate the Autocomplete widget
        const autocomplete = new googlePlaces.Autocomplete(inputRef.current, {
          fields: ['formatted_address', 'geometry', 'name'],
          types: ['establishment', 'geocode'],
        });

        // Add the listener for when a user selects a place
        autocomplete.addListener('place_changed', () => {
          const place = autocomplete.getPlace();
          if (!place.geometry || !place.geometry.location) {
            setError('No location data available for this place.');
            return;
          }
          setError(null);
          onPlaceSelected(place);
        });
      })
      .catch((err) => {
        console.error('Failed to load Google Places library', err);
        setError('Failed to initialize location services. Check API restrictions.');
      });
  }, [apiKey, onPlaceSelected]);

  return (
    <div className="autocomplete-container">
      <input
        ref={inputRef}
        type="text"
        placeholder="Search for a location..."
        className="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
      />
      {error && <p className="text-red-500 text-sm mt-2">{error}</p>}
    </div>
  );
};

Analyzing the Code Integration

In the implementation above, the loader.importLibrary('places') method performs an asynchronous fetch to Google's servers.

If you bypass Step 1 and fail to enable the Places API in Google Cloud, the Promise returned by importLibrary will resolve, but the subsequent network payload fired when the user types into the input field will return an HTTP 403. By correctly passing the libraries: ['places'] array, you explicitly signal your intent to utilize the Places API infrastructure.

Common Pitfalls and Edge Cases

Even after enabling the correct APIs, developers frequently encounter secondary issues that masquerade as authorization errors.

HTTP Referrer Mismatches

Frontend API keys should always be secured using HTTP referrers. A common mistake is configuring the restriction too strictly. If your local development server runs on http://localhost:3000, adding localhost is insufficient. You must use the exact format: http://localhost:3000/*. For production domains, utilizing wildcards correctly (e.g., *example.com/*) ensures that subdomains and specific paths are all authorized.

Utilizing Geocoding for Autocomplete

A severe anti-pattern is attempting to build an autocomplete search bar by firing a request to the Geocoding API on every keystroke. The Geocoding API is not optimized for partial string matching and will return erratic results. Furthermore, this will rapidly exhaust your API quota. Always use the Places API Autocomplete service for keystroke-level predictions, and reserve the Geocoding API for translating complete, static addresses into map coordinates.

Missing Billing Account

Google Maps Platform requires an active billing account, even if you remain entirely within the $200 monthly recurring free tier. If your billing account is suspended, or if a credit card has expired, Google Cloud will silently fail authorization checks. The resulting network error often looks identical to an unconfigured API key. If your API restrictions are perfect and the correct services are enabled, check the Billing dashboard in Google Cloud Console.