I want to retrieve information like the city, state, and country of a visitor from their IP address, so that I can customize my web page according to their location. Is there a good and reliable way to do this in PHP? I am using JavaScript for client-side scripting, PHP for server-side scripting, and MySQL for the database.
This question is related to
php
geolocation
ip
geoip
Thought I'd post as nobody seems to have given info on this particular API, but its returning exactly what I'm after and you can get it to return in multiple formats, json, xml and csv
.
$location = file_get_contents('http://freegeoip.net/json/'.$_SERVER['REMOTE_ADDR']);
print_r($location);
This will give you all of the things you could possibly want:
{
"ip": "77.99.179.98",
"country_code": "GB",
"country_name": "United Kingdom",
"region_code": "H9",
"region_name": "London, City of",
"city": "London",
"zipcode": "",
"latitude": 51.5142,
"longitude": -0.0931,
"metro_code": "",
"areacode": ""
}
PHP has an extension for that.
From PHP.net:
The GeoIP extension allows you to find the location of an IP address. City, State, Country, Longitude, Latitude, and other information as all, such as ISP and connection type can be obtained with the help of GeoIP.
For example:
$record = geoip_record_by_name($ip);
echo $record['city'];
I run the service at IPLocate.io, which you can hook into for free with one easy call:
<?php
$res = file_get_contents('https://www.iplocate.io/api/lookup/8.8.8.8');
$res = json_decode($res);
echo $res->country; // United States
echo $res->continent; // North America
echo $res->latitude; // 37.751
echo $res->longitude; // -97.822
var_dump($res);
The $res
object will contain your geolocation fields like country
, city
, etc.
Check out the docs for more information.
Ipdata.co is a fast, highly available IP Geolocation API with reliable performance.
It's extremely scalable with 10 endpoints around the world each able to handle >10,000 requests per second!
This answer uses a 'test' API Key that is very limited and only meant for testing a few calls. Signup for your own Free API Key and get up to 1500 requests daily for development.
In php
php > $ip = '8.8.8.8';
php > $details = json_decode(file_get_contents("https://api.ipdata.co/{$ip}?api-key=test"));
php > echo $details->region;
California
php > echo $details->city;
Mountain View
php > echo $details->country_name;
United States
php > echo $details->latitude;
37.751
Here's a client-side example showing how you'd get the country, region and city;
$.get("https://api.ipdata.co?api-key=test", function (response) {_x000D_
$("#response").html(JSON.stringify(response, null, 4));_x000D_
$("#country").html('Country: ' + response.country_name);_x000D_
$("#region").html('Region ' + response.region);_x000D_
$("#city").html('City' + response.city); _x000D_
}, "jsonp");
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>_x000D_
<div id="country"></div>_x000D_
<div id="region"></div>_x000D_
<div id="city"></div>_x000D_
<pre id="response"></pre>
_x000D_
Disclaimer;
I built the service.
For examples in multiple languages see the Docs
Also see this detailed analysis of the best IP Geolocation APIs.
This question is protected, which I understand. However, I do not see an answer here, what I see is a lot of people showing what they came up with from having the same question.
There are currently five Regional Internet Registries with varying degrees of functionality that serve as the first point of contact with regard to IP ownership. The process is in flux, which is why the various services here work sometimes and don't at other times.
Who Is is (obviously) an ancient TCP protocol, however -- the way it worked originally was by connection to port 43, which makes it problematic getting it routed through leased connections, through firewalls...etc.
At this moment -- most Who Is is done via RESTful HTTP and ARIN, RIPE and APNIC have RESTful services that work. LACNIC's returns a 503 and AfriNIC apparently has no such API. (All have online services, however.)
That will get you -- the address of the IP's registered owner, but -- not your client's location -- you must get that from them and also -- you have to ask for it. Also, proxies are the least of your worries when validating the IP that you think is the originator.
People do not appreciate the notion that they are being tracked, so -- my thoughts are -- get it from your client directly and with their permission and expect a lot to balk at the notion.
The service in Ben Dowling's response has changed, so it's now simpler. To find the location, simply do:
// no need to pass ip any longer; ipinfo grabs the ip of the person requesting
$details = json_decode(file_get_contents("http://ipinfo.io/"));
echo $details->city; // city
The coordinates return in a single string like '31,-80', so from there you just:
$coordinates = explode(",", $details->loc); // -> '31,-89' becomes'31','-80'
echo $coordinates[0]; // latitude
echo $coordinates[1]; // longitude
I like the free GeoLite City from Maxmind which works for most applications and from which you can upgrade to a paying version if it's not precise enough. There is a PHP API included, as well as for other languages. And if you are running Lighttpd as a webserver, you can even use a module to get the information in the SERVER variable for every visitor if that's what you need.
I should add there is also a free Geolite Country (which would be faster if you don't need to pinpoint the city the IP is from) and Geolite ASN (if you want to know who owns the IP) and that finally all these are downloadable on your own server, are updated every month and are pretty quick to lookup with the provided APIs as they state "thousands of lookups per second".
I wrote a bot using an API from ipapi.co, here's how you can get location for an IP address (e.g. 1.2.3.4
) in php
:
Set header :
$opts = array('http'=>array('method'=>"GET", 'header'=>"User-Agent: mybot.v0.7.1"));
$context = stream_context_create($opts);
Get JSON response
echo file_get_contents('https://ipapi.co/1.2.3.4/json/', false, $context);
of get a specific field (country, timezone etc.)
echo file_get_contents('https://ipapi.co/1.2.3.4/country/', false, $context);
If you need to get location from an IP address you can use reliable geo ip service, you can get more detail here. It supports IPv6.
As a bonus it allows to check whether ip address is a tor node, public proxy or spammer.
You can use javascript or php as below.
Javascript Code:
$(document).ready(function () {
$('#btnGetIpDetail').click(function () {
if ($('#txtIP').val() == '') {
alert('IP address is reqired');
return false;
}
$.getJSON("http://ip-api.io/json/" + $('#txtIP').val(),
function (result) {
alert('City Name: ' + result.city)
console.log(result);
});
});
});
Php Code:
$result = json_decode(file_get_contents('http://ip-api.io/json/64.30.228.118'));
var_dump($result);
Output:
{
"ip": "64.30.228.118",
"country_code": "US",
"country_name": "United States",
"region_code": "FL",
"region_name": "Florida",
"city": "Fort Lauderdale",
"zip_code": "33309",
"time_zone": "America/New_York",
"latitude": 26.1882,
"longitude": -80.1711,
"metro_code": 528,
"suspicious_factors": {
"is_proxy": false,
"is_tor_node": false,
"is_spam": false,
"is_suspicious": false
}
Ipdata.co is a fast, highly available IP Geolocation API with reliable performance.
It's extremely scalable with 10 endpoints around the world each able to handle >10,000 requests per second!
This answer uses a 'test' API Key that is very limited and only meant for testing a few calls. Signup for your own Free API Key and get up to 1500 requests daily for development.
In php
php > $ip = '8.8.8.8';
php > $details = json_decode(file_get_contents("https://api.ipdata.co/{$ip}?api-key=test"));
php > echo $details->region;
California
php > echo $details->city;
Mountain View
php > echo $details->country_name;
United States
php > echo $details->latitude;
37.751
Here's a client-side example showing how you'd get the country, region and city;
$.get("https://api.ipdata.co?api-key=test", function (response) {_x000D_
$("#response").html(JSON.stringify(response, null, 4));_x000D_
$("#country").html('Country: ' + response.country_name);_x000D_
$("#region").html('Region ' + response.region);_x000D_
$("#city").html('City' + response.city); _x000D_
}, "jsonp");
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>_x000D_
<div id="country"></div>_x000D_
<div id="region"></div>_x000D_
<div id="city"></div>_x000D_
<pre id="response"></pre>
_x000D_
Disclaimer;
I built the service.
For examples in multiple languages see the Docs
Also see this detailed analysis of the best IP Geolocation APIs.
You need to use an external service... such as http://www.hostip.info/ if you google search for "geo-ip" you can get more results.
The Host-IP API is HTTP based so you can use it either in PHP or JavaScript depending on your needs.
You could download a free GeoIP database and lookup the IP address locally, or you could use a third party service and perform a remote lookup. This is the simpler option, as it requires no setup, but it does introduce additional latency.
One third party service you could use is mine, http://ipinfo.io. They provide hostname, geolocation, network owner and additional information, eg:
$ curl ipinfo.io/8.8.8.8
{
"ip": "8.8.8.8",
"hostname": "google-public-dns-a.google.com",
"loc": "37.385999999999996,-122.0838",
"org": "AS15169 Google Inc.",
"city": "Mountain View",
"region": "CA",
"country": "US",
"phone": 650
}
Here's a PHP example:
$ip = $_SERVER['REMOTE_ADDR'];
$details = json_decode(file_get_contents("http://ipinfo.io/{$ip}/json"));
echo $details->city; // -> "Mountain View"
You can also use it client-side. Here's a simple jQuery example:
$.get("https://ipinfo.io/json", function (response) {_x000D_
$("#ip").html("IP: " + response.ip);_x000D_
$("#address").html("Location: " + response.city + ", " + response.region);_x000D_
$("#details").html(JSON.stringify(response, null, 4));_x000D_
}, "jsonp");
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>_x000D_
<h3>Client side IP geolocation using <a href="http://ipinfo.io">ipinfo.io</a></h3>_x000D_
_x000D_
<hr/>_x000D_
<div id="ip"></div>_x000D_
<div id="address"></div>_x000D_
<hr/>Full response: <pre id="details"></pre>
_x000D_
You can also use "smart-ip" service:
$.getJSON("http://smart-ip.net/geoip-json?callback=?",
function (data) {
alert(data.countryName);
alert(data.city);
}
);
I wrote a bot using an API from ipapi.co, here's how you can get location for an IP address (e.g. 1.2.3.4
) in php
:
Set header :
$opts = array('http'=>array('method'=>"GET", 'header'=>"User-Agent: mybot.v0.7.1"));
$context = stream_context_create($opts);
Get JSON response
echo file_get_contents('https://ipapi.co/1.2.3.4/json/', false, $context);
of get a specific field (country, timezone etc.)
echo file_get_contents('https://ipapi.co/1.2.3.4/country/', false, $context);
You could download a free GeoIP database and lookup the IP address locally, or you could use a third party service and perform a remote lookup. This is the simpler option, as it requires no setup, but it does introduce additional latency.
One third party service you could use is mine, http://ipinfo.io. They provide hostname, geolocation, network owner and additional information, eg:
$ curl ipinfo.io/8.8.8.8
{
"ip": "8.8.8.8",
"hostname": "google-public-dns-a.google.com",
"loc": "37.385999999999996,-122.0838",
"org": "AS15169 Google Inc.",
"city": "Mountain View",
"region": "CA",
"country": "US",
"phone": 650
}
Here's a PHP example:
$ip = $_SERVER['REMOTE_ADDR'];
$details = json_decode(file_get_contents("http://ipinfo.io/{$ip}/json"));
echo $details->city; // -> "Mountain View"
You can also use it client-side. Here's a simple jQuery example:
$.get("https://ipinfo.io/json", function (response) {_x000D_
$("#ip").html("IP: " + response.ip);_x000D_
$("#address").html("Location: " + response.city + ", " + response.region);_x000D_
$("#details").html(JSON.stringify(response, null, 4));_x000D_
}, "jsonp");
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>_x000D_
<h3>Client side IP geolocation using <a href="http://ipinfo.io">ipinfo.io</a></h3>_x000D_
_x000D_
<hr/>_x000D_
<div id="ip"></div>_x000D_
<div id="address"></div>_x000D_
<hr/>Full response: <pre id="details"></pre>
_x000D_
A pure Javascript example, using the services of https://geolocation-db.com They provide a JSON and JSONP-callback solution.
No jQuery required!
<!DOCTYPE html>
<html>
<head>
<title>Geo City Locator by geolocation-db.com</title>
</head>
<body>
<div>Country: <span id="country"></span></div>
<div>State: <span id="state"></span></div>
<div>City: <span id="city"></span></div>
<div>Postal: <span id="postal"></span></div>
<div>Latitude: <span id="latitude"></span></div>
<div>Longitude: <span id="longitude"></span></div>
<div>IP address: <span id="ipv4"></span></div>
</body>
<script>
var country = document.getElementById('country');
var state = document.getElementById('state');
var city = document.getElementById('city');
var postal = document.getElementById('postal');
var latitude = document.getElementById('latitude');
var longitude = document.getElementById('longitude');
var ip = document.getElementById('ipv4');
function callback(data)
{
country.innerHTML = data.country_name;
state.innerHTML = data.state;
city.innerHTML = data.city;
postal.innerHTML = data.postal;
latitude.innerHTML = data.latitude;
longitude.innerHTML = data.longitude;
ip.innerHTML = data.IPv4;
}
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://geoilocation-db.com/json/geoip.php?jsonp=callback';
var h = document.getElementsByTagName('script')[0];
h.parentNode.insertBefore(script, h);
</script>
</html>
You can also use "smart-ip" service:
$.getJSON("http://smart-ip.net/geoip-json?callback=?",
function (data) {
alert(data.countryName);
alert(data.city);
}
);
Assuming you want to do it yourself and not rely upon other providers, IP2Nation provides a MySQL database of the mappings which are updated as the regional registries change things around.
You need to use an external service... such as http://www.hostip.info/ if you google search for "geo-ip" you can get more results.
The Host-IP API is HTTP based so you can use it either in PHP or JavaScript depending on your needs.
This question is protected, which I understand. However, I do not see an answer here, what I see is a lot of people showing what they came up with from having the same question.
There are currently five Regional Internet Registries with varying degrees of functionality that serve as the first point of contact with regard to IP ownership. The process is in flux, which is why the various services here work sometimes and don't at other times.
Who Is is (obviously) an ancient TCP protocol, however -- the way it worked originally was by connection to port 43, which makes it problematic getting it routed through leased connections, through firewalls...etc.
At this moment -- most Who Is is done via RESTful HTTP and ARIN, RIPE and APNIC have RESTful services that work. LACNIC's returns a 503 and AfriNIC apparently has no such API. (All have online services, however.)
That will get you -- the address of the IP's registered owner, but -- not your client's location -- you must get that from them and also -- you have to ask for it. Also, proxies are the least of your worries when validating the IP that you think is the originator.
People do not appreciate the notion that they are being tracked, so -- my thoughts are -- get it from your client directly and with their permission and expect a lot to balk at the notion.
Using Google APIS:
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script>
contry_code = google.loader.ClientLocation.address.country_code
city = google.loader.ClientLocation.address.city
region = google.loader.ClientLocation.address.region
</script>
I like the free GeoLite City from Maxmind which works for most applications and from which you can upgrade to a paying version if it's not precise enough. There is a PHP API included, as well as for other languages. And if you are running Lighttpd as a webserver, you can even use a module to get the information in the SERVER variable for every visitor if that's what you need.
I should add there is also a free Geolite Country (which would be faster if you don't need to pinpoint the city the IP is from) and Geolite ASN (if you want to know who owns the IP) and that finally all these are downloadable on your own server, are updated every month and are pretty quick to lookup with the provided APIs as they state "thousands of lookups per second".
I've done a bunch of testing with IP address services and here are a few ways I do it myself. First off a bunch off links to useful websites that I use:
https://db-ip.com/db Has a free ip-lookup service and has a few free csv files you can download. This uses a free api key that is attached to your email. It limits at 2000 queries per day.
http://ipinfo.io/ Free ip-lookup service without a api-key PHP functions:
//uses http://ipinfo.io/.
function ip_visitor_country($ip){
$ip_data_in = get_web_page("http://ipinfo.io/".$ip."/json"); //add the ip to the url and retrieve the json data
$ip_data = json_decode($ip_data_in['content'],true); //json_decode it for php use
//this ip-lookup service returns 404 if the ip is invalid/not found so return false if this is the case.
if(empty($ip_data) || $ip_data_in['httpcode'] == 404){
return false;
}else{
return $ip_data;
}
}
function get_web_page($url){
$user_agent = 'Mozilla/5.0 (Windows NT 6.1; rv:8.0) Gecko/20100101 Firefox/8.0';
$options = array(
CURLOPT_CUSTOMREQUEST =>"GET", //set request type post or get
CURLOPT_POST =>false, //set to GET
CURLOPT_USERAGENT => $user_agent, //set user agent
CURLOPT_RETURNTRANSFER => true, // return web page
CURLOPT_HEADER => false, // don't return headers
CURLOPT_FOLLOWLOCATION => true, // follow redirects
CURLOPT_ENCODING => "", // handle all encodings
CURLOPT_AUTOREFERER => true, // set referer on redirect
CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect
CURLOPT_TIMEOUT => 120, // timeout on response
CURLOPT_MAXREDIRS => 10, // stop after 10 redirects
);
$ch = curl_init( $url );
curl_setopt_array( $ch, $options );
$content = curl_exec( $ch );
$err = curl_errno( $ch );
$errmsg = curl_error( $ch );
$header = curl_getinfo( $ch );
$httpCode = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
curl_close( $ch );
$header['errno'] = $err; //curl error code
$header['errmsg'] = $errmsg; //curl error message
$header['content'] = $content; //the webpage result (In this case the ip data in json array form)
$header['httpcode'] = $httpCode; //the webpage response code
return $header; //return the collected data and response codes
}
In the end you get something like this:
Array
(
[ip] => 1.1.1.1
[hostname] => No Hostname
[city] =>
[country] => AU
[loc] => -27.0000,133.0000
[org] => AS15169 Google Inc.
)
http://www.geoplugin.com/ Slightly older but this service gives you a bunch of extra usefull information such as the currency off the country, continent code, longitude and more.
http://lite.ip2location.com/database-ip-country-region-city-latitude-longitude Offers a bunch of downloadable files with instructions to import them into your database. Once you have one off these files in your database you can select the data fairly easily.
SELECT * FROM `ip2location_db5` WHERE IP > ip_from AND IP < ip_to
Use the php function ip2long(); to turn the ip-address into a numeric value. For example 1.1.1.1 becomes 16843009. This lets you scan for the ip ranges given to you by the database file.
So in order to find out where 1.1.1.1 belongs to all we do is run this query:
SELECT * FROM `ip2location_db5` WHERE 16843009 > ip_from AND 16843009 < ip_to;
This returns this data as a example.
FROM: 16843008
TO: 16843263
Country code: AU
Country: Australia
Region: Queensland
City: Brisbane
Latitude: -27.46794
Longitude: 153.02809
If you need to get location from an IP address you can use reliable geo ip service, you can get more detail here. It supports IPv6.
As a bonus it allows to check whether ip address is a tor node, public proxy or spammer.
You can use javascript or php as below.
Javascript Code:
$(document).ready(function () {
$('#btnGetIpDetail').click(function () {
if ($('#txtIP').val() == '') {
alert('IP address is reqired');
return false;
}
$.getJSON("http://ip-api.io/json/" + $('#txtIP').val(),
function (result) {
alert('City Name: ' + result.city)
console.log(result);
});
});
});
Php Code:
$result = json_decode(file_get_contents('http://ip-api.io/json/64.30.228.118'));
var_dump($result);
Output:
{
"ip": "64.30.228.118",
"country_code": "US",
"country_name": "United States",
"region_code": "FL",
"region_name": "Florida",
"city": "Fort Lauderdale",
"zip_code": "33309",
"time_zone": "America/New_York",
"latitude": 26.1882,
"longitude": -80.1711,
"metro_code": 528,
"suspicious_factors": {
"is_proxy": false,
"is_tor_node": false,
"is_spam": false,
"is_suspicious": false
}
In case anyone stumbles upon this thread, here's another solution. At timezoneapi.io you can request an IP address and get several objects in return (I've created the service). It was created because I needed to know which timezone my users were in, where in the world and what time it currently is.
In PHP - returns location, timezone and date/time:
// Get IP address
$ip_address = getenv('HTTP_CLIENT_IP') ?: getenv('HTTP_X_FORWARDED_FOR') ?: getenv('HTTP_X_FORWARDED') ?: getenv('HTTP_FORWARDED_FOR') ?: getenv('HTTP_FORWARDED') ?: getenv('REMOTE_ADDR');
// Get JSON object
$jsondata = file_get_contents("http://timezoneapi.io/api/ip/?" . $ip_address);
// Decode
$data = json_decode($jsondata, true);
// Request OK?
if($data['meta']['code'] == '200'){
// Example: Get the city parameter
echo "City: " . $data['data']['city'] . "<br>";
// Example: Get the users time
echo "Time: " . $data['data']['datetime']['date_time_txt'] . "<br>";
}
Using jQuery:
// Get JSON object
$.getJSON('https://timezoneapi.io/api/ip', function(data){
// Request OK?
if(data.meta.code == '200'){
// Log
console.log(data);
// Example: Get the city parameter
var city = data.data.city;
alert(city);
// Example: Get the users time
var time = data.data.datetime.date_time_txt;
alert(time);
}
});
The following is a modified version of a snippet I found that uses http://ipinfodb.com/ip_locator.php to get its information. Keep in mind, you can also apply for an API key with them and use the API directly to get the information supplied as you see fit.
function detect_location($ip=NULL, $asArray=FALSE) {
if (empty($ip)) {
if (!empty($_SERVER['HTTP_CLIENT_IP'])) { $ip = $_SERVER['HTTP_CLIENT_IP']; }
elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; }
else { $ip = $_SERVER['REMOTE_ADDR']; }
}
elseif (!is_string($ip) || strlen($ip) < 1 || $ip == '127.0.0.1' || $ip == 'localhost') {
$ip = '8.8.8.8';
}
$url = 'http://ipinfodb.com/ip_locator.php?ip=' . urlencode($ip);
$i = 0; $content; $curl_info;
while (empty($content) && $i < 5) {
$ch = curl_init();
$curl_opt = array(
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_HEADER => 0,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => $url,
CURLOPT_TIMEOUT => 1,
CURLOPT_REFERER => 'http://' . $_SERVER['HTTP_HOST'],
);
if (isset($_SERVER['HTTP_USER_AGENT'])) $curl_opt[CURLOPT_USERAGENT] = $_SERVER['HTTP_USER_AGENT'];
curl_setopt_array($ch, $curl_opt);
$content = curl_exec($ch);
if (!is_null($curl_info)) $curl_info = curl_getinfo($ch);
curl_close($ch);
}
$araResp = array();
if (preg_match('{<li>City : ([^<]*)</li>}i', $content, $regs)) $araResp['city'] = trim($regs[1]);
if (preg_match('{<li>State/Province : ([^<]*)</li>}i', $content, $regs)) $araResp['state'] = trim($regs[1]);
if (preg_match('{<li>Country : ([^<]*)}i', $content, $regs)) $araResp['country'] = trim($regs[1]);
if (preg_match('{<li>Zip or postal code : ([^<]*)</li>}i', $content, $regs)) $araResp['zip'] = trim($regs[1]);
if (preg_match('{<li>Latitude : ([^<]*)</li>}i', $content, $regs)) $araResp['latitude'] = trim($regs[1]);
if (preg_match('{<li>Longitude : ([^<]*)</li>}i', $content, $regs)) $araResp['longitude'] = trim($regs[1]);
if (preg_match('{<li>Timezone : ([^<]*)</li>}i', $content, $regs)) $araResp['timezone'] = trim($regs[1]);
if (preg_match('{<li>Hostname : ([^<]*)</li>}i', $content, $regs)) $araResp['hostname'] = trim($regs[1]);
$strResp = ($araResp['city'] != '' && $araResp['state'] != '') ? ($araResp['city'] . ', ' . $araResp['state']) : 'UNKNOWN';
return $asArray ? $araResp : $strResp;
}
detect_location();
// returns "CITY, STATE" based on user IP
detect_location('xxx.xxx.xxx.xxx');
// returns "CITY, STATE" based on IP you provide
detect_location(NULL, TRUE); // based on user IP
// returns array(8) { ["city"] => "CITY", ["state"] => "STATE", ["country"] => "US", ["zip"] => "xxxxx", ["latitude"] => "xx.xxxxxx", ["longitude"] => "-xx.xxxxxx", ["timezone"] => "-07:00", ["hostname"] => "xx-xx-xx-xx.host.name.net" }
detect_location('xxx.xxx.xxx.xxx', TRUE); // based on IP you provide
// returns array(8) { ["city"] => "CITY", ["state"] => "STATE", ["country"] => "US", ["zip"] => "xxxxx", ["latitude"] => "xx.xxxxxx", ["longitude"] => "-xx.xxxxxx", ["timezone"] => "-07:00", ["hostname"] => "xx-xx-xx-xx.host.name.net" }
Look at the API from hostip.info - it provides lots of information.
Example in PHP:
$data = file_get_contents("http://api.hostip.info/country.php?ip=12.215.42.19");
//$data contains: "US"
$data = file_get_contents("http://api.hostip.info/?ip=12.215.42.19");
//$data contains: XML with country, lat, long, city, etc...
If you trust hostip.info, it seems to be a very useful API.
You need to use an external service... such as http://www.hostip.info/ if you google search for "geo-ip" you can get more results.
The Host-IP API is HTTP based so you can use it either in PHP or JavaScript depending on your needs.
I run the service at IPLocate.io, which you can hook into for free with one easy call:
<?php
$res = file_get_contents('https://www.iplocate.io/api/lookup/8.8.8.8');
$res = json_decode($res);
echo $res->country; // United States
echo $res->continent; // North America
echo $res->latitude; // 37.751
echo $res->longitude; // -97.822
var_dump($res);
The $res
object will contain your geolocation fields like country
, city
, etc.
Check out the docs for more information.
I've done a bunch of testing with IP address services and here are a few ways I do it myself. First off a bunch off links to useful websites that I use:
https://db-ip.com/db Has a free ip-lookup service and has a few free csv files you can download. This uses a free api key that is attached to your email. It limits at 2000 queries per day.
http://ipinfo.io/ Free ip-lookup service without a api-key PHP functions:
//uses http://ipinfo.io/.
function ip_visitor_country($ip){
$ip_data_in = get_web_page("http://ipinfo.io/".$ip."/json"); //add the ip to the url and retrieve the json data
$ip_data = json_decode($ip_data_in['content'],true); //json_decode it for php use
//this ip-lookup service returns 404 if the ip is invalid/not found so return false if this is the case.
if(empty($ip_data) || $ip_data_in['httpcode'] == 404){
return false;
}else{
return $ip_data;
}
}
function get_web_page($url){
$user_agent = 'Mozilla/5.0 (Windows NT 6.1; rv:8.0) Gecko/20100101 Firefox/8.0';
$options = array(
CURLOPT_CUSTOMREQUEST =>"GET", //set request type post or get
CURLOPT_POST =>false, //set to GET
CURLOPT_USERAGENT => $user_agent, //set user agent
CURLOPT_RETURNTRANSFER => true, // return web page
CURLOPT_HEADER => false, // don't return headers
CURLOPT_FOLLOWLOCATION => true, // follow redirects
CURLOPT_ENCODING => "", // handle all encodings
CURLOPT_AUTOREFERER => true, // set referer on redirect
CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect
CURLOPT_TIMEOUT => 120, // timeout on response
CURLOPT_MAXREDIRS => 10, // stop after 10 redirects
);
$ch = curl_init( $url );
curl_setopt_array( $ch, $options );
$content = curl_exec( $ch );
$err = curl_errno( $ch );
$errmsg = curl_error( $ch );
$header = curl_getinfo( $ch );
$httpCode = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
curl_close( $ch );
$header['errno'] = $err; //curl error code
$header['errmsg'] = $errmsg; //curl error message
$header['content'] = $content; //the webpage result (In this case the ip data in json array form)
$header['httpcode'] = $httpCode; //the webpage response code
return $header; //return the collected data and response codes
}
In the end you get something like this:
Array
(
[ip] => 1.1.1.1
[hostname] => No Hostname
[city] =>
[country] => AU
[loc] => -27.0000,133.0000
[org] => AS15169 Google Inc.
)
http://www.geoplugin.com/ Slightly older but this service gives you a bunch of extra usefull information such as the currency off the country, continent code, longitude and more.
http://lite.ip2location.com/database-ip-country-region-city-latitude-longitude Offers a bunch of downloadable files with instructions to import them into your database. Once you have one off these files in your database you can select the data fairly easily.
SELECT * FROM `ip2location_db5` WHERE IP > ip_from AND IP < ip_to
Use the php function ip2long(); to turn the ip-address into a numeric value. For example 1.1.1.1 becomes 16843009. This lets you scan for the ip ranges given to you by the database file.
So in order to find out where 1.1.1.1 belongs to all we do is run this query:
SELECT * FROM `ip2location_db5` WHERE 16843009 > ip_from AND 16843009 < ip_to;
This returns this data as a example.
FROM: 16843008
TO: 16843263
Country code: AU
Country: Australia
Region: Queensland
City: Brisbane
Latitude: -27.46794
Longitude: 153.02809
Using Google APIS:
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script>
contry_code = google.loader.ClientLocation.address.country_code
city = google.loader.ClientLocation.address.city
region = google.loader.ClientLocation.address.region
</script>
Assuming you want to do it yourself and not rely upon other providers, IP2Nation provides a MySQL database of the mappings which are updated as the regional registries change things around.
You need to use an external service... such as http://www.hostip.info/ if you google search for "geo-ip" you can get more results.
The Host-IP API is HTTP based so you can use it either in PHP or JavaScript depending on your needs.
Assuming you want to do it yourself and not rely upon other providers, IP2Nation provides a MySQL database of the mappings which are updated as the regional registries change things around.
I like the free GeoLite City from Maxmind which works for most applications and from which you can upgrade to a paying version if it's not precise enough. There is a PHP API included, as well as for other languages. And if you are running Lighttpd as a webserver, you can even use a module to get the information in the SERVER variable for every visitor if that's what you need.
I should add there is also a free Geolite Country (which would be faster if you don't need to pinpoint the city the IP is from) and Geolite ASN (if you want to know who owns the IP) and that finally all these are downloadable on your own server, are updated every month and are pretty quick to lookup with the provided APIs as they state "thousands of lookups per second".
Assuming you want to do it yourself and not rely upon other providers, IP2Nation provides a MySQL database of the mappings which are updated as the regional registries change things around.
The following is a modified version of a snippet I found that uses http://ipinfodb.com/ip_locator.php to get its information. Keep in mind, you can also apply for an API key with them and use the API directly to get the information supplied as you see fit.
function detect_location($ip=NULL, $asArray=FALSE) {
if (empty($ip)) {
if (!empty($_SERVER['HTTP_CLIENT_IP'])) { $ip = $_SERVER['HTTP_CLIENT_IP']; }
elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; }
else { $ip = $_SERVER['REMOTE_ADDR']; }
}
elseif (!is_string($ip) || strlen($ip) < 1 || $ip == '127.0.0.1' || $ip == 'localhost') {
$ip = '8.8.8.8';
}
$url = 'http://ipinfodb.com/ip_locator.php?ip=' . urlencode($ip);
$i = 0; $content; $curl_info;
while (empty($content) && $i < 5) {
$ch = curl_init();
$curl_opt = array(
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_HEADER => 0,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => $url,
CURLOPT_TIMEOUT => 1,
CURLOPT_REFERER => 'http://' . $_SERVER['HTTP_HOST'],
);
if (isset($_SERVER['HTTP_USER_AGENT'])) $curl_opt[CURLOPT_USERAGENT] = $_SERVER['HTTP_USER_AGENT'];
curl_setopt_array($ch, $curl_opt);
$content = curl_exec($ch);
if (!is_null($curl_info)) $curl_info = curl_getinfo($ch);
curl_close($ch);
}
$araResp = array();
if (preg_match('{<li>City : ([^<]*)</li>}i', $content, $regs)) $araResp['city'] = trim($regs[1]);
if (preg_match('{<li>State/Province : ([^<]*)</li>}i', $content, $regs)) $araResp['state'] = trim($regs[1]);
if (preg_match('{<li>Country : ([^<]*)}i', $content, $regs)) $araResp['country'] = trim($regs[1]);
if (preg_match('{<li>Zip or postal code : ([^<]*)</li>}i', $content, $regs)) $araResp['zip'] = trim($regs[1]);
if (preg_match('{<li>Latitude : ([^<]*)</li>}i', $content, $regs)) $araResp['latitude'] = trim($regs[1]);
if (preg_match('{<li>Longitude : ([^<]*)</li>}i', $content, $regs)) $araResp['longitude'] = trim($regs[1]);
if (preg_match('{<li>Timezone : ([^<]*)</li>}i', $content, $regs)) $araResp['timezone'] = trim($regs[1]);
if (preg_match('{<li>Hostname : ([^<]*)</li>}i', $content, $regs)) $araResp['hostname'] = trim($regs[1]);
$strResp = ($araResp['city'] != '' && $araResp['state'] != '') ? ($araResp['city'] . ', ' . $araResp['state']) : 'UNKNOWN';
return $asArray ? $araResp : $strResp;
}
detect_location();
// returns "CITY, STATE" based on user IP
detect_location('xxx.xxx.xxx.xxx');
// returns "CITY, STATE" based on IP you provide
detect_location(NULL, TRUE); // based on user IP
// returns array(8) { ["city"] => "CITY", ["state"] => "STATE", ["country"] => "US", ["zip"] => "xxxxx", ["latitude"] => "xx.xxxxxx", ["longitude"] => "-xx.xxxxxx", ["timezone"] => "-07:00", ["hostname"] => "xx-xx-xx-xx.host.name.net" }
detect_location('xxx.xxx.xxx.xxx', TRUE); // based on IP you provide
// returns array(8) { ["city"] => "CITY", ["state"] => "STATE", ["country"] => "US", ["zip"] => "xxxxx", ["latitude"] => "xx.xxxxxx", ["longitude"] => "-xx.xxxxxx", ["timezone"] => "-07:00", ["hostname"] => "xx-xx-xx-xx.host.name.net" }
PHP has an extension for that.
From PHP.net:
The GeoIP extension allows you to find the location of an IP address. City, State, Country, Longitude, Latitude, and other information as all, such as ISP and connection type can be obtained with the help of GeoIP.
For example:
$record = geoip_record_by_name($ip);
echo $record['city'];
I like the free GeoLite City from Maxmind which works for most applications and from which you can upgrade to a paying version if it's not precise enough. There is a PHP API included, as well as for other languages. And if you are running Lighttpd as a webserver, you can even use a module to get the information in the SERVER variable for every visitor if that's what you need.
I should add there is also a free Geolite Country (which would be faster if you don't need to pinpoint the city the IP is from) and Geolite ASN (if you want to know who owns the IP) and that finally all these are downloadable on your own server, are updated every month and are pretty quick to lookup with the provided APIs as they state "thousands of lookups per second".
Look at the API from hostip.info - it provides lots of information.
Example in PHP:
$data = file_get_contents("http://api.hostip.info/country.php?ip=12.215.42.19");
//$data contains: "US"
$data = file_get_contents("http://api.hostip.info/?ip=12.215.42.19");
//$data contains: XML with country, lat, long, city, etc...
If you trust hostip.info, it seems to be a very useful API.
The service in Ben Dowling's response has changed, so it's now simpler. To find the location, simply do:
// no need to pass ip any longer; ipinfo grabs the ip of the person requesting
$details = json_decode(file_get_contents("http://ipinfo.io/"));
echo $details->city; // city
The coordinates return in a single string like '31,-80', so from there you just:
$coordinates = explode(",", $details->loc); // -> '31,-89' becomes'31','-80'
echo $coordinates[0]; // latitude
echo $coordinates[1]; // longitude
A pure Javascript example, using the services of https://geolocation-db.com They provide a JSON and JSONP-callback solution.
No jQuery required!
<!DOCTYPE html>
<html>
<head>
<title>Geo City Locator by geolocation-db.com</title>
</head>
<body>
<div>Country: <span id="country"></span></div>
<div>State: <span id="state"></span></div>
<div>City: <span id="city"></span></div>
<div>Postal: <span id="postal"></span></div>
<div>Latitude: <span id="latitude"></span></div>
<div>Longitude: <span id="longitude"></span></div>
<div>IP address: <span id="ipv4"></span></div>
</body>
<script>
var country = document.getElementById('country');
var state = document.getElementById('state');
var city = document.getElementById('city');
var postal = document.getElementById('postal');
var latitude = document.getElementById('latitude');
var longitude = document.getElementById('longitude');
var ip = document.getElementById('ipv4');
function callback(data)
{
country.innerHTML = data.country_name;
state.innerHTML = data.state;
city.innerHTML = data.city;
postal.innerHTML = data.postal;
latitude.innerHTML = data.latitude;
longitude.innerHTML = data.longitude;
ip.innerHTML = data.IPv4;
}
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://geoilocation-db.com/json/geoip.php?jsonp=callback';
var h = document.getElementsByTagName('script')[0];
h.parentNode.insertBefore(script, h);
</script>
</html>
There 2 broad approaches to perform IP geolocation: one is to download a dataset, host it on your infrastructure and maintain it up-to-date. This requires time and effort, especially if you need to support a high number of requests. Another solution is to use an existing API service that manages all the work for you and more.
There exist many API Geolocation services: Maxmind, Ip2location, Ipstack, IpInfo, etc. Recently, the company I work for has switched to Ipregistry (https://ipregistry.co) and I was involved in the decision and implementation process. Here are some elements you should consider while looking for an IP geolocation API:
Here is an example to get IP geolocation information (but also threat and user agent data using one call):
$ip = $_SERVER['REMOTE_ADDR'];
$details = json_decode(file_get_contents("https://api.ipregistry.co/{$ip}?key=tryout"));
echo $details->location;
Note: I am not here to promote Ipregistry and say it's the best but I spent a long time analyzing existing solutions and their solution is really promising.
In case anyone stumbles upon this thread, here's another solution. At timezoneapi.io you can request an IP address and get several objects in return (I've created the service). It was created because I needed to know which timezone my users were in, where in the world and what time it currently is.
In PHP - returns location, timezone and date/time:
// Get IP address
$ip_address = getenv('HTTP_CLIENT_IP') ?: getenv('HTTP_X_FORWARDED_FOR') ?: getenv('HTTP_X_FORWARDED') ?: getenv('HTTP_FORWARDED_FOR') ?: getenv('HTTP_FORWARDED') ?: getenv('REMOTE_ADDR');
// Get JSON object
$jsondata = file_get_contents("http://timezoneapi.io/api/ip/?" . $ip_address);
// Decode
$data = json_decode($jsondata, true);
// Request OK?
if($data['meta']['code'] == '200'){
// Example: Get the city parameter
echo "City: " . $data['data']['city'] . "<br>";
// Example: Get the users time
echo "Time: " . $data['data']['datetime']['date_time_txt'] . "<br>";
}
Using jQuery:
// Get JSON object
$.getJSON('https://timezoneapi.io/api/ip', function(data){
// Request OK?
if(data.meta.code == '200'){
// Log
console.log(data);
// Example: Get the city parameter
var city = data.data.city;
alert(city);
// Example: Get the users time
var time = data.data.datetime.date_time_txt;
alert(time);
}
});
Thought I'd post as nobody seems to have given info on this particular API, but its returning exactly what I'm after and you can get it to return in multiple formats, json, xml and csv
.
$location = file_get_contents('http://freegeoip.net/json/'.$_SERVER['REMOTE_ADDR']);
print_r($location);
This will give you all of the things you could possibly want:
{
"ip": "77.99.179.98",
"country_code": "GB",
"country_name": "United Kingdom",
"region_code": "H9",
"region_name": "London, City of",
"city": "London",
"zipcode": "",
"latitude": 51.5142,
"longitude": -0.0931,
"metro_code": "",
"areacode": ""
}
There 2 broad approaches to perform IP geolocation: one is to download a dataset, host it on your infrastructure and maintain it up-to-date. This requires time and effort, especially if you need to support a high number of requests. Another solution is to use an existing API service that manages all the work for you and more.
There exist many API Geolocation services: Maxmind, Ip2location, Ipstack, IpInfo, etc. Recently, the company I work for has switched to Ipregistry (https://ipregistry.co) and I was involved in the decision and implementation process. Here are some elements you should consider while looking for an IP geolocation API:
Here is an example to get IP geolocation information (but also threat and user agent data using one call):
$ip = $_SERVER['REMOTE_ADDR'];
$details = json_decode(file_get_contents("https://api.ipregistry.co/{$ip}?key=tryout"));
echo $details->location;
Note: I am not here to promote Ipregistry and say it's the best but I spent a long time analyzing existing solutions and their solution is really promising.
Look at the API from hostip.info - it provides lots of information.
Example in PHP:
$data = file_get_contents("http://api.hostip.info/country.php?ip=12.215.42.19");
//$data contains: "US"
$data = file_get_contents("http://api.hostip.info/?ip=12.215.42.19");
//$data contains: XML with country, lat, long, city, etc...
If you trust hostip.info, it seems to be a very useful API.
Source: Stackoverflow.com