Using the Google Distance Matrix API for taxi dispatch
In this blog post, I'll tell you all about the new Google Distance Matrix API - the Compute Route Matrix endpoint of the Routes API. I'll explain how it can be used to get the travel time (considering real time traffic) and distance for a matrix of origins and destinations, and how you can use it to build a basic taxi dispatch system that matches passengers to the nearest driver.
Part 1: A developer's guide to the Google Routes API
Part 2: Plan a route with multiple stops using the Routes API
Part 3: Using the Google Distance Matrix API for taxi dispatch (this article)
Part 4: Google Search Along Route
Part 5: How to draw a route on Google Maps for Android with the Routes API
What is the Google distance matrix API?
A distance matrix API is a web service that returns travel times and distances for multiple locations. It returns a matrix where each row represents an origin, each column represents a destination, and the values in the matrix contain the travel time and/or distance between them. The Google Distance Matrix API is called Compute Route Matrix. It's part of the Routes API, a collection of APIs that help with navigation, ETA (Estimated Arrival Time) calculation and route finding.
In this blog post, I'll be using the terms Distance Matrix API and Compute Route Matrix interchangeably throughout, because they essentially mean the same thing. Compute Route Matrix is the updated version of the original Google Distance Matrix API, which will be deprecated on March 1, 2025.
Suppose you have three locations, A
, B
and C
in Vancouver, Canada, and you want to get the distance from each point to every other point. Compute Route Matrix will make 9 Compute Routes calls in parallel to get the distance from A to B, A to C, ..., C to C, and present the results in a table like this:
A | B | C | |
---|---|---|---|
A | A → A (0 km) | A → B (5.7 km) | A → C (5.4 km) |
B | B → A (5.7 km) | B → B (0 km) | B → C (4.8 km) |
C | C → A (5.4 km) | C → B (4.8 km) | C → C (0 km) |
This table is called a distance matrix (let's call it matrix), and it allows us to easily look up distances between two points e.g. the distance between A
and B
is simply matrix[A
][B
] which is 5.7 km. The number of elements in a distance matrix of 3 origins and 3 destinations is 3 x 3 = 9.
Compute Route Matrix always returns the travel time and distance for the fastest route between each origin-destination pair in the matrix, considering real time traffic. The Compute Route Matrix endpoint is highly efficient, providing results for multiple routes in approximately the same time it takes the Compute Routes endpoint to return data for a single route. However, it does not provide route geometries. If you need to draw a route polyline, you'll need to make a separate call to the Compute Routes endpoint of the Routes API.
Google Distance Matrix API use cases
The Google Distance Matrix API is commonly used to find the nearest store, locate the closest available vehicle, and serve as a lookup table for route optimization algorithms.
Nearest store or restaurant Many chain stores or restaurants such as MacDonald's have an app that you can download to place online orders, access discounts, and find the nearest open location based on your current position.
Nearest available vehicle Ride-sharing platforms like Uber and Lyft typically display a list of available vehicles, sorted by travel time from the user's location. This allows passengers to choose the best option based on their preferences. For example, a rider might select a cheaper ride that's farther away, even if it means waiting longer.
Lookup table Route optimization solvers like Google OR Tools and jsprit use distance matrices to calculate the most efficient travel routes between multiple locations. Once the matrix data is provided, the solver runs an algorithm to optimize routes for a fleet of vehicles, ensuring efficient delivery of goods or services to customers.
Google Distance Matrix API example
The Compute Route Matrix endpoint can return a duration matrix, a distance matrix, or both, and provide travel times and distances between multiple locations.
Here's a simple example with one origin and three destinations. Suppose you use a taxi app to book a ride from your hotel to Vancouver International Airport. The origin is your location at the "Residence Inn" in downtown Vancouver, while the destinations are three taxis located in the "West End", "Kitsilano", and "Mount Pleasant".
Endpoint POST
https://routes.googleapis.com/distanceMatrix/v2:computeRouteMatrix
Headers
Content-Type: application/json
X-Goog-Api-Key: YOUR_API_KEY
X-Goog-FieldMask: originIndex,destinationIndex,duration,distanceMeters
Request
{
"origins": [
{
"waypoint": {
"address": "Residence Inn Vancouver Downtown, Vancouver, BC Canada"
}
}
],
"destinations": [
{
"waypoint": {
"address": "Kitsalano, Vancouver, BC Canada"
}
},
{
"waypoint": {
"address": "West End, Vancouver, BC Canada"
}
},
{
"waypoint": {
"address": "Mount Pleasant, Vancouver, BC Canada"
}
}
],
"travelMode": "DRIVE",
"routingPreference": "TRAFFIC_AWARE",
"departureTime": "2025-10-23T15:00:00Z"
}
origins
is an array of RouteMatrixOrigin objects. Just like with the Routes API Compute Routes method, there are several ways you can define an origin
object:
- Address string
{
"waypoint": {
"address": "Residence Inn Vancouver Downtown, Vancouver, BC Canada"
}
}
- Google Maps Place ID
{
"waypoint": {
"placeId": "ChIJgXOcgNRzhlQRYaYJ-NfFCzg"
}
}
location
object with coordinates
{
"waypoint": {
"location": {
"latLng": {
"latitude": 49.277871,
"longitude": -123.128413
}
}
}
}
You can also add Route Modifiers to avoid certain routes. For example, to avoid toll roads, you should include routeModifiers": {"avoidTolls": true}
to the origin
object like so:
{
"waypoint": {
"address": "Residence Inn Vancouver Downtown, Vancouver, BC Canada"
},
"routeModifiers": {
"avoidTolls": true
}
}
The destinations
parameter is an array of RouteMatrixDestinations objects, representing the endpoints of the routes. Its structure and available options are identical to those of origins
.
travelMode
refers to the mode of transport ("DRIVE", "WALK", "TRANSIT" or "BICYCLE"). Right now, truck routing is not supported by the Routes API but this might change in the future.
The routingPreference
parameter lets you choose between:
- "TRAFFIC_UNAWARE",
- "TRAFFIC_AWARE", and
- "TRAFFIC_AWARE_OPTIMAL".
Choosing "TRAFFIC_AWARE" enables the routing algorithm to account for real time traffic conditions when calculating routes. This is ideal for urban areas, where traffic congestion during peak hours can lead to significant delays.
Selecting "TRAFFIC_UNAWARE" means the Routes API will base its calculations solely on posted speed limits, without considering live traffic data.
For the most accurate and efficient routes in traffic-heavy areas, "TRAFFIC_AWARE" is the recommended option.
The departureTime
field, specified in RFC3339 UTC "Zulu" format (e.g., "2025-02-24T15:00:00Z"), ensures that the API accounts for predicted real time traffic conditions when calculating travel time or drive time. If departureTime
is left empty, it defaults to the time that the request was made.
Response
[
{
"originIndex": 0,
"destinationIndex": 1,
"status": {},
"distanceMeters": 1861,
"duration": "379s"
},
{
"originIndex": 0,
"destinationIndex": 0,
"status": {},
"distanceMeters": 3630,
"duration": "521s"
},
{
"originIndex": 0,
"destinationIndex": 2,
"status": {},
"distanceMeters": 3640,
"duration": "637s"
}
]
Compute Route Matrix returns the three possible routes
for each origin-destination pair, sorted in no particular order.
The response is an array, where each array element corresponds to the route
from one origin waypoint to one destination waypoint. You can identify each route in the response by using the originIndex
and destinationIndex
response fields.
For example, an originIndex
of 0 (passenger pickup location) in the response corresponds to a route calculated from the waypoint at index 1 (West End) of the origins array in the request.
{
"originIndex": 0,
"destinationIndex": 1,
"status": {},
"distanceMeters": 1861,
"duration": "379s"
}
distanceMeters
is the total distance in meters that the taxi will need to drive to pick up the passenger while duration
is his driving time in seconds.
Using the response from the Distance Matrix API, a taxi company can offer customers multiple route options and allow them to choose the best taxi based on their needs. For example, a passenger might opt for a cheaper taxi that’s farther away, even if it means a longer wait time.
Google Distance Matrix API limits
The Compute Route Matrix endpoint is very computational intensive (each cell in the distance matrix requires the equivalent of a Routes API Compute Routes call), so there are some necessary limits in place to prevent abuse.
- Origins & Destinations: Maximum of 25 origins or 25 destinations per request.
- Rate Limit: Up to 3,000 elements per minute (EPM), calculated as:
Number of origins × Number of destinations. - Place ID or Address: Maximum of 50 origins and destinations when using a Place ID or address.
- Traffic-Aware Routing: When
"routingPreference": "TRAFFIC_AWARE_OPTIMAL"
, the request can only include up to 100 elements. - Transit Mode: When
"travelMode": "TRANSIT"
, the request can include up to 100 elements. - General Limit: For all other cases, the request can include up to 625 elements.
However, the 625 element limit does make it challenging to use Compute Route Matrix for optimization problems involving a large number of origins and destinations. To work around this, you can either:
- Split the matrix into smaller ones, each with a maximum size of 25 × 25.
- Use a different distance matrix API provider that supports larger matrices.
Google Distance Matrix API Pricing
Since the Compute Route Matrix endpoint handles requests of widely varying sizes, billing is tracked by the number of elements returned instead of the number of requests made. The number of elements is equal to the number of origins multiplied by the number of destinations. If a request contain one origin and three destinations (as shown in our example), then the single request is billed for three elements.
The Compute Route Matrix endpoint has three pricing tiers based on the cost per element - Basic ($5), Advanced ($10 CPM) and Preferred ($15 CPM).
Basic: Supports up to 25 origins and 25 destinations. No real time traffic.
Advanced: Enabled when you use "TRAFFIC_AWARE" or "TRAFFIC_AWARE_OPTIMAL" routing options set in the routingPreference
property, and side of the road, heading and vehicle stopover location modifiers.
Preferred: Any request that uses two wheeled vehicle routing, toll calculation or route modifiers e.g. "avoid tolls".
If you work with a Google Maps Partner, you can access discounted Routes API pricing based on the following price schedule.
0 - 100k | 100k - 500k | 500k - 1M | 1M - 5M | 5M - 10M | 10M - 20M | 20M + | |
---|---|---|---|---|---|---|---|
Compute Route Matrix (Basic) | $5.00 | $4.00 | $3.00 | $1.50 | $0.38 | $0.11 | $0.04 |
Compute Route Matrix (Advanced) | $10.00 | $8.00 | $6.00 | $3.00 | $0.75 | $0.23 | $0.08 |
Compute Route Matrix (Preferred) | $15.00 | $12.00 | $9.00 | $4.50 | $1.14 | $0.33 | $0.12 |
As you can imagine, the Google Distance Matrix API can get very expensive, quickly. A maxed out 25 x 25 matrix will cost you $5 CPM x 625 elements = $3.125 per request. In real world applications such as ride sharing or restaurant search, thousands of origins and destinations often need to be processed at once, making the Google Distance Matrix API too expensive to use.
For this reason, it is important to prune the search space before calling the Google Distance Matrix API. One approach is to pre-filter destinations using K-nearest neighbor (k-NN) search to find the closest locations. After this initial filtering, you can then use Compute Route Matrix to get precise driving distances and travel times.
Google Distance Matrix API alternatives
The two main drawbacks of the Google Distance Matrix API are its high cost and size limitations. If you don't care about real time traffic, using an open source distance matrix API such as the OSRM Table API solves both these problems. OSRM, or the Open Source Routing Machine, is a free and open source alternative to Google Maps. It gets data from OpenStreetMap (OSM), a geographic database updated and maintained by a community of volunteers.
OSM data is generally OK, but it does not include the real time traffic updates that Google Maps is known for. However, if you host OSRM yourself, it is free to use, and you can work with large distance matrices by allocating additional memory and compute to the OSRM server as needed.
If you prefer not to host your own distance matrix API, you should opt for a service that includes real time traffic data. The HERE Matrix Routing Service supports up to 10,000 origins and destinations, with a cost of $4.60 CPM per element. The Tom Tom Matrix Routing service is more affordable at $2.60 CPM per element, but comes with a limit of 2,500 elements.
Building a taxi dispatch system with the Google Distance Matrix API
Since the Google Distance Matrix API is mainly used for taxi dispatch, I’ll show you how to build a simple taxi dispatch system that finds the nearest available driver for a passenger. If you don't want to pull the code from GitHub and run the app locally, you can play around with a live demo at https://google-distance-matrix.afi.dev/.
google_distance_matrix_demo (coming soon!) is a single page React app that uses Vite as the build tool and development server. It simulates the taxi dispatch process by allowing us to select a location anywhere in Vancouver, Canada, and match us with the nearest available taxi using the Google Distance Matrix API. Just like ride sharing apps such as Uber and Lyft, we display the driver’s route to us (thanks Routes API!), along with his estimated travel time and distance.
App.jsx
App.jsx
does more than act as the main entry point into the app. In addition to managing the overall structure, routing, and layout, it also makes API calls to the Routes API's Compute Route Matrix and Compute Routes endpoints to locate the nearest taxi and generate the route polyline to your location.
In App.jsx
, the useEffect
hook is triggered whenever the value of myLocation
(the user's current location) changes. This happens whenever you enter a new address into the Places Autocomplete search box.
/*** App.jsx ***/
useEffect(() => {
if (!myLocation) return;
resetData();
computeRouteMatrix();
}, [myLocation]);
Compute Route Matrix API call
If myLocation
is not null, we make a call to computeRouteMatrix()
which recalculates new routes based on the updated myLocation
.
- For each
taxi
, we create an array oforigins
by extracting thetaxi.lat
andtaxi.lng
coordinates and saving them to thelatitude
andlongitude
fields of eachorigin
object. - We then create a single
destination
and set itsplaceId
tomyLocation.placeId
. - Finally, we tell the Compute Routes endpoint that we are only interested in four wheel vehicle routes by specifying
travelMode: "DRIVE"
.
/*** App.jsx ***/
const computeRouteMatrix = async () => {
const requestBody = {
origins: taxis.map((taxi) => ({
waypoint: {
sideOfRoad: true,
location: {
latLng: {
latitude: taxi.lat,
longitude: taxi.lng,
},
},
},
})),
destinations: [
{
waypoint: {
sideOfRoad: true,
placeId: myLocation.placeId,
},
},
],
travelMode: "DRIVE",
};
try {
const { response } = await request(
"https://routes.googleapis.com/distanceMatrix/v2:computeRouteMatrix",
{
headers: {
"X-Goog-FieldMask": "originIndex,distanceMeters,duration",
},
method: "POST",
data: requestBody,
},
);
if (response) {
const newList = taxis
.map((taxi, index) => {
const route = response.find((r) => r.originIndex === index);
return {
...taxi,
duration: route.duration,
distance: route ? route.distanceMeters : undefined,
};
})
.sort((x, y) => x.distance - y.distance);
setTaxis(newList);
fetchRoute(newList[0], 0);
}
} catch (error) {
console.error(error);
}
};
As explained earlier, the response from the Compute Route Matrix endpoint is an array (unsorted and seemingly random, which is annoying), where each array element defines the route from one origin waypoint to one destination waypoint.
/*** response[] ***/
[
{
"originIndex": 2,
"destinationIndex": 0,
"status": {},
"distanceMeters": 4146,
"duration": "924s"
},
// ... 2 more entries
]
We also have an array of taxi
data objects, each with an address
, lat
and lng
.
/*** constant/index.js ***/
export const DATA = [
{
address: '7272 Robson St, Vancouver, BC',
lat: 49.275794,
lng: -123.114735,
},
{
address: '3702 Robson St, Vancouver, BC',
lat: 49.294657,
lng: -123.13668,
}
// ... 10 more taxi objects
]
Once we get a valid response from Compute Route Matrix, we need to sort the list of taxis by distance
(we could also use duration
) from the our pickup location. Here's how to do it.
- We initialize a new array,
newList
, and use the map function to iterate over eachtaxi
intaxis
.
const newList = taxis.map((taxi, index) => {
});
- Next, the
index
of eachtaxi
in the array is used to find a corresponding route in theresponse
array.
const route = response.find((r) => r.originIndex === index);
- If a matching route is found, the
taxi
object is copied over tonewList
with two new fields,duration
(fromroute.duration
) anddistance
(fromroute.distanceMeters
).
return {
...taxi,
duration: route.duration,
distance: route ? route.distanceMeters : undefined,
};
- Finally, the taxis are sorted in ascending order of
distance
(smallest to nearest).
sort((x, y) => x.distance - y.distance);
To get the nearest taxi to the our location, access the first element of the newList
array with newList[0]
.
Compute Routes API Call
Once we get the nearest taxi, we can use the Compute Routes endpoint of the Routes API to display the driver's route to our pickup location.
/*** App.jsx ***/
const fetchRoute = async (taxi, index) => {
const requestBody = {
origin: {
sideOfRoad: true,
location: {
latLng: {
latitude: taxi.lat,
longitude: taxi.lng,
},
},
},
destination: {
sideOfRoad: true,
placeId: myLocation.placeId,
},
travelMode: "DRIVE",
};
try {
const { response } = await request(
"https://routes.googleapis.com/directions/v2:computeRoutes",
{
headers: {
"X-Goog-FieldMask": "routes.polyline.encodedPolyline",
},
method: "POST",
data: requestBody,
},
);
if (response) {
const route = response.routes[0].polyline.encodedPolyline;
setActiveTaxi(index);
console.log(taxi);
setPolyline({
color: taxi.color,
encodedPath: route,
});
}
} catch (error) {
console.error(error);
}
};