An open API service indexing awesome lists of open source software.

https://github.com/universal-geocoder/universal-geocoder-js

Universal Geocoder is a universal JavaScript library for server-side and client-side geocoding applications with multiple built-in providers.
https://github.com/universal-geocoder/universal-geocoder-js

browser electron geocoder geocoding geolocation ip-geolocation isomorphic node react-native typescript universal

Last synced: about 1 year ago
JSON representation

Universal Geocoder is a universal JavaScript library for server-side and client-side geocoding applications with multiple built-in providers.

Awesome Lists containing this project

README

          

![Universal Geocoder Logo](https://raw.githubusercontent.com/universal-geocoder/universal-geocoder-js/main/assets/logo.svg)

Universal Geocoder
==================

[![CI](https://img.shields.io/github/workflow/status/universal-geocoder/universal-geocoder-js/Continuous%20Integration?event=push)](https://github.com/universal-geocoder/universal-geocoder-js/actions)
[![codecov](https://img.shields.io/codecov/c/gh/universal-geocoder/universal-geocoder-js/main)](https://codecov.io/gh/universal-geocoder/universal-geocoder-js)

[![npm](https://img.shields.io/npm/v/universal-geocoder)](https://www.npmjs.com/package/universal-geocoder)
[![downloads](https://img.shields.io/npm/dw/universal-geocoder)](https://www.npmjs.com/package/universal-geocoder)

[![dependency-count](https://badgen.net/bundlephobia/dependency-count/universal-geocoder)](https://bundlephobia.com/result?p=universal-geocoder)
[![minified-size](https://img.shields.io/bundlephobia/min/universal-geocoder)](https://bundlephobia.com/result?p=universal-geocoder)
[![tree-shaking](https://badgen.net/bundlephobia/tree-shaking/universal-geocoder)](https://bundlephobia.com/result?p=universal-geocoder)
![types](https://badgen.net/npm/types/universal-geocoder)

Universal Geocoder is a universal JavaScript library for server-side and client-side geocoding applications with multiple built-in providers.

Need geocoding 🌍️ in your website or application? Don't want to be vendor-locked to a service? ✨️ Universal Geocoder ✨️ is for you!

Depending of the chosen provider, it can use geocoding, reverse geocoding or IP geolocation.

Universal Geocoder is a TypeScript fork of [GeocoderJS](https://github.com/geocoder-php/geocoder-js), itself a port of the [Geocoder PHP](https://geocoder-php.org/) library.

This library is platform agnostic: it is available either server-side (**Node**) or client-side (**browsers**, **React Native**, **Electron**).

It aims to be compatible with a maximum of browsers (even old ones) and provides multiple ways to use it, from an old use (available in global environment, results from callbacks) to the most modern use (available as a module, async / await results).

Installation
------------

Add the library to your project:

```shell
npm install --save universal-geocoder
```

> ⚠️ **Warning**: If you need to use this library in an environment not supporting the Promise API such as Internet Explorer, you must install an ES6 Promise compatible polyfill like [es6-promise](https://github.com/jakearchibald/es6-promise).

Usage
-----

You can either use Universal Geocoder as a module (both CommonJS and ES module syntaxes are provided) or as a direct dependency.

As a module:

```javascript
import UniversalGeocoder from "universal-geocoder";

const openStreetMapGeocoder = UniversalGeocoder.createGeocoder("openstreetmap");

// async / await syntax
(async () =>
console.log(await openStreetMapGeocoder.geocode("1600 Pennsylvania Ave NW, Washington, DC"))
)();

// callback syntax
openStreetMapGeocoder.geocode("1600 Pennsylvania Ave NW, Washington, DC", (result) => {
console.log(result);
});
```

For this example, the output will be something like this:

```javascript
[
NominatimGeocoded {
coordinates: { latitude: 38.8976998, longitude: -77.03655348862276 },
bounds: {
latitudeSW: 38.8974898,
longitudeSW: -77.0368542,
latitudeNE: 38.897911,
longitudeNE: -77.0362526
},
formattedAddress: undefined,
streetNumber: '1600',
streetName: 'Pennsylvania Avenue Northwest',
subLocality: undefined,
locality: 'Washington',
postalCode: '20500',
region: 'District of Columbia',
adminLevels: [
AdminLevel {
level: 1,
name: 'District of Columbia',
code: undefined
},
AdminLevel {
level: 2,
name: 'Washington',
code: undefined
}
],
country: 'United States of America',
countryCode: 'us',
timezone: undefined,
displayName: 'White House, 1600, Pennsylvania Avenue Northwest, Washington, District of Columbia, 20500, United States of America',
osmId: 238241022,
osmType: 'way',
category: 'historic',
type: 'castle',
attribution: 'Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright'
},
// ... (other results)
]
```

If you want to use the library as a direct dependecy (for browsers only), copy `dist/universal-geocoder.js` or `dist/universal-geocoder.min.js` to your dependencies.

Universal Geocoder will be available in the global environment:

```javascript
const openStreetMapGeocoder = UniversalGeocoder.createGeocoder("openstreetmap");

openStreetMapGeocoder.geodecode("44.915", "-93.21", (result) => {
console.log(result);
});
```

For a more advanced usage, see the example below:

```javascript
import UniversalGeocoder, { ReverseQuery } from "universal-geocoder";

const googleGeocoder = UniversalGeocoder.createGeocoder({
provider: "googlemaps",
apiKey: "YOUR_API_KEY",
useSsl: true,
useJsonp: false,
// other specific provider options
});

(async () =>
console.log(await googleGeocoder.geocode({
text: "1600 Pennsylvania Ave, Washington, DC",
locale: "FR",
limit: 10,
// other specific provider parameters
}))
)();

const reverseQuery = ReverseQuery.create({
coordinates: {
latitude: "44.915",
longitude: "-93.21",
},
})
.withLocale("FR")
.withLimit(7);
(async () =>
console.log(await googleGeocoder.geodecode(reverseQuery))
)();
```

### Common Options (`createGeocoder` method)

- `useSsl`: boolean to use the HTTPS API of the providers
- `useJsonp`: boolean to use JSONP
- `apiKey`: the API key to use for the provider

### Common `geocode` parameters (`GeocodeQuery` object)

- `text`: what is searched
- `ip`: the IP searched
- `bounds` (object with `latitudeSW`, `longitudeSW`, `latitudeNE` and `longitudeNE` keys): the bounds to use (either bias or filter the results)
- `locale`: the locale to use for the query
- `limit`: the maximum number of results to have

### Common `geodecode` parameters (`ReverseQuery` object)

- `coordinates` (object with `latitude`, `longitude` keys): the coordinates to search for
- `locale`: the locale to use for the query
- `limit`: the maximum number of results to have

### Common Result Properties (`Geocoded` object)

The result of a query is a `Geocoded` object which maps the following common information:
- Coordinates (object with `latitute` and `longitude` keys)
- Bounds (object with `latitudeSW`, `longitudeSW`, `latitudeNE`, `longitudeNE` keys)
- Formatted address
- Address details: street number, street name, (sub) locality, postal code, region, administration levels, country (with its code)
- Time zone

You can either use getter methods to retrieve them or use the `toObject` method to manipulate an object containing the properties.

Providers
---------

Universal Geocoder comes with modules to integrate with various geocoding providers.

The following table summarizes the features of each:



Provider
Codename
Supports location geocoding?
Supports reverse geocoding?
Supports IP geolocation?




OpenStreetMap (Nominatim)
openstreetmap or nominatim
✅️ yes
✅️ yes
❌️ no


OpenCage
opencage
✅️ yes
✅️ yes
❌️ no


Google Maps (Geocoding API)
google or googlemaps
✅️ yes
✅️ yes
❌️ no


LocationIQ
locationiq
✅️ yes
✅️ yes
❌️ no


Mapbox
mapbox
✅️ yes
✅️ yes
❌️ no


MapQuest
mapquest
✅️ yes
✅️ yes
❌️ no


Bing
bing
✅️ yes
✅️ yes
❌️ no


Yandex
yandex
✅️ yes
✅️ yes
❌️ no


GeoPlugin
geoplugin
❌️ no
❌️ no
✅️ yes

### Specific Provider Usage

The documentation for specific provider options, parameters and results can be found [here](docs/provider_usage.md).

Special Providers
-----------------

A `chain` provider is available: it iterates over multiple providers.

For more information, see [its documentation](docs/provider_usage/chain.md).

Dumpers
-------

Dumpers transform a `Geocoded` object to another format.

### GeoJSON

[GeoJSON](https://geojson.org/) is a format for encoding a variety of geographic data structures.

#### Usage

```javascript
import UniversalGeocoder, { GeoJsonDumper } from "universal-geocoder";

const nominatimGeocoder = UniversalGeocoder.createGeocoder("nominatim");

(async () => {
const result = await nominatimGeocoder.geocode("1600 Pennsylvania Ave NW, Washington, DC");
console.log(result);
console.log("GeoJSON:", GeoJsonDumper.dump(result[0]));
})();
```

Building
--------

```shell
npm run build
```

Testing
-------

Unit and functional tests are handled by Jasmine. To run tests from the command line, use:

```shell
npm test
```

If you need to record new API calls, use:

```shell
npm run test-record
```

You can also check if the examples are running correctly.

For the Web:

```shell
npm run serve
```

Then go to http://localhost:8080/example/web, choose a provider and open the console.

For Node:

```shell
npm run ts-node -- example/node/provider.ts
```

FAQ
---

**Q: When using Universal Geocoder client-side, how to make sure the API key is not stolen?**

**A:** First of all, there are some providers that do not use an API key, like OpenStreetMap (Nominatim) or GeoPlugin.

If you want to use a provider with an API key, the best approach is generally to use Universal Geocoder in the server-side (Node) and to call it from the client-side.
This way the API key is not exposed directly.

Some providers allow to add URL restrictions when generating a token, like [Mapbox](https://docs.mapbox.com/help/getting-started/access-tokens/#url-restrictions).
Even if the token is visible, it mitigates its unwanted use since the `Origin` header [cannot be changed](https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_header_name) in a browser environment.
However, the stolen token would be still usable in a server environment (for instance with cURL).