Forward geocoding with the Google Geocoding API
Learn how to use the Google Geocoding API to convert addresses into latitude and longitude. Includes real world examples and sample code.

Forward geocoding is the process of converting a street address into geographic coordinates (latitude and longitude), which can then be used to place markers on a map, plan efficient routes or verify delivery addresses. In this article, I'll show you how to use the forward geocoding endpoint of the Google Geocoding API to do all these and more!

Part 1: A practical guide to the Google Geocoding API
Part 2: Forward geocoding with the Google Geocoding API (this article)
Part 3: Google Maps reverse geocoding: Get addresses from coordinates
Part 4: Google Address Validation API: Better than USPS?
Part 5: Google Maps Building Outlines and Entrances API
I’ll explain what forward geocoding is, walk through a typical request, and cover common use cases. Together, we'll build a simple demo app (https://google-forward-geocoding.afi.dev/) to learn how Google geocoding works in practice. As always, you can find sample code (frontend / backend) for this project on GitHub.

What is forward geocoding?
Forward geocoding converts a written address e.g. "555 West Hastings Street, Vancouver BC V6B4N4, Canada" into geographic coordinates e.g. 49.2846966, -123.1119349. It's the first step in turning real world addresses into usable data.

Google Maps can do this because over the years it has built a vast database of business and residential addresses along with their exact geographic coordinates. Some of this data is sourced through public records and commercial or postal service datasets, but increasingly, a lot of it is user contributed e.g. business owners updating listings via Google Business Profile.
What is forward geocoding used for?
Forward geocoding is essential when you need to display an address on a map or provide location data to an API.
Visualizing data on a map
Forward geocoding is most often used to visualize locations on a map. For instance, instead of showing a plain list of addresses, mapping Vancouver’s best craft breweries makes the information far more useful and engaging.

Address validation
Forward geocoding is also useful for address validation, especially when working with data imported from spreadsheets or legacy systems. The Google Geocoding API helps assess the accuracy of an address by returning a location_type
field (e.g., "ROOFTOP", "RANGE_INTERPOLATED", or "APPROXIMATE"), which indicates the precision of the geocode. This allows companies to determine whether an address is reliable enough to use.

Planning efficient delivery routes
Addresses can be ambiguous or imprecise, and many of Google Map's more advanced routing and navigation products such as the Google Maps Route Optimization API, the Routes API and the Navigation SDK work best with known, mappable coordinates. This is especially important when matching points to road networks, considering traffic, or snapping to the nearest valid route. Forward geocoding is the crucial first step in converting human readable addresses into coordinates that these APIs can consume.

Google Geocoding API example (forward geocoding)
Here's a simple geocoding example that returns the latitude and longitude for "555 West Hastings Street, Vancouver".
Endpoint: GET
https://maps.googleapis.com/maps/api/geocode/json?
address={ADDRESS}&
key={YOUR_API_KEY}
{ADDRESS} is the street address that you want to geocode. Give as much detail as possible including the postal code, but leave out business names and unit, suite or floor numbers.
{YOUR_API_KEY} is your Google Maps API key with the Google Geocoding API enabled.
Endpoint: GET
https://maps.googleapis.com/maps/api/geocode/json?address=555+west+hastings+street+vancouver&key={GOOGLE_MAPS_API_KEY}
Response
{
"results": [
{
"address_components": [
{
"long_name": "555",
"short_name": "555",
"types": [
"street_number"
]
},
{
"long_name": "West Hastings Street",
"short_name": "W Hastings St",
"types": [
"route"
]
},
{
"long_name": "Central Vancouver",
"short_name": "Central Vancouver",
"types": [
"neighborhood",
"political"
]
},
{
"long_name": "Vancouver",
"short_name": "Vancouver",
"types": [
"locality",
"political"
]
},
{
"long_name": "Metro Vancouver",
"short_name": "Metro Vancouver",
"types": [
"administrative_area_level_2",
"political"
]
},
{
"long_name": "British Columbia",
"short_name": "BC",
"types": [
"administrative_area_level_1",
"political"
]
},
{
"long_name": "Canada",
"short_name": "CA",
"types": [
"country",
"political"
]
},
{
"long_name": "V6B 4N4",
"short_name": "V6B 4N4",
"types": [
"postal_code"
]
}
],
"formatted_address": "555 W Hastings St, Vancouver, BC V6B 4N4, Canada",
"geometry": {
"bounds": {
"northeast": {
"lat": 49.2851751,
"lng": -123.111479
},
"southwest": {
"lat": 49.28441489999999,
"lng": -123.1126507
}
},
"location": {
"lat": 49.2846966,
"lng": -123.1119349
},
"location_type": "ROOFTOP",
"viewport": {
"northeast": {
"lat": 49.28614398029149,
"lng": -123.1107158697085
},
"southwest": {
"lat": 49.28344601970849,
"lng": -123.1134138302915
}
}
},
"navigation_points": [
{
"location": {
"latitude": 49.2845048,
"longitude": -123.1124829
}
}
],
"place_id": "ChIJUcKFZ3hxhlQREJGVU1foPaE",
"types": [
"premise",
"street_address"
]
}
],
"status": "OK"
}
When you make a forward geocoding request to the Google Maps Geocoding API, the response is an array, results
. Each item in this array contains detailed information about the geocoded address, including its formatted address, geographic coordinates and level of accuracy.
formatted_address
is a string that provides the official, human readable version of an address - essentially, the way you'd write it on a postcard or envelope when sending mail to that location.
types
is an array of place types that apply to the geocoded address. Most addresses have multiple types. For example, "Vancouver, Canada" is tagged with both locality
and political
, which indicates it is both a city and a political entity.
The geometry
object contains geographic details about the geocoded result, specifically:
location
, which contains the exactlocation.lat
andlocation.lng
of the place.
{
"location": {
"lat": 49.2827291,
"lng": -123.1207375
}
}
location_type
, which indicates the accuracy of the geocoded result.- "ROOFTOP" means the result is highly precise, accurate down to a specific street address.
- "RANGE_INTERPOLATED" and "APPROXIMATE" suggest the location is estimated and less reliable.
As a rule of thumb, only addresses with "ROOFTOP" accuracy should be considered deliverable.
place_id
is the Google Place ID, which uniquely identifies a place in the Google Maps database (docs). You can use it to retrieve additional information about the place e.g. photos, user ratings and reviews.
When should you use the Google Geocoding API for forward geocoding?
Generally, only one entry in the results
array is returned when you forward geocode an address with the Google Geocoding API. This means that the API works best when handling unambiguous queries such as complete postal address strings. The Google Geocoding API is not recommended if your application handles ambiguous or incomplete queries, such as “123 Main St”, or if it handles queries that may contain non address information such as apartment numbers or business names.
If you need to geocode a query such as "Tim Hortons, Vancouver" that will likely have multiple locations, use Google Text Search instead.
Google Maps forward geocoding demo
In this final section, we’ll build a web app that geocodes an address and displays its location on a Google Map, similar to the demo app in Google’s official documentation. The app features three main components:
- A text input field in the top-left corner that lets you enter an address or place name to be geocoded.
- A red marker that indicates the geocoded location of the address.
- A basic information popup that displays the name of the geocoded location and its coordinates.
While the code in this app is fairly simple, it serves as a helpful template for building map based applications that accept user input, call an API, and display the results on a map. If you don't want to pull the code from GitHub and run the app locally, you can still play around with it at https://google-forward-geocoding.afi.dev/.
How our code is organized
google_forward_geocoding is a simple React app created with the Vite build tool. The app works together with google_geocoding_backend, which retrieves place data from the Google Geocoding API.
App.jsx
App.jsx
is the main building block of our app. Think of it as the "frame" or "shell" that holds everything else you see on the screen.

The App.jsx
file is built around three main components:
<SearchBox/>
, a presentational component that includes a text input field and two buttons - [Clear], which resets the map and removes any markers, and [Geocode], which sends the entered address to the Google Geocoding API.<GoogleMap/>
, a wrapper for the react-google-maps<Map/>
component that handles map rendering.<Marker/>
, a red map marker positioned at the geocoded location. When clicked, it opens an<InfoWindow/>
displaying the place name and coordinates of the geocoded address.
/*** App.jsx ***/
import { APIProvider } from "@vis.gl/react-google-maps";
import axios from "axios";
import { useState } from "react";
import GoogleMap from "~/components/GoogleMap";
import SearchBox from "~/components/SearchBox";
import "./App.scss";
function App() {
const [address, setAddress] = useState("");
const [places, setPlaces] = useState([]);
const handleChangeAddress = (e) => {
setAddress(e.target.value);
};
// ... action handler methods
return (
<APIProvider apiKey={import.meta.env.VITE_GOOGLE_MAP_API_KEY}>
<div className="App">
<SearchBox
address={address}
onChangeAddress={handleChangeAddress}
onSearchAddress={handleSearchAddress}
onClearAddress={handleClearAddress}
/>
<GoogleMap places={places} />
</div>
</APIProvider>
);
}
export default App;
SearchBox.jsx
SearchBox.jsx
is a simple address input UI that lets users type in a location, then either clear the input or trigger a geocoding search.
*** components/SearchBox.jsx ***
import "./SearchBox.scss";
const SearchBox = ({
address,
onSearchAddress,
onChangeAddress,
onClearAddress,
}) => {
return (
<div className="SearchBox">
<div className="input-group">
<label className="label">Location</label>
<input
placeholder="Enter your location"
onChange={onChangeAddress}
value={address}
/>
</div>
<div className="button">
<button className="btn clear-btn" onClick={onClearAddress}>
Clear
</button>
<button
className="btn geocode-btn"
onClick={() => onSearchAddress(address)}
>
Geocode
</button>
</div>
</div>
);
};
export default SearchBox;
In SearchBox.jsx
, the text input is controlled by the address
state. When the user types, the onChangeAddress()
function (which points to to handleChangeAddress()
in App.jsx
) is called with the event object, allowing the parent component to update the address
value.
/*** App.jsx ***/
const [address, setAddress] = useState("");
const handleChangeAddress = (e) => {
setAddress(e.target.value);
};
The contents of the text input field are passed to handleChangeAddress()
automatically because React sends a SyntheticEvent
to the onChange
handler whenever the user types in the <input/>
. This event contains the typed address string.
When the user clicks the [Geocode] button, the address is passed to the onSearchAddress()
prop, which calls the handleSearchAddress()
function in App.jsx
.
*** App.jsx ***
const handleSearchAddress = async (address) => {
if (!address) return;
const response = await axios.get(`${import.meta.env.VITE_API_URL}/geocode`, {
params: {
address: address,
},
});
if (response.data.results) {
setPlaces(response.data.results);
}
};
handleSearchAddress()
uses an API loading wrapper pattern to fetch data from the Google Geocoding API. It sends the address string to the /geocode
endpoint of google_geocoding_backend. If the response includes geocoded results, they are saved in state using the setPlaces()
function.
geocode.js
geocode.js
in google_geocoding_backend is a thin proxy client for the Google Geocoding API. Calls to /geocode
are routed to the getGeocode()
function, which then forwards each request to the Geocoding API.
/*** services/geocode.js ***
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();
const GOOGLE_MAP_API_KEY = process.env.GOOGLE_MAP_API_KEY;
const getGeocode = async (address) => {
const res = await axios.get(
"https://maps.googleapis.com/maps/api/geocode/json",
{
params: {
address,
key: GOOGLE_MAP_API_KEY,
},
},
);
return res.data;
};
// ... reverse geocoding endpoint
export default {
getGeocode,
getReverseGeocode,
};
Here, the popular Axios HTTP client library is used to make a GET
request to the Google Geocoding API (https://maps.googleapis.com/maps/api/geocode/json) by passing in the address
and key
(the Google Maps API key retrieved from the .env configuration file) parameters. Axios automatically encodes those parameters into a URL that looks like:
https://maps.googleapis.com/maps/api/geocode/json?address=555 west hastings street vancouver&key={YOUR_API_KEY}
This URL is used to make the API call, and the response from the Geocoding API (below) is stored in the res.data
object. The data is then returned to App.jsx
(from google_forward_geocoding) and saved in the places
state, allowing the geocoded address to be displayed on the map.
{
"results": [
{
"address_components": [
//... address components
],
"formatted_address": "555 W Hastings St, Vancouver, BC V6B 4N4, Canada",
"geometry": {
"location": {
"lat": 49.2846966,
"lng": -123.1119349
},
"location_type": "ROOFTOP"
},
"navigation_points": [
//... navigation info
],
"place_id": "ChIJUcKFZ3hxhlQREJGVU1foPaE",
"types": [
"premise",
"street_address"
]
}
],
"status": "OK"
}
GoogleMap.jsx
GoogleMap.jsx
, found in components/GoogleMap/index.jsx
, is a React component that displays a full screen Google Map using the @vis.gl/react-google-maps library. It takes in a single prop, places
, the array of geocoded location data returned by the Google Geocoding API.
/*** components/GoogleMap/index.jsx ***/
import { Map } from "@vis.gl/react-google-maps";
import MapHandler from "./MapHandler";
import Marker from "./Marker";
const DEFAULT_CENTER = { lat: 49.25307278849622, lng: -123.12095840000302 };
const GoogleMap = ({ places }) => {
return (
<div className="GoogleMap">
<Map
style={{
height: "100dvh",
width: "100dvw",
}}
defaultZoom={12}
defaultCenter={DEFAULT_CENTER}
gestureHandling="greedy"
disableDefaultUI
reuseMaps
>
<MapHandler places={places} />
{places.length > 0 &&
places.map((place) => {
return <Marker key={place.place_id} place={place} />;
})}
</Map>
</div>
);
};
export default GoogleMap;
If places
is non empty, it loops through each place
and renders a <Marker/>
for each one. Each <Marker/>
knows how to position itself on the map based on the geometry.location.lat
and geometry.location.lng
returned by the Geocoding API and stored inside each place
.
Marker.jsx

<Marker/>
is a React component that displays a standard red pin on the map. It accepts a single prop - a place
object - and uses it to position the marker at the geocoded location on the Google Map.
/*** components/GoogleMap/Marker.jsx ***/
import {
Marker as GMarker,
InfoWindow,
useAdvancedMarkerRef,
} from "@vis.gl/react-google-maps";
import { useEffect, useState } from "react";
import "./Marker.scss";
const Marker = ({ place }) => {
const [infowindowOpen, setInfowindowOpen] = useState(true);
const [markerRef, marker] = useAdvancedMarkerRef();
const position = {
lat: place.geometry.location.lat,
lng: place.geometry.location.lng,
};
useEffect(() => {
setInfowindowOpen(false);
}, [position.lat, position.lng]);
return (
<>
<GMarker
ref={markerRef}
position={position}
onClick={() => setInfowindowOpen((prev) => !prev)}
/>
{infowindowOpen && (
<InfoWindow className="info-window" anchor={marker} headerDisabled>
<div className="info-detail">
<div className="info-header">{place.formatted_address}</div>
<div className="info-location">
{position.lat}, {position.lng}
</div>
</div>
<button
className="btn-close"
onClick={() => setInfowindowOpen(false)}
>
X
</button>
</InfoWindow>
)}
</>
);
};
export default Marker;
When the <Marker />
is clicked, the infowindowOpen
boolean is set to true
, which triggers the <InfoWindow />
component to appear. This window displays the place’s formatted_address
and GPS coordinates.
Running the app
To try the app, head over to https://google-forward-geocoding.afi.dev/ and enter an address or place name e.g. "Harbor Center, Vancouver" in the text field at the top left. Hit the [Geocode] button and you'll see a map marker appear at the geocoded location.
If you prefer to run the app locally:
- Fork both the google_forward_geocoding and google_geocoding_backend repositories on GitHub.
- In google_geocoding_backend, run
npm install
to install the dependencies followed bynpm start
. - In geocoding_api_frontend, run
npm install
followed byvite run dev
to start the app. Open your browser to http://localhost:3000/ to view the app.
Remember to update the .env
files in both folders with a Google Maps API key that has the Google Geocoding API enabled.
Next up
In this post, I explained how forward geocoding works using the Google Geocoding API and showed you how to build a simple web app with a map interface to visualize the results. In the next one, we’ll explore Google’s Reverse Geocoding API and build a similar tool that converts coordinates into human readable addresses.
👋 As always, if you have any questions or suggestions for me, please reach out or say hello on LinkedIn.
Next: Part 3: Google Maps reverse geocoding: Get addresses from coordinates