{"id":26606867,"url":"https://github.com/universal-geocoder/universal-geocoder-js","last_synced_at":"2025-04-09T20:33:15.367Z","repository":{"id":49147647,"uuid":"282179933","full_name":"universal-geocoder/universal-geocoder-js","owner":"universal-geocoder","description":"Universal Geocoder is a universal JavaScript library for server-side and client-side geocoding applications with multiple built-in providers.","archived":false,"fork":false,"pushed_at":"2021-06-27T14:45:51.000Z","size":17362,"stargazers_count":11,"open_issues_count":2,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-18T15:45:02.167Z","etag":null,"topics":["browser","electron","geocoder","geocoding","geolocation","ip-geolocation","isomorphic","node","react-native","typescript","universal"],"latest_commit_sha":null,"homepage":"https://universal-geocoder.github.io/universal-geocoder-js/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/universal-geocoder.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-07-24T09:37:31.000Z","updated_at":"2024-04-12T23:28:45.000Z","dependencies_parsed_at":"2022-08-25T15:21:04.966Z","dependency_job_id":null,"html_url":"https://github.com/universal-geocoder/universal-geocoder-js","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/universal-geocoder%2Funiversal-geocoder-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/universal-geocoder%2Funiversal-geocoder-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/universal-geocoder%2Funiversal-geocoder-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/universal-geocoder%2Funiversal-geocoder-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/universal-geocoder","download_url":"https://codeload.github.com/universal-geocoder/universal-geocoder-js/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248107787,"owners_count":21049008,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["browser","electron","geocoder","geocoding","geolocation","ip-geolocation","isomorphic","node","react-native","typescript","universal"],"created_at":"2025-03-23T22:23:48.729Z","updated_at":"2025-04-09T20:33:15.333Z","avatar_url":"https://github.com/universal-geocoder.png","language":"TypeScript","readme":"![Universal Geocoder Logo](https://raw.githubusercontent.com/universal-geocoder/universal-geocoder-js/main/assets/logo.svg)\n\nUniversal Geocoder\n==================\n\n[![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)\n[![codecov](https://img.shields.io/codecov/c/gh/universal-geocoder/universal-geocoder-js/main)](https://codecov.io/gh/universal-geocoder/universal-geocoder-js)\n\n[![npm](https://img.shields.io/npm/v/universal-geocoder)](https://www.npmjs.com/package/universal-geocoder)\n[![downloads](https://img.shields.io/npm/dw/universal-geocoder)](https://www.npmjs.com/package/universal-geocoder)\n\n[![dependency-count](https://badgen.net/bundlephobia/dependency-count/universal-geocoder)](https://bundlephobia.com/result?p=universal-geocoder)\n[![minified-size](https://img.shields.io/bundlephobia/min/universal-geocoder)](https://bundlephobia.com/result?p=universal-geocoder)\n[![tree-shaking](https://badgen.net/bundlephobia/tree-shaking/universal-geocoder)](https://bundlephobia.com/result?p=universal-geocoder)\n![types](https://badgen.net/npm/types/universal-geocoder)\n\nUniversal Geocoder is a universal JavaScript library for server-side and client-side geocoding applications with multiple built-in providers.\n\nNeed geocoding 🌍️ in your website or application? Don't want to be vendor-locked to a service? ✨️ Universal Geocoder ✨️ is for you!\n\nDepending of the chosen provider, it can use geocoding, reverse geocoding or IP geolocation.\n\nUniversal 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.\n\nThis library is platform agnostic: it is available either server-side (**Node**) or client-side (**browsers**, **React Native**, **Electron**).\n\nIt 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).\n\nInstallation\n------------\n\nAdd the library to your project:\n\n```shell\nnpm install --save universal-geocoder\n```\n\n\u003e ⚠️ **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).\n\nUsage\n-----\n\nYou can either use Universal Geocoder as a module (both CommonJS and ES module syntaxes are provided) or as a direct dependency.\n\nAs a module:\n\n```javascript\nimport UniversalGeocoder from \"universal-geocoder\";\n\nconst openStreetMapGeocoder = UniversalGeocoder.createGeocoder(\"openstreetmap\");\n\n// async / await syntax\n(async () =\u003e\n  console.log(await openStreetMapGeocoder.geocode(\"1600 Pennsylvania Ave NW, Washington, DC\"))\n)();\n\n// callback syntax\nopenStreetMapGeocoder.geocode(\"1600 Pennsylvania Ave NW, Washington, DC\", (result) =\u003e {\n  console.log(result);\n});\n```\n\nFor this example, the output will be something like this:\n\n```javascript\n[\n  NominatimGeocoded {\n    coordinates: { latitude: 38.8976998, longitude: -77.03655348862276 },\n    bounds: {\n      latitudeSW: 38.8974898,\n      longitudeSW: -77.0368542,\n      latitudeNE: 38.897911,\n      longitudeNE: -77.0362526\n    },\n    formattedAddress: undefined,\n    streetNumber: '1600',\n    streetName: 'Pennsylvania Avenue Northwest',\n    subLocality: undefined,\n    locality: 'Washington',\n    postalCode: '20500',\n    region: 'District of Columbia',\n    adminLevels: [\n      AdminLevel {\n        level: 1,\n        name: 'District of Columbia',\n        code: undefined\n      },\n      AdminLevel {\n        level: 2,\n        name: 'Washington',\n        code: undefined\n      }\n    ],\n    country: 'United States of America',\n    countryCode: 'us',\n    timezone: undefined,\n    displayName: 'White House, 1600, Pennsylvania Avenue Northwest, Washington, District of Columbia, 20500, United States of America',\n    osmId: 238241022,\n    osmType: 'way',\n    category: 'historic',\n    type: 'castle',\n    attribution: 'Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright'\n  },\n  // ... (other results)\n]\n```\n\nIf 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.\n\nUniversal Geocoder will be available in the global environment:\n\n```javascript\nconst openStreetMapGeocoder = UniversalGeocoder.createGeocoder(\"openstreetmap\");\n\nopenStreetMapGeocoder.geodecode(\"44.915\", \"-93.21\", (result) =\u003e {\n  console.log(result);\n});\n```\n\nFor a more advanced usage, see the example below:\n\n```javascript\nimport UniversalGeocoder, { ReverseQuery } from \"universal-geocoder\";\n\nconst googleGeocoder = UniversalGeocoder.createGeocoder({\n  provider: \"googlemaps\",\n  apiKey: \"YOUR_API_KEY\",\n  useSsl: true,\n  useJsonp: false,\n  // other specific provider options\n});\n\n(async () =\u003e\n  console.log(await googleGeocoder.geocode({\n    text: \"1600 Pennsylvania Ave, Washington, DC\",\n    locale: \"FR\",\n    limit: 10,\n    // other specific provider parameters\n  }))\n)();\n\nconst reverseQuery = ReverseQuery.create({\n  coordinates: {\n    latitude: \"44.915\",\n    longitude: \"-93.21\",\n  },\n})\n.withLocale(\"FR\")\n.withLimit(7);\n(async () =\u003e\n  console.log(await googleGeocoder.geodecode(reverseQuery))\n)();\n```\n\n### Common Options (`createGeocoder` method)\n\n- `useSsl`: boolean to use the HTTPS API of the providers\n- `useJsonp`: boolean to use JSONP\n- `apiKey`: the API key to use for the provider\n\n### Common `geocode` parameters (`GeocodeQuery` object)\n\n- `text`: what is searched\n- `ip`: the IP searched\n- `bounds` (object with `latitudeSW`, `longitudeSW`, `latitudeNE` and `longitudeNE` keys): the bounds to use (either bias or filter the results)\n- `locale`: the locale to use for the query\n- `limit`: the maximum number of results to have\n\n### Common `geodecode` parameters (`ReverseQuery` object)\n\n- `coordinates` (object with `latitude`, `longitude` keys): the coordinates to search for\n- `locale`: the locale to use for the query\n- `limit`: the maximum number of results to have\n\n### Common Result Properties (`Geocoded` object)\n\nThe result of a query is a `Geocoded` object which maps the following common information:\n- Coordinates (object with `latitute` and `longitude` keys)\n- Bounds (object with `latitudeSW`, `longitudeSW`, `latitudeNE`, `longitudeNE` keys)\n- Formatted address\n- Address details: street number, street name, (sub) locality, postal code, region, administration levels, country (with its code)\n- Time zone\n\nYou can either use getter methods to retrieve them or use the `toObject` method to manipulate an object containing the properties.\n\nProviders\n---------\n\nUniversal Geocoder comes with modules to integrate with various geocoding providers.\n\nThe following table summarizes the features of each:\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth\u003eProvider\u003c/th\u003e\n      \u003cth\u003eCodename\u003c/th\u003e\n      \u003cth\u003eSupports location geocoding?\u003c/th\u003e\n      \u003cth\u003eSupports reverse geocoding?\u003c/th\u003e\n      \u003cth\u003eSupports IP geolocation?\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eOpenStreetMap (Nominatim)\u003c/td\u003e\n      \u003ctd\u003eopenstreetmap or nominatim\u003c/td\u003e\n      \u003ctd\u003e✅️ yes\u003c/td\u003e\n      \u003ctd\u003e✅️ yes\u003c/td\u003e\n      \u003ctd\u003e❌️ no\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eOpenCage\u003c/td\u003e\n      \u003ctd\u003eopencage\u003c/td\u003e\n      \u003ctd\u003e✅️ yes\u003c/td\u003e\n      \u003ctd\u003e✅️ yes\u003c/td\u003e\n      \u003ctd\u003e❌️ no\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eGoogle Maps (Geocoding API)\u003c/td\u003e\n      \u003ctd\u003egoogle or googlemaps\u003c/td\u003e\n      \u003ctd\u003e✅️ yes\u003c/td\u003e\n      \u003ctd\u003e✅️ yes\u003c/td\u003e\n      \u003ctd\u003e❌️ no\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eLocationIQ\u003c/td\u003e\n      \u003ctd\u003elocationiq\u003c/td\u003e\n      \u003ctd\u003e✅️ yes\u003c/td\u003e\n      \u003ctd\u003e✅️ yes\u003c/td\u003e\n      \u003ctd\u003e❌️ no\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eMapbox\u003c/td\u003e\n      \u003ctd\u003emapbox\u003c/td\u003e\n      \u003ctd\u003e✅️ yes\u003c/td\u003e\n      \u003ctd\u003e✅️ yes\u003c/td\u003e\n      \u003ctd\u003e❌️ no\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eMapQuest\u003c/td\u003e\n      \u003ctd\u003emapquest\u003c/td\u003e\n      \u003ctd\u003e✅️ yes\u003c/td\u003e\n      \u003ctd\u003e✅️ yes\u003c/td\u003e\n      \u003ctd\u003e❌️ no\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eBing\u003c/td\u003e\n      \u003ctd\u003ebing\u003c/td\u003e\n      \u003ctd\u003e✅️ yes\u003c/td\u003e\n      \u003ctd\u003e✅️ yes\u003c/td\u003e\n      \u003ctd\u003e❌️ no\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eYandex\u003c/td\u003e\n      \u003ctd\u003eyandex\u003c/td\u003e\n      \u003ctd\u003e✅️ yes\u003c/td\u003e\n      \u003ctd\u003e✅️ yes\u003c/td\u003e\n      \u003ctd\u003e❌️ no\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eGeoPlugin\u003c/td\u003e\n      \u003ctd\u003egeoplugin\u003c/td\u003e\n      \u003ctd\u003e❌️ no\u003c/td\u003e\n      \u003ctd\u003e❌️ no\u003c/td\u003e\n      \u003ctd\u003e✅️ yes\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n### Specific Provider Usage\n\nThe documentation for specific provider options, parameters and results can be found [here](docs/provider_usage.md).\n\nSpecial Providers\n-----------------\n\nA `chain` provider is available: it iterates over multiple providers.\n\nFor more information, see [its documentation](docs/provider_usage/chain.md).\n\nDumpers\n-------\n\nDumpers transform a `Geocoded` object to another format.\n\n### GeoJSON\n\n[GeoJSON](https://geojson.org/) is a format for encoding a variety of geographic data structures.\n\n#### Usage\n\n```javascript\nimport UniversalGeocoder, { GeoJsonDumper } from \"universal-geocoder\";\n\nconst nominatimGeocoder = UniversalGeocoder.createGeocoder(\"nominatim\");\n\n(async () =\u003e {\n  const result = await nominatimGeocoder.geocode(\"1600 Pennsylvania Ave NW, Washington, DC\");\n  console.log(result);\n  console.log(\"GeoJSON:\", GeoJsonDumper.dump(result[0]));\n})();\n```\n\nBuilding\n--------\n\n```shell\nnpm run build\n```\n\nTesting\n-------\n\nUnit and functional tests are handled by Jasmine. To run tests from the command line, use:\n\n```shell\nnpm test\n```\n\nIf you need to record new API calls, use:\n\n```shell\nnpm run test-record\n```\n\nYou can also check if the examples are running correctly.\n\nFor the Web:\n\n```shell\nnpm run serve\n```\n\nThen go to http://localhost:8080/example/web, choose a provider and open the console.\n\nFor Node:\n\n```shell\nnpm run ts-node -- example/node/provider.ts\n```\n\nFAQ\n---\n\n**Q: When using Universal Geocoder client-side, how to make sure the API key is not stolen?**\n\n**A:** First of all, there are some providers that do not use an API key, like OpenStreetMap (Nominatim) or GeoPlugin.\n\nIf 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.\nThis way the API key is not exposed directly.\n\nSome providers allow to add URL restrictions when generating a token, like [Mapbox](https://docs.mapbox.com/help/getting-started/access-tokens/#url-restrictions).\nEven 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.\nHowever, the stolen token would be still usable in a server environment (for instance with cURL).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funiversal-geocoder%2Funiversal-geocoder-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funiversal-geocoder%2Funiversal-geocoder-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funiversal-geocoder%2Funiversal-geocoder-js/lists"}