Map matching that puts the ride back on the road.

A phone’s GPS fixes wander off the street by metres. Send the trace and get back the roads it was actually on, as a clean line with a real distance and a real duration. One unit, up to a hundred fixes.

10,000 units free every month. No credit card, no sales call.

Real response · by bike37 fixes = 1 unit
matched
4.12km
on the road
15min
fixes were off by
6m avg
POST /map-matching/v1 · 37 points · costing: bicycle

raw · 37 fixes, ±8 m

Where it lands in your product.

Nobody ships an endpoint. They ship a ride log whose distance a cyclist believes, a fleet map where the van is on the street and not in the canal, a mileage claim that holds up. This is what a matched trace looks like from the outside.

Map of Amsterdam with 37 scattered GPS fixes beside the streets and the matched route drawn on the streets

Centraal to the Vondelpark by bike, 37 fixes off by ±15 m

  • Raw fixes, 10 m off on average
  • Matched, 4.17 km on the road
© OpenStreetMap contributors

The fixes beside the road, the ride on it.

Thirty-seven fixes from one bike ride, each off by metres the way a phone in a coat pocket is. The matched line runs down the streets the rider actually took, and its length is the distance actually ridden.

The same road graph, routed
Ride log · same ride, three phones
The route on the ground: 4.15 km
  • Open sky±4 m4.14 km· 15 min
  • City street±8 m4.12 km· 15 min
  • Urban canyon±15 m4.17 km· 15 min

Three phones, one distance.

The same ride recorded at three noise levels comes back within a few dozen metres of the same length every time. Summing raw fixes would have given three different, longer answers.

Then navigate it

A ride being recorded, one fix every few seconds

1unit for the whole trace

0 of 100 fixes
still 1 unit

One unit, a hundred fixes.

A match costs one unit however many points it carries, up to a hundred per request. Longer traces go as an encoded polyline, or in chunks.

See what a month costs
ride.ts
const { trip } = await rijwind.mapMatching({
  shape: fixes, // [{ lat, lon }, …] from the phone
  costing: 'bicycle',
});

saveRide({ km: trip.summary.length, line: trip.legs[0].shape });

It comes back as a route.

Same envelope as directions: a summary with the real distance and time, and a leg with the matched geometry and the streets it took. The code that draws a route draws a matched ride.

Read the quickstart

A trace in, a route out.

The response is the route the device took: the snapped start and end, a summary with the distance actually travelled, and a leg with the matched line and the streets along it. Nothing new to parse if you already draw routes.

Every field, in the docs ↗
trip · 37 fixes in
  1. {
  2. "trip": {// same shape as a plain route
  3. "locations": [// where the trace starts and ends, snapped
  4. { "lat": 52.379946, "lon": 4.900703, "originalIndex": 0 },
  5. { "lat": 52.358392, "lon": 4.86862, "originalIndex": 36 }// fix 36 of 37
  6. ],
  7. "summary": { "length": 4.172, "time": 896, … },// the distance actually ridden, not the sum of the jitter
  8. "legs": [{
  9. "shape": "…",// the matched line, 304 points, encoded polyline
  10. "maneuvers": [ … ]// the streets it took, in order
  11. }],
  12. "units": "kilometers"
  13. }
  14. }

The short version.

Everything a developer scans a product page for, in one place, without the adjectives.

Map matchingHowever many fixes it carries, up to the cap.
1 unit / request
Per requestAs coordinates; longer traces as an encoded polyline or in chunks.
up to 100 fixes
ProfilesTells the matcher which roads the device could be on.
car · bike · foot
Timestamps, speedsPositions in order, matched on geometry. Speeds are yours to derive.
no
OutputSame envelope as directions: summary, matched geometry, manoeuvres.
a route
Free tierHard cap. No card, no sales call.
10,000 units / month
Paid plansOne unit pool across maps, geocoding and routing, plus a spending cap you set.
from €5 / month
ProcessingNo US-controlled provider in the request path. DPA and sub-processor list published.
EU, end to end

Numbers as of September 2026. The pricing page has the full ladder.

Map matching, answered.

What is map matching?

Taking a sequence of GPS positions, which are always a few metres off, and working out which roads the device was actually travelling on. The result is a line that follows the streets, with the distance and time of that line rather than of the jittery fixes.

What is it for?

Ride and run logs that show the real route and the real distance, fleet and delivery apps that need to know which streets a vehicle used, mileage claims, and any analysis that starts with 'which road was this on'. The matched line also draws cleanly, where raw fixes zigzag.

How much does it cost?

One unit per request, from the same monthly pool as maps, geocoding and routing, whatever the number of fixes up to the cap.

How many points can one request carry?

Up to a hundred fixes as a list of coordinates. Longer traces can be sent as a single encoded polyline instead, or split into chunks that are matched one after the other.

How noisy can the trace be?

The three traces on this page were jittered by 4, 8 and 15 metres and all matched to within a few dozen metres of the true length. Much larger errors, long gaps or a device that stopped for a while can still be matched, but the further the fixes are from any road the more the matcher has to guess.

Which travel profiles are supported?

Car, bicycle and pedestrian. The profile tells the matcher which roads the device could have been on, so a bike trace is not snapped onto a motorway.

Does it use timestamps or speed?

No. It takes positions in order and matches on geometry alone, which is enough for the route and the distance. If you need per-fix speeds, compute them from your own timestamps against the matched line.

What comes back exactly?

The same envelope as a route: a summary with the matched distance and time, a leg with the matched geometry as an encoded polyline and the manoeuvres along it, and the snapped start and end. The code that handles a route handles this.

Is there a free tier?

Yes. The free plan includes 10,000 units a month with no card and no sales call, which is 10,000 matched traces if that is all you spend them on. It is a hard cap, so a runaway loop cannot produce a bill.

Where are my requests processed?

In the European Union, end to end. No part of the request path touches a US-controlled provider, which is what makes the GDPR and data-residency conversation short. We publish a DPA and a full sub-processor list.

Put your rides on the road.

Ten thousand units a month, free. The same key covers maps, search and routing when you get to them.

37 fixes from a coat pocket, by bikeGet an API key
No credit card. No sales call. A spending cap you set yourself.Read the quickstart