How to get Place ID of city from Latitude/Longitude using Facebook API

Stan James picture Stan James · Feb 3, 2012 · Viewed 7.2k times · Source

I need to find the Facebook place for the city for many lat/long points. The actual points refer to personal addresses, so there are no exact place ID's to look for as in the case of a business.

For testing, I was looking for the town of Red Feather Lakes, CO.

  • The graph search function will return a lot of places, but does not return cities Example

  • Raw FQL does not let you search by lat/long, and has no concept of "nearby" anyway. Example

  • An FQL query by ID reveals that there is an least a "Display Subtext" field which indicates that object is a city. Example

Thanks for any help. I have over 80 years of dated and geotagged photos of my dad that he would love to see on his timeline!

EDIT

Cities are not in the place table, they are only in the page table. There is an undocumented distance() FQL function, but it only works in the place table. (Via this SO answer.)

This works:

SELECT name,description,geometry,latitude,longitude, display_subtext 
FROM place 
WHERE distance(latitude, longitude, "40.801985", "-105.593719") < 50000

But this gives an error "distance is not valid in table page":

SELECT page_id,name,description,type,location 
FROM page 
WHERE distance(
  location.latitude,location.longitude,
  "40.801985", "-105.593719") < 50000

Answer

Stan James picture Stan James · Feb 3, 2012

It's a glorious hack, but this code works. The trick is to make two queries. First we look for places near our point. This returns a lot of business places. We then take the city of one of these places, and use this to look in the page table for that city's page. There seems to be a standard naming conventions for cities, but different for US and non-US cities.

Some small cities have various spellings in the place table, so the code loops through the returned places until it finds a match in the page table.

$fb_token = 'YOUR_TOKEN';

// Red Feather Lakes, Colorado
$lat = '40.8078';
$long = '-105.579';
// Karlsruhe, Germany
$lat = '49.037868';
$long = '8.350124';

$states_arr  = array('AL'=>"Alabama",'AK'=>"Alaska",'AZ'=>"Arizona",'AR'=>"Arkansas",'CA'=>"California",'CO'=>"Colorado",'CT'=>"Connecticut",'DE'=>"Delaware",'FL'=>"Florida",'GA'=>"Georgia",'HI'=>"Hawaii",'ID'=>"Idaho",'IL'=>"Illinois", 'IN'=>"Indiana", 'IA'=>"Iowa",  'KS'=>"Kansas",'KY'=>"Kentucky",'LA'=>"Louisiana",'ME'=>"Maine",'MD'=>"Maryland", 'MA'=>"Massachusetts",'MI'=>"Michigan",'MN'=>"Minnesota",'MS'=>"Mississippi",'MO'=>"Missouri",'MT'=>"Montana",'NE'=>"Nebraska",'NV'=>"Nevada",'NH'=>"New Hampshire",'NJ'=>"New Jersey",'NM'=>"New Mexico",'NY'=>"New York",'NC'=>"North Carolina",'ND'=>"North Dakota",'OH'=>"Ohio",'OK'=>"Oklahoma", 'OR'=>"Oregon",'PA'=>"Pennsylvania",'RI'=>"Rhode Island",'SC'=>"South Carolina",'SD'=>"South Dakota",'TN'=>"Tennessee",'TX'=>"Texas",'UT'=>"Utah",'VT'=>"Vermont",'VA'=>"Virginia",'WA'=>"Washington",'DC'=>"Washington D.C.",'WV'=>"West Virginia",'WI'=>"Wisconsin",'WY'=>"Wyoming");

$place_search = json_decode(file_get_contents('https://graph.facebook.com/search?type=place&center=' . $lat . ',' . $long . '&distance=10000&access_token=' . $fb_token));
foreach($place_search->data as $result) {
  if ($result->location->city) {
    $city = $result->location->city;
    $state = $result->location->state;
    $country = $result->location->country;
    if ($country=='United States') {
      $city_name = $city . ', ' . $states_arr[$state]; // e.g. 'Chicago, Illinois'
    }
    else {
      $city_name = $city . ', ' . $country; // e.g. 'Rome, Italy'
    }
    $fql = 'SELECT name,page_id,name,description,type,location FROM page WHERE type="CITY" and name="' .$city_name. '"';
    $result = json_decode(file_get_contents('https://graph.facebook.com/fql?q=' . rawurlencode($fql) . '&access_token=' . $fb_token));
    if (count($result->data)>0) {
      // We found it!
      print_r($result);
      break;
    }
    else {
      // No luck, try the next place
      print ("Couldn't find " . $city_name . "\n");
    }
  }
}