3

I am looking for some API that will return me the info of location from Latitude and Longitude parameters.

I tried using Google Geocoding but it doesn't work well for anything water-related, like it doesn't consider a water to be part of a country even if its just next to the coast or inside some lake.

Expected input: 37.29978035556258,-75.66096298677134

And output: "Virginia, United States" or "Virginia, USA" etc.

In Google Geocoding it gives

"results" : [],
"status" : "ZERO_RESULTS"

Maybe there is some API parameter to give the closest location result in Google Geocoding? I couldn't find one.

6
  • 4
    This process is called "reverse geocoding" and the expected output is an address. There are no addresses in open water, which is why Google is returning nothing.
    – Mintx
    Commented Jan 12, 2022 at 16:53
  • Is there any way of getting the closest address? Or getting Water Area name?
    – Chris K
    Commented Jan 12, 2022 at 18:53
  • 1
    Using open streetmap data. There, countries extend also into the sea.
    – Babel
    Commented Jan 12, 2022 at 19:27
  • @Babel yes they extend but just a little bit, is there an option to get the closest address? or even the closest region, country, county, anything?
    – Chris K
    Commented Jan 12, 2022 at 23:45
  • 1
    Check this API: github.com/osm-search/Nominatim Demo: nominatim.openstreetmap.org/ui/… Commented Jan 13, 2022 at 4:19

7 Answers 7

2

The thing you are looking for is reverse geocoding. It means, that you want to extract the address from the certain coordinates.

I think, this article might be helpful for you:

http://www.mkrgeo-blog.com/reverse-geocoding-in-excel-without-loosing-money/

As it bounds all available methods for getting the addresses from coordinates for free. However they're mostly based on VBA Excel instead of API programming language.

Alternatively you can use the geocoding scripts for Google Sheets

https://willgeary.github.io/data/2016/11/04/Geocoding-with-Google-Sheets.html

They should be still free, although not more than 1000 records daily is supported. When setting up your account, you can paste this code

https://github.com/OpenCageData/opencagedata-googlesheets-scripts/blob/master/opencage.js

and run it as advised in the text above.

2

Option# 1

Marinetraffic.com has an API to reverse geocode based on Marine Borders. For the lat/long example (37.29978035556258,-75.66096298677134) you provided this API returns the following response

GET https://services.marinetraffic.com/api/reversegeocode/<YOUR-API-KEY>?protocol=xml&coordinates=37.29978035556258%2C-75.66096298677134

    

RESPONSE:

<?xml version="1.0" encoding="UTF-8"?>
    <RESPONSE>
       <ITEM ID="143" NAME="US East Coast" TYPE="Standard Area" SUBTYPE="Trade Area" COUNTRY="" UNLOCODE="" GEOMETRY_CENTER="37.7656,-73.7004" DISTANCE="0" TERMINAL="" URL="https://marinetraffic.com/en/details/areas/areaId:143" />
       <ITEM ID="4" NAME="US Atlantic ECA" TYPE="Standard Area" SUBTYPE="ECA Zone" COUNTRY="" UNLOCODE="" GEOMETRY_CENTER="39.2229,-74.2087" DISTANCE="0" TERMINAL="" URL="https://marinetraffic.com/en/details/areas/areaId:4" />
       <ITEM ID="1814" NAME="United States Exclusive Economic Zone (Atlantic)" TYPE="Standard Area" SUBTYPE="Exclusive Economic Zone" COUNTRY="" UNLOCODE="" GEOMETRY_CENTER="32.6811,-79.4974" DISTANCE="0" TERMINAL="" URL="https://marinetraffic.com/en/details/areas/areaId:1814" />
       <ITEM ID="784" NAME="North America Winter Seasonal Area" TYPE="Standard Area" SUBTYPE="Load Line Zone" COUNTRY="" UNLOCODE="" GEOMETRY_CENTER="40.2027,-73.55" DISTANCE="0" TERMINAL="" URL="https://marinetraffic.com/en/details/areas/areaId:784" />
       <ITEM ID="1085" NAME="IV United States" TYPE="Standard Area" SUBTYPE="NAVAREA" COUNTRY="" UNLOCODE="" GEOMETRY_CENTER="29.4104,-75.3306" DISTANCE="0" TERMINAL="" URL="https://marinetraffic.com/en/details/areas/areaId:1085" />
    </RESPONSE>

Option:2 Since most marine border data/API would be commercial and will not yield the results of nearest city/port. I would suggest

  1. Download Offline Marine border dataset (available from source like https://www.marineregions.org/downloads.phphttps://www.marineregions.org/downloads.php) .
  2. Download offline country and admin borders dataset ( available from many sources including OSM, Google, HERE, Bing)
  3. For every query point first query the country marine border based on #1
  4. For country obtained from #3 obtain its border from #2 and snap the query point to nearest point on the country border.
  5. Reverse geocode snapped point from #4 to obtain details of admin regions like cities etc.
2
+25

You can also use the OpenStreetMap Nominatim service, which has a handy JSON api.

Edit: You can specify the 'Max Zoom' setting, your issue might be not finding good results at the default zoom level...

4
  • I am using this already but it doesn't work well with Water
    – Chris K
    Commented Jan 18, 2022 at 11:23
  • So, I played with the zoom settings, it looks like you get OK results at the Town/City level. I think some of this is going to have to do with straight-line distances to curved coastlines, so your use case might need some refining or expanding on
    – nizz0k
    Commented Jan 18, 2022 at 11:39
  • In worst case ~100km (points on water ~100km from land)
    – Chris K
    Commented Jan 18, 2022 at 11:40
  • yeah, I think you'd need to do a custom approach this in a spatial database or something to really be able to control your results. I'm pretty sure you can get under the hood data on how the API's decide what's the closest address, but with the extreme curviness of coastlines you're going to have a lot of edge cases with 100km distances.
    – nizz0k
    Commented Jan 18, 2022 at 11:49
0

Google's Reverse Geocoding API would be enough, just paste your pair of coordinates there and check the output.

0

Check out ESRI's reverse geocoding api

https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/reverseGeocode?<PARAMETERS>
2
0

This answer considers the Geocoding API provided by the Google Maps Platform in addressing the question, as this is the API which the author mentioned in the description of the question.

Using the Geocoding API requires an API key with the appropriate privileges, and to obtain it, one has to set up a billing account in Google Cloud Console. However, the monthly free limit for API calls is so high that it is difficult to imagine exceeding that for academic projects or even small business needs.

To know how to setup the billing account and starting to use the Geocoding API, see the nicely explained guide by Google and the references therein. Obtain an API key following the instructions there, and then the API calls for geocoding and reverse geocoding can be made.

In geocoding, one needs to provide an address in a prescribed format of GET http request, as described here. Similarly, in reverse geocoding, another GET request has to be made, which is

https://maps.googleapis.com/maps/api/geocode/json?latlng=LATITUDE,LONGITUDE&key=API_KEY

Replace LATITUDE with the latitude value, LONGITUDE with the longitude value and API_KEY with your API key for geocoding. For example, paste the following line (after replacing API_KEY with your API key) in one of your browser tab to obtain the reverse geocoding response in the JSON format:

https://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&key=API_KEY

Note that, in this step, there is a mistake in Google's official documentation as on the time of writing this answer: Google's documentation contains this link as an example request for reverse geocoding:

https://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&amp;key=YOUR_API_KEY

However, it won't work unless the amp; phrase is removed. One needs to remove amp; and replace YOUR_API_KEY with the API key of yours for geocoding to get the proper results from the GET request.

Now, in the question, LATITUDE = 37.29978035556258, LONGITUDE = -75.66096298677134. So, let's form the correct request string (sans the actual API key, which is to be placed by the user):

https://maps.googleapis.com/maps/api/geocode/json?latlng=37.29978035556258,-75.66096298677134&key=API_KEY

After replacing API_KEY with your own API key, paste the link in a browser tab (or, make a GET request through any programming language or application of your preference). The result obtained (in raw data) is

{
   "plus_code" : {
      "compound_code" : "78XQ+WJ7 Broadwater, VA, USA",
      "global_code" : "879678XQ+WJ7"
   },
   "results" : [
      {
         "address_components" : [
            {
               "long_name" : "78XQ+WJ",
               "short_name" : "78XQ+WJ",
               "types" : [ "plus_code" ]
            },
            {
               "long_name" : "Broadwater",
               "short_name" : "Broadwater",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "Northampton County",
               "short_name" : "Northampton County",
               "types" : [ "administrative_area_level_2", "political" ]
            },
            {
               "long_name" : "Virginia",
               "short_name" : "VA",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "United States",
               "short_name" : "US",
               "types" : [ "country", "political" ]
            }
         ],
         "formatted_address" : "78XQ+WJ Broadwater, VA, USA",
         "geometry" : {
            "bounds" : {
               "northeast" : {
                  "lat" : 37.299875,
                  "lng" : -75.66087499999999
               },
               "southwest" : {
                  "lat" : 37.29975,
                  "lng" : -75.661
               }
            },
            "location" : {
               "lat" : 37.2997804,
               "lng" : -75.660963
            },
            "location_type" : "GEOMETRIC_CENTER",
            "viewport" : {
               "northeast" : {
                  "lat" : 37.3011614802915,
                  "lng" : -75.65958851970849
               },
               "southwest" : {
                  "lat" : 37.29846351970851,
                  "lng" : -75.6622864802915
               }
            }
         },
         "place_id" : "GhIJq_1CNF-mQkARbTfBN03qUsA",
         "plus_code" : {
            "compound_code" : "78XQ+WJ Broadwater, VA, USA",
            "global_code" : "879678XQ+WJ"
         },
         "types" : [ "plus_code" ]
      },
      {
         "address_components" : [
            {
               "long_name" : "United States",
               "short_name" : "US",
               "types" : [ "country", "political" ]
            }
         ],
         "formatted_address" : "United States",
         "geometry" : {
            "bounds" : {
               "northeast" : {
                  "lat" : 71.5388001,
                  "lng" : -66.885417
               },
               "southwest" : {
                  "lat" : 18.7763,
                  "lng" : 170.5957
               }
            },
            "location" : {
               "lat" : 37.09024,
               "lng" : -95.712891
            },
            "location_type" : "APPROXIMATE",
            "viewport" : {
               "northeast" : {
                  "lat" : 71.5388001,
                  "lng" : -66.885417
               },
               "southwest" : {
                  "lat" : 18.7763,
                  "lng" : 170.5957
               }
            }
         },
         "place_id" : "ChIJCzYy5IS16lQRQrfeQ5K5Oxw",
         "types" : [ "country", "political" ]
      }
   ],
   "status" : "OK"
}

So, clearly, the result returns the country as the United States, as well as the state (administrative_area_level_1) as Virginia. Other lower level address components are also returned, e.g., Northampton County.

If one is not interested in the complete detailed result, optional parameters may be supplied to get only the intended component of the result. For example, if one requires only the country information, the following format would work:

https://maps.googleapis.com/maps/api/geocode/json?latlng=37.29978035556258,-75.66096298677134&result_type=country&key=API_KEY

The result is:

{
   "plus_code" : {
      "compound_code" : "78XQ+WJ7 Broadwater, VA, USA",
      "global_code" : "879678XQ+WJ7"
   },
   "results" : [
      {
         "address_components" : [
            {
               "long_name" : "United States",
               "short_name" : "US",
               "types" : [ "country", "political" ]
            }
         ],
         "formatted_address" : "United States",
         "geometry" : {
            "bounds" : {
               "northeast" : {
                  "lat" : 71.5388001,
                  "lng" : -66.885417
               },
               "southwest" : {
                  "lat" : 18.7763,
                  "lng" : 170.5957
               }
            },
            "location" : {
               "lat" : 37.09024,
               "lng" : -95.712891
            },
            "location_type" : "APPROXIMATE",
            "viewport" : {
               "northeast" : {
                  "lat" : 71.5388001,
                  "lng" : -66.885417
               },
               "southwest" : {
                  "lat" : 18.7763,
                  "lng" : 170.5957
               }
            }
         },
         "place_id" : "ChIJCzYy5IS16lQRQrfeQ5K5Oxw",
         "types" : [ "country", "political" ]
      }
   ],
   "status" : "OK"
}

However, parsing the plus code would yield the state information also.

There are other optional arguments, which are described in the official documentation.

Now, the coordinates given in the question was within the territorial waters of a country. What happens if one gives coordinates of the point in the middle of the ocean to the API call? To see this, let's set LATITUDE=37.323285561840336, LONGITUDE=-66.47779150961728 in the API call:

https://maps.googleapis.com/maps/api/geocode/json?latlng=37.323285561840336,-66.47779150961728&key=API_KEY

The following image shows the position of this point in the middle of the ocean: point in the ocean Result of the API call:

{
   "plus_code" : {
      "global_code" : "879M8GFC+8V8"
   },
   "results" : [
      {
         "address_components" : [
            {
               "long_name" : "879M8GFC+8V",
               "short_name" : "879M8GFC+8V",
               "types" : [ "plus_code" ]
            }
         ],
         "formatted_address" : "879M8GFC+8V",
         "geometry" : {
            "bounds" : {
               "northeast" : {
                  "lat" : 37.323375,
                  "lng" : -66.47775
               },
               "southwest" : {
                  "lat" : 37.32325,
                  "lng" : -66.477875
               }
            },
            "location" : {
               "lat" : 37.3232856,
               "lng" : -66.4777915
            },
            "location_type" : "GEOMETRIC_CENTER",
            "viewport" : {
               "northeast" : {
                  "lat" : 37.3246614802915,
                  "lng" : -66.4764635197085
               },
               "southwest" : {
                  "lat" : 37.3219635197085,
                  "lng" : -66.47916148029151
               }
            }
         },
         "place_id" : "GhIJRaIrbGGpQkARorPMIpSeUMA",
         "plus_code" : {
            "global_code" : "879M8GFC+8V"
         },
         "types" : [ "plus_code" ]
      }
   ],
   "status" : "OK"
}

Here, only the plus code is there in the address field. This is because the point is outside of the political boundary of any country, and so it does not have an usual descriptive address.

However, one shortcoming of the Google Geocoding API is that it may yield no result if the location is very remote. In such a case, the value of the "status" field is "ZERO_RESULTS".

Now, a query of interest may be to find the name of the nearest country or political territory of a given pair of latitude and longitude coordinates. Unfortunately, the Google Geocoding API is not capable of providing that. It can only provide the latitude and longitude of a given address (geocoding) or the address of a given pair of latitude and longitude (reverse geocoding). Closest location results cannot be obtained from the Google Geocoding API currently. All the required and optional parameters of the API calls for geocoding and reverse geocoding are described here. Getting the closest territorial location from a given point outside any political boundaries would require a program which would make API calls to Geocoding API for points at increasing distance from the given given point, until a territorial address is returned.

0

I tested the following platforms for how each of the platforms handle something in the water. location is a shipwreck called the Thistlegorm in the Red Sea.

local-reverse-geocoder ✅

I was using this originally and it works very well, created by a googler, but it requires downloading a 2GB file of data and would increase the memory of my node server, which lead me to search for a service instead, without realizing that most completely fail on water coordinates. https://github.com/tomayac/local-reverse-geocoder

arcgis ✅

Doesn't have a way to translate to a language, so results are in arabic. https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/reverseGeocode?location=34.2567%2C27.8133&f=json

nominatim ✅

https://nominatim.openstreetmap.org/reverse?lat=27.8133&lon=34.2567&format=json&language=en

bing ❌

errors

gmaps ❌

returns empty result except for plus code

mapbox ❌

empty result

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.