I've been using http://freegeoip.net/
It's not perfect, but it seems to be good enough for my purposes.
$ip = $_SERVER['REMOTE_ADDR'];
$ua = $_SERVER['HTTP_USER_AGENT'];
$ch = curl_init();
// set url
curl_setopt($ch, CURLOPT_URL, "freegeoip.net/csv/" . $ip);
//return the transfer as a string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// $output contains the output string
$ip = curl_exec($ch);
// close curl resource to free up system resources
curl_close($ch);
$array = explode(',', $ip);