geojson-getter
v1.0.0
Published
Resolve GeoJSON for OpenStreetMap relations via OSM relation ID or Wikidata ID
Downloads
157
Maintainers
Readme
geojson-getter
A TypeScript library that resolves GeoJSON for OpenStreetMap relations, either directly by OSM relation ID or via a Wikidata ID lookup.
How it works
- Wikidata lookup — given a Wikidata ID, fetches the entity and extracts the OSM relation ID from the P402 statement
- Overpass query — fetches the relation geometry from the Overpass API using
[out:json];relation(id);out geom qt; - GeoJSON conversion — converts the Overpass response to GeoJSON using osmtogeojson
Multiple Overpass mirrors are tried in sequence; the first successful response is used. All functions return a Result type — errors never throw, and every failure mode is typed.
Fair use
This library queries the Wikidata REST API and public Overpass API mirrors. Both are free, community-funded services — please use them responsibly:
- Cache results wherever possible. Relation geometry rarely changes; re-fetching on every request is unnecessary load on shared infrastructure.
- Set a meaningful
userAgentthat identifies your application and includes a contact URL. Instance operators use this to reach you if your usage causes issues. - Do not use this library for bulk or batch processing without running your own Overpass instance. Public mirrors are not intended for high-volume automated queries.
- Respect rate limits. A 429 response means you are sending too many requests. Back off and retry with delays rather than switching mirrors aggressively.
Each Overpass mirror operates independently and may have its own usage policy — check the terms of the specific mirror you are using. For large-scale usage, consider hosting your own Overpass instance using overpass-api.de's Docker image and passing it via overpassApiUrls.
Wikidata API usage policy: https://www.wikidata.org/wiki/Wikidata:Data_access
Overpass API: https://wiki.openstreetmap.org/wiki/Overpass_API
Usage
By OSM relation ID
import { getGeojsonFromOsmRelationId } from 'geojson-getter';
const result = await getGeojsonFromOsmRelationId({
osmId: 62484,
userAgent: 'myapp/1.0 (https://github.com/myorg/myrepo)',
});
if (!result.ok) {
switch (result.error.type) {
case 'invalid_osm_id': // bad input
case 'no_elements': // relation exists but has no geometry
case 'overpass_failed': // all mirrors exhausted; result.error.attempts has per-URL details
case 'geojson_conversion_failed':
}
return;
}
console.log(result.value); // GeoJSON FeatureCollectionCustom Overpass mirrors
const result = await getGeojsonFromOsmRelationId({
osmId: 62484,
userAgent: 'myapp/1.0 (https://github.com/myorg/myrepo)',
overpassApiUrls: [
'https://overpass-api.de/api/interpreter',
'https://my-own-mirror.example.com/api/interpreter',
],
});By Wikidata ID
import { getGeojsonFromWikidataId } from 'geojson-getter';
const result = await getGeojsonFromWikidataId({
wikidataId: 'Q3974',
userAgent: 'myapp/1.0 (https://github.com/myorg/myrepo)',
});
if (!result.ok) {
switch (result.error.type) {
case 'no_osm_id_for_wikidata': // entity exists but has no P402 statement
case 'wikidata_failed': // Wikidata request failed
case 'no_elements':
case 'overpass_failed':
case 'geojson_conversion_failed':
}
return;
}
console.log(result.value); // GeoJSON FeatureCollectionError types
All functions return a Result discriminated union — check result.ok before
accessing result.value (success) or result.error (failure).
type GeojsonError =
| { type: 'invalid_osm_id'; osmId: string }
| { type: 'no_osm_id_for_wikidata'; wikidataId: string }
| { type: 'wikidata_failed'; error: WikidataError }
| { type: 'overpass_failed'; attempts: OverpassAttempt[] }
| { type: 'geojson_conversion_failed'; cause: unknown }
| { type: 'no_elements'; osmId: string };
type WikidataError =
| { type: 'network_error'; cause: unknown }
| { type: 'http_error'; status: number };
type OverpassAttempt = {
url: string;
error:
| { type: 'network_error'; cause: unknown }
| { type: 'http_error'; status: number }
| { type: 'overpass_error'; cause: unknown };
};OverpassAttempt contains the URL that was tried and the specific error (network_error, http_error, or overpass_error) so callers have full visibility into which mirrors failed and why.
User agent
Overpass mirrors require a descriptive User-Agent to identify your application. The conventional format is:
appname/version (contact-or-url)Omitting it or using a generic value will result in 403 or 429 responses from most mirrors.
Default Overpass mirrors
Requests are tried in order against:
- https://overpass.private.coffee/api/interpreter
- https://maps.mail.ru/osm/tools/overpass/api/interpreter
- https://overpass-api.de/api/interpreter
Development
Setup
npm installTesting
# run once
npm test
# watch mode
npm run test:watch
# with coverage
npx vitest run --coverageNo tests make real HTTP requests. Fetch and module dependencies are fully mocked.
