osrmroute
v1.0.0
Published
Official JavaScript/TypeScript SDK for the OSRMRoute Maps, Routing & Geocoding API
Maintainers
Readme
osrmroute
Official JavaScript / TypeScript SDK for the OSRMRoute Maps, Routing & Geocoding API.
- Zero dependencies — uses the platform
fetch(Node 18+, Deno, Bun, browsers) - Fully typed — TypeScript definitions for every endpoint
- All 23 APIs — routing, matrix, isochrones, geocoding, VRP, elevation, geofencing…
[lat, lon]everywhere — the SDK flips to OSRM'slon,latinternally, so the classic "my route is in the ocean" bug can't happen- Automatic retries with exponential backoff, honouring
Retry-After
npm install osrmrouteQuick start
import { OSRMRoute } from 'osrmroute';
const maps = new OSRMRoute({ apiKey: process.env.OSRMROUTE_API_KEY });
const r = await maps.route([[40.4093, 49.8671], [40.3777, 49.8920]]);
console.log(`${(r.routes[0].distance / 1000).toFixed(1)} km, ${Math.round(r.routes[0].duration / 60)} min`);Get a free key at osrmroute.com — no card required.
Configuration
new OSRMRoute({
apiKey: 'your-key', // required
baseUrl: '…', // self-hosted / staging (default https://osrmroute.com)
timeout: 30_000, // per-request ms
retries: 2, // retries on 429 / 5xx / network errors
authMode: 'query', // or 'bearer' to send Authorization: Bearer
headers: {}, // extra headers
});A bare string also works: new OSRMRoute('your-key').
Routing
await maps.route([a, b, c], { profile: 'car', geometries: 'geojson', steps: true });
await maps.matrix([a, b, c]); // { durations, distances }
await maps.directions([a, b], { alternatives: true, lang: 'az' });
await maps.trip([a, b, c]); // travelling-salesman order
await maps.match(gpsTrace); // snap a noisy trace to roads
await maps.nearest(a, { number: 3 });
await maps.snap([a, b]);
await maps.isochrone(a, { timeLimit: 900 }); // 15-min reachability polygonProfiles: car (global), bike, foot. Aliases driving / cycling / walking also work.
Geocoding
await maps.geocode('Nizami küçəsi, Bakı'); // → { hits: [...] }
await maps.reverse([40.4093, 49.8671]); // coordinates → address
await maps.autocomplete('Berl', { limit: 5 }); // → { suggestions: [...] }
await maps.geocodeBatch(['Baku', 'Tbilisi', 'Yerevan']);
await maps.places([40.4093, 49.8671], { radius: 1000, category: 'restaurant' });Bias results toward a location with near, restrict with bbox or city.
Fleet optimisation
const plan = await maps.optimize({
vehicles: [{ id: 1, start: [49.8671, 40.4093], end: [49.8671, 40.4093] }],
services: [{ id: 1, location: [49.8920, 40.3777] }],
});
await maps.cluster(customers); // group nearby stops into delivery zonesNote: VRP
vehicles/servicestake raw[lon, lat](upstream VROOM format).
Geo utilities
await maps.timezone([40.4093, 49.8671]);
await maps.elevation([[40.4093, 49.8671], [40.3777, 49.8920]]);
await maps.elevationProfile({ points: routePoints });
await maps.boundary([40.4093, 49.8671], { polygon: true });
await maps.geofence(fences, points);
await maps.solar([40.4093, 49.8671], { date: '2026-07-18' });
await maps.geometry('distance', { from: a, to: b });
await maps.convert({ point: [40.4093, 49.8671] });
await maps.country('AZ');Error handling
Every non-2xx response throws an OSRMRouteError:
import { OSRMRoute, OSRMRouteError } from 'osrmroute';
try {
await maps.route([a, b]);
} catch (err) {
if (err instanceof OSRMRouteError) {
if (err.isRateLimited) { /* 429 — plan limit reached */ }
if (err.isOutOfCoverage) { /* 422 — outside routable coverage */ }
console.error(err.status, err.code, err.message);
}
}429 and 5xx are retried automatically before they ever reach you.
Coverage
Driving routes cover every continent (mainland China excluded). Forward geocoding is worldwide; reverse geocoding is currently strongest in the Caucasus / Central Asia region and expanding to full planet coverage. See osrmroute.com/status.
License
MIT © MAMMADOFF AGENCY LLC
