Is there a service or API I can ping, and pass in the lat/long as parameters, where it returns the zip code that lat/long pair is within? This is US-only, so I don't have to worry about international codes, etc.
I feel like Google Maps' reverse-geocoding is too heavy for me. I'd prefer something lighter, if possible. This will be done in javascript.
It is called Reverse Geocoding (Address Lookup). To get address for lat: 40.714224, lng: -73.961452 query http://maps.googleapis.com/maps/api/geocode/json
with parameters latlng=40.714224,-73.961452&sensor=true
(example) and it returns JSON object or use http://maps.googleapis.com/maps/api/geocode/xml
to return XML response (example). It's from Google and it's free.
For the Google API, you need to use it within a Google map, according to their site:
Note: the Geocoding API may only be used in conjunction with a Google
map; geocoding results without displaying them on a map is
prohibited.
Please have a look on http://geonames.org. There is a webservice findNearbyPostalCodes (international).
Example: findNearbyPostalCodesJSON?lat=47&lng=9&username=demo
Shortened output:
{
"postalCodes": [{
"adminCode3": "1631",
"distance": "2.2072",
"postalCode": "8775",
"countryCode": "CH",
"lng": 8.998679778165283,
"placeName": "Luchsingen",
"lat": 46.980169648620375
}]
}
Limit of the demo account is 2000 queries per hour.
Google Maps API can get zip code associated with a geolocation. However if you are somewhere in middle of jungle then this API will not return anything as postal code are mapped to postal addresses. In that case you need to get zip code of nearby city.
You can use this method to do so
//Reverse GeoCode position into Address and ZipCOde
function getZipCodeFromPosition(geocoder, map,latlng,userLocationInfoWindow) {
geocoder.geocode({'location': latlng}, function(result, status) {
if (status === 'OK') {
if (result[0]) {
console.log("GeoCode Results Found:"+JSON.stringify(result));
//Display Address
document.getElementById("address").textContent = "Address: " +result[0].formatted_address;
//Update Info Window on Server Map
userLocationInfoWindow.setPosition(latlng);
userLocationInfoWindow.setContent('<IMG BORDER="0" ALIGN="Left" SRC="https://media3.giphy.com/media/IkwH4WZWgdfpu/giphy.gif" style ="width:50px; height:50px"><h6 class ="pink-text">You Are Here</h4> <p class = "purple-text" style ="margin-left:30px;">'+result[0].formatted_address+'</p>');
userLocationInfoWindow.open(map);
map.setCenter(latlng);
//Try to Get Postal Code
var postal = null;
var city = null;
var state = null;
var country = null;
for(var i=0;i<result.length;++i){
if(result[i].types[0]=="postal_code"){
postal = result[i].long_name;
}
if(result[i].types[0]=="administrative_area_level_1"){
state = result[i].long_name;
}
if(result[i].types[0]=="locality"){
city = result[i].long_name;
}
if(result[i].types[0]=="country"){
country = result[i].long_name;
}
}
if (!postal) {
geocoder.geocode({ 'location': result[0].geometry.location }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
//Postal Code Not found, Try to get Postal code for City
var result=results[0].address_components;
for(var i=0;i<result.length;++i){
if(result[i].types[0]=="postal_code"){
postal = result[i].long_name;
}
}
if (!postal) {
//Postal Code Not found
document.getElementById("postal").textContent = "No Postal Code Found for this location";
}else
{
//Postal Code found
document.getElementById("postal").textContent = "Zip Code: "+postal;
}
}
});
} else
{
//Postal Code found
document.getElementById("postal").textContent = "Zip Code: "+postal;
}
console.log("STATE: " + state);
console.log("CITY: " + city);
console.log("COUNTRY: " + country);
} else {
window.alert('No results found');
}
} else {
window.alert('Geocoder failed due to: ' + status);
}
});
}
</script>
Working example
https://codepen.io/hiteshsahu/pen/gxQyQE?editors=1010
The answer from kubetz is great, but since we have to use https to get geolocation to work (Geolocation API Removed from Unsecured Origins in Chrome 50), the call to http://api.geonames.org fails because it is not over https. A local php script, called over https, that gets from geonames.org solves the problem.
//javascript function
function getZipFromLatLong() {
var url = "getzip.php";
var formData = new FormData();
formData.append("lat", current_lat);
formData.append("long", current_long);
var r = new XMLHttpRequest();
r.open("POST", url, true);
r.onreadystatechange = function () {
if (r.readyState != 4 || r.status != 200) {
return;
} else {
data = r.responseText;
var jdata = JSON.parse(data);
document.getElementById("zip").value = jdata.postalCodes[0].postalCode;
}
}
r.send(formData);
}
//getzip.php script
<?php
$lat = $_POST["lat"];
$long = $_POST["long"];
$url = "http://api.geonames.org/findNearbyPostalCodesJSON?username=demo&lat=" . $lat . "&lng=" . $long;
$content = file_get_contents($url);
//the output is json, so just return it as-is
die($content);
?>