Getting visitors country from their IP

320,852

Solution 1

Try this simple PHP function.

<?php

function ip_info($ip = NULL, $purpose = "location", $deep_detect = TRUE) {
    $output = NULL;
    if (filter_var($ip, FILTER_VALIDATE_IP) === FALSE) {
        $ip = $_SERVER["REMOTE_ADDR"];
        if ($deep_detect) {
            if (filter_var(@$_SERVER['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP))
                $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
            if (filter_var(@$_SERVER['HTTP_CLIENT_IP'], FILTER_VALIDATE_IP))
                $ip = $_SERVER['HTTP_CLIENT_IP'];
        }
    }
    $purpose    = str_replace(array("name", "\n", "\t", " ", "-", "_"), NULL, strtolower(trim($purpose)));
    $support    = array("country", "countrycode", "state", "region", "city", "location", "address");
    $continents = array(
        "AF" => "Africa",
        "AN" => "Antarctica",
        "AS" => "Asia",
        "EU" => "Europe",
        "OC" => "Australia (Oceania)",
        "NA" => "North America",
        "SA" => "South America"
    );
    if (filter_var($ip, FILTER_VALIDATE_IP) && in_array($purpose, $support)) {
        $ipdat = @json_decode(file_get_contents("http://www.geoplugin.net/json.gp?ip=" . $ip));
        if (@strlen(trim($ipdat->geoplugin_countryCode)) == 2) {
            switch ($purpose) {
                case "location":
                    $output = array(
                        "city"           => @$ipdat->geoplugin_city,
                        "state"          => @$ipdat->geoplugin_regionName,
                        "country"        => @$ipdat->geoplugin_countryName,
                        "country_code"   => @$ipdat->geoplugin_countryCode,
                        "continent"      => @$continents[strtoupper($ipdat->geoplugin_continentCode)],
                        "continent_code" => @$ipdat->geoplugin_continentCode
                    );
                    break;
                case "address":
                    $address = array($ipdat->geoplugin_countryName);
                    if (@strlen($ipdat->geoplugin_regionName) >= 1)
                        $address[] = $ipdat->geoplugin_regionName;
                    if (@strlen($ipdat->geoplugin_city) >= 1)
                        $address[] = $ipdat->geoplugin_city;
                    $output = implode(", ", array_reverse($address));
                    break;
                case "city":
                    $output = @$ipdat->geoplugin_city;
                    break;
                case "state":
                    $output = @$ipdat->geoplugin_regionName;
                    break;
                case "region":
                    $output = @$ipdat->geoplugin_regionName;
                    break;
                case "country":
                    $output = @$ipdat->geoplugin_countryName;
                    break;
                case "countrycode":
                    $output = @$ipdat->geoplugin_countryCode;
                    break;
            }
        }
    }
    return $output;
}

?>

How to use:

Example1: Get visitor IP address details

<?php

echo ip_info("Visitor", "Country"); // India
echo ip_info("Visitor", "Country Code"); // IN
echo ip_info("Visitor", "State"); // Andhra Pradesh
echo ip_info("Visitor", "City"); // Proddatur
echo ip_info("Visitor", "Address"); // Proddatur, Andhra Pradesh, India

print_r(ip_info("Visitor", "Location")); // Array ( [city] => Proddatur [state] => Andhra Pradesh [country] => India [country_code] => IN [continent] => Asia [continent_code] => AS )

?>

Example 2: Get details of any IP address. [Support IPV4 & IPV6]

<?php

echo ip_info("173.252.110.27", "Country"); // United States
echo ip_info("173.252.110.27", "Country Code"); // US
echo ip_info("173.252.110.27", "State"); // California
echo ip_info("173.252.110.27", "City"); // Menlo Park
echo ip_info("173.252.110.27", "Address"); // Menlo Park, California, United States

print_r(ip_info("173.252.110.27", "Location")); // Array ( [city] => Menlo Park [state] => California [country] => United States [country_code] => US [continent] => North America [continent_code] => NA )

?>

Solution 2

You can use a simple API from http://www.geoplugin.net/

$xml = simplexml_load_file("http://www.geoplugin.net/xml.gp?ip=".getRealIpAddr());
echo $xml->geoplugin_countryName ;


echo "<pre>";
foreach ($xml as $key => $value)
{
    echo $key , "= " , $value ,  " \n" ;
}
echo "</pre>";

Function Used

function getRealIpAddr()
{
    if (!empty($_SERVER['HTTP_CLIENT_IP']))   //check ip from share internet
    {
      $ip=$_SERVER['HTTP_CLIENT_IP'];
    }
    elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))   //to check ip is pass from proxy
    {
      $ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
    }
    else
    {
      $ip=$_SERVER['REMOTE_ADDR'];
    }
    return $ip;
}

Output

United States
geoplugin_city= San Antonio
geoplugin_region= TX
geoplugin_areaCode= 210
geoplugin_dmaCode= 641
geoplugin_countryCode= US
geoplugin_countryName= United States
geoplugin_continentCode= NA
geoplugin_latitude= 29.488899230957
geoplugin_longitude= -98.398696899414
geoplugin_regionCode= TX
geoplugin_regionName= Texas
geoplugin_currencyCode= USD
geoplugin_currencySymbol= $
geoplugin_currencyConverter= 1

It makes you have so many options you can play around with

Thanks

:)

Solution 3

I tried Chandra's answer but my server configuration does not allow file_get_contents()

PHP Warning: file_get_contents() URL file-access is disabled in the server configuration

I modified Chandra's code so that it also works for servers like that using cURL:

function ip_visitor_country()
{

    $client  = @$_SERVER['HTTP_CLIENT_IP'];
    $forward = @$_SERVER['HTTP_X_FORWARDED_FOR'];
    $remote  = $_SERVER['REMOTE_ADDR'];
    $country  = "Unknown";

    if(filter_var($client, FILTER_VALIDATE_IP))
    {
        $ip = $client;
    }
    elseif(filter_var($forward, FILTER_VALIDATE_IP))
    {
        $ip = $forward;
    }
    else
    {
        $ip = $remote;
    }
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, "http://www.geoplugin.net/json.gp?ip=".$ip);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    $ip_data_in = curl_exec($ch); // string
    curl_close($ch);

    $ip_data = json_decode($ip_data_in,true);
    $ip_data = str_replace('&quot;', '"', $ip_data); // for PHP 5.2 see stackoverflow.com/questions/3110487/

    if($ip_data && $ip_data['geoplugin_countryName'] != null) {
        $country = $ip_data['geoplugin_countryName'];
    }

    return 'IP: '.$ip.' # Country: '.$country;
}

echo ip_visitor_country(); // output Coutry name

?>

Hope that helps ;-)

Solution 4

Use MaxMind GeoIP (or GeoIPLite if you are not ready to pay).

$gi = geoip_open('GeoIP.dat', GEOIP_MEMORY_CACHE);
$country = geoip_country_code_by_addr($gi, $_SERVER['REMOTE_ADDR']);
geoip_close($gi);

Solution 5

You can use a web-service from http://ip-api.com
in your php code, do as follow :

<?php
$ip = $_REQUEST['REMOTE_ADDR']; // the IP address to query
$query = @unserialize(file_get_contents('http://ip-api.com/php/'.$ip));
if($query && $query['status'] == 'success') {
  echo 'Hello visitor from '.$query['country'].', '.$query['city'].'!';
} else {
  echo 'Unable to get location';
}
?>

the query have many other informations:

array (
  'status'      => 'success',
  'country'     => 'COUNTRY',
  'countryCode' => 'COUNTRY CODE',
  'region'      => 'REGION CODE',
  'regionName'  => 'REGION NAME',
  'city'        => 'CITY',
  'zip'         => ZIP CODE,
  'lat'         => LATITUDE,
  'lon'         => LONGITUDE,
  'timezone'    => 'TIME ZONE',
  'isp'         => 'ISP NAME',
  'org'         => 'ORGANIZATION NAME',
  'as'          => 'AS NUMBER / NAME',
  'query'       => 'IP ADDRESS USED FOR QUERY',
)
Share:
320,852

Related videos on Youtube

Alex C.
Author by

Alex C.

Updated on July 08, 2022

Comments

  • Alex C.
    Alex C. almost 2 years

    I want to get visitors country via their IP... Right now I'm using this (http://api.hostip.info/country.php?ip=...... )

    Here is my code:

    <?php
    
    if (isset($_SERVER['HTTP_CLIENT_IP']))
    {
        $real_ip_adress = $_SERVER['HTTP_CLIENT_IP'];
    }
    
    if (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
    {
        $real_ip_adress = $_SERVER['HTTP_X_FORWARDED_FOR'];
    }
    else
    {
        $real_ip_adress = $_SERVER['REMOTE_ADDR'];
    }
    
    $cip = $real_ip_adress;
    $iptolocation = 'http://api.hostip.info/country.php?ip=' . $cip;
    $creatorlocation = file_get_contents($iptolocation);
    
    ?>
    

    Well, it's working properly, but the thing is, this returns the country code like US or CA., and not the whole country name like United States or Canada.

    So, is there any good alternative to hostip.info offers this?

    I know that I can just write some code that will eventually turn this two letters to whole country name, but I'm just too lazy to write a code that contains all countries...

    P.S: For some reason I don't want to use any ready made CSV file or any code that will grab this information for me, something like ip2country ready made code and CSV.

    • Ezz Elkady
      Ezz Elkady over 11 years
      Don't be lazy, there aren't that many countries, and it's not too hard to obtain a translation table for FIPS 2 letter codes to country names.
    • Tchoupi
      Tchoupi over 11 years
      Use Maxmind geoip feature. It will include the country name in the results. maxmind.com/app/php
    • Walter Tross
      Walter Tross about 10 years
      Your first assignment to $real_ip_address is always ignored. Anyways, remember that the X-Forwarded-For HTTP header can be extremely easily counterfeited, and that there are proxies like www.hidemyass.com
    • ttarik
      ttarik over 6 years
      IPLocate.io provides a free API: https://www.iplocate.io/api/lookup/8.8.8.8 - Disclaimer: I run this service.
    • Laurent
      Laurent over 4 years
      I suggest giving a try to Ipregistry: api.ipregistry.co/… (disclaimer: I run the service).
  • echo_Me
    echo_Me about 10 years
    we must provide database information to work ? seems not good.
  • echo_Me
    echo_Me about 10 years
    why im getting unknow all the time with every ip ? , used same code.
  • Avatar
    Avatar about 10 years
    You get "Unknown" probably because your server does not allow file_get_contents(). Just check your error_log file. Workaround: see my answer.
  • Hontoni
    Hontoni about 10 years
    also it might be because u check it localy (192.168.1.1 / 127.0.0.1 / 10.0.0.1)
  • Walter Tross
    Walter Tross almost 10 years
    Quoting from their website: "You are limited to 1,000 API requests per day. If you need to make more requests, or need SSL support, see our paid plans."
  • imbondbaby
    imbondbaby almost 10 years
    I used it on my personal website so that is why I posted it. Thank you for the info... didn't realize it. I put much more effort on the post, so please see the updated post :)
  • mOna
    mOna over 9 years
    I tried your code, it returns this for me: Array ( [known] => false )
  • mOna
    mOna over 9 years
    when I try this : $ip = $_SERVER["REMOTE_ADDR"]; echo $ip; it returns it : 10.48.44.43, do you know what is the problem?? I used alspo maxmind geoip, and when I used geoip_country_name_by_addr($gi, $ip) againit returned me nothing...
  • mOna
    mOna over 9 years
    @imbondbaby: Hi, I tried your code, but for me it returns this :Array ( [country] => - ), I do not understand the problem since when i try to print this: $ipaddress = $_SERVER['REMOTE_ADDR']; it shows me this ip : 10.48.44.43, I can't understand why this ip does not work! I mean wherever I insert this number it does not return any country!!! counld u plz help me?
  • mOna
    mOna over 9 years
    @Joyce: I tried to use Maxmind API and DB, but I don't know why it does not work for me, actually it works in general, but for instance when I run this $_SERVER['REMOTE_ADDR'];it shows me this ip : 10.48.44.43, but when i use it in geoip_country_code_by_addr($gi, $ip), it returns nothing, any idea?
  • Joyce Babu
    Joyce Babu over 9 years
    It is a reserved ip address (internal ip address from your local network). Try running the code on a remote server.
  • mOna
    mOna over 9 years
    @EchtEinfachTV I can not get the country name as well, when I echo $cip, $iptolocation and $creatorlocation I get this: 10.48.44.43http://api.hostip.info/country.php?ip=10.48.44.43‌​XX , why it returns xx for country?
  • mOna
    mOna over 9 years
    @Antonimo: I can not get the country name as well, when I echo $cip, $iptolocation and $creatorlocation I get this: 10.48.44.43http://api.hostip.info/country.php?ip=10.48.44.43‌​XX , why it returns xx for country? –
  • Ram Sharma
    Ram Sharma over 9 years
    @mOna, it return your ip address. for more details pls, share your code.
  • mOna
    mOna over 9 years
    I found that problem is realted to my ip since it is for private network. then I fuond my real ip in ifconfig and used it in my program. then it worked:) Now, my question is how to get real ip in case of those users similar to me? (if they use local ip).. I wrote my code here: stackoverflow.com/questions/25958564/…
  • Hontoni
    Hontoni over 9 years
    anything starting with 10. is a local ip, check the manuals/wiki
  • Chandra Nakka
    Chandra Nakka over 9 years
    @echo_Me Maybe your server failed to connecting geoplugin.net API server.
  • M B Parvez
    M B Parvez about 9 years
    That's really cool. But while testing here are no values in the following fields "geoplugin_city, geoplugin_region, geoplugin_regionCode, geoplugin_regionName".. What is the reason? Is there any solution? Thanks in advance
  • madcrazydrumma
    madcrazydrumma about 9 years
    Keep getting 'undefined' for my country
  • Chandra Nakka
    Chandra Nakka about 9 years
    @madcrazydrumma What is your IP?
  • madcrazydrumma
    madcrazydrumma about 9 years
    @ChandraNakka 127.0.0.1 is the localhost server, my ip is currently 197.234.10.142 which should be in the Seychelles
  • machineaddict
    machineaddict almost 9 years
    Remember to cache the results for a defined period. Also, as a note, you should never rely on another website to get any data, the website might go down, the service could stop, etc. And if you get an increased number of visitors on your website, this service could ban you.
  • Richard Tinkler
    Richard Tinkler almost 8 years
    Used ip-api.com because they also supply ISP name!
  • AlexioVay
    AlexioVay over 7 years
    You used an else after else which causes an error. What did you try to prevent? REMOTE_ADDR should be available all the time?
  • 4 Leave Cover
    4 Leave Cover over 7 years
    Does this require user authorization just like how Geolocation did?
  • Eaten by a Grue
    Eaten by a Grue over 7 years
    @Vaia - Perhaps it should be but you never know.
  • AlexioVay
    AlexioVay over 7 years
    Is there a case where it isnt available you know of?
  • Eaten by a Grue
    Eaten by a Grue over 7 years
    @Vaia - from the PHP docs on $_SERVER: "There is no guarantee that every web server will provide any of these; servers may omit some, or provide others not listed here."
  • Nick
    Nick about 7 years
    echo ip_info("Visitor", "Country Code"); returns NULL
  • Nick
    Nick about 7 years
    Follow on: this is an issue when testing a site on localhost. Any way to fix for testing purposes? Uses the standard 127.0.0.1 localhost IP
  • Bram Vanroy
    Bram Vanroy almost 7 years
    Please provide more actual code than just hard links.
  • Roy Shoa
    Roy Shoa over 6 years
    I Used because they also supply the Timezone
  • Sayed
    Sayed over 6 years
    God bless you, man! I got more than what I asked for! Quick question: can I use it for prod? I mean, you're not going to put it down anytime soon, are you?
  • Jonathan
    Jonathan over 6 years
    Not at all :) I'm in fact adding more regions and more polish. Glad you found this to be of help :)
  • Sayed
    Sayed over 6 years
    Very helpful, specially with the additional params, solved more than one problem for me!
  • Jonathan
    Jonathan over 6 years
    Thanks for the positive feedback! I built around the most common usecases for such a tool, the goal was to eliminate having to do any additional processing after the geolocation, happy to see this paying off for users
  • Vignesh Chinnaiyan
    Vignesh Chinnaiyan almost 6 years
    Worked for ME. Thanks.
  • reformed
    reformed almost 6 years
    This API allows 100 (free) API calls per day.
  • reformed
    reformed almost 6 years
    This API allows 1000 (free) API calls per day.
  • Accountant م
    Accountant م over 5 years
    It should be noted that HTTP_X_FORWARDED_FOR and HTTP_CLIENT_IP used in the deep_detect option will get you the real IP of the user if he is using a proxy server -transparent proxy offcurse - , not the IP of the proxy server which is the client how is actually tcp-connected to my website. Thanks for this great answer
  • Dipanshu Mahla
    Dipanshu Mahla about 5 years
    The if-else part will give you the IP address of the visitor and the next part will return the country code. Try visiting api.wipmania.com and then api.wipmania.com/[your_IP_address]
  • Rick Hellewell
    Rick Hellewell over 4 years
    According to the docs on their site: "If geoplugin.net was responding perfectly, then stopped, then you have gone over the free lookup limit of 120 requests per minute. "
  • Rick Hellewell
    Rick Hellewell over 4 years
    Note there is a limit to requests; from their site: "If geoplugin.net was responding perfectly, then stopped, then you have gone over the free lookup limit of 120 requests per minute. "
  • Rick Hellewell
    Rick Hellewell over 4 years
    Later news from the link: "As of January 2, 2019 Maxmind discontinued the original GeoLite databases that we have been using in all these examples. You can read the full announcement here: support.maxmind.com/geolite-legacy-discontinuation-notice"
  • bleah1
    bleah1 over 4 years
    I can't make this work. I have copied the function and tried the first example and there is not a single echo or print on the page.
  • Ryan D
    Ryan D over 4 years
    This is awesome i've been looking for something like this for a while, well done!
  • Najeeb
    Najeeb almost 4 years
    Worked beautifully. Thanks!
  • richey
    richey over 3 years
    note that this only works with the GeoIP PECL extension of PHP installed (which is by default not bundled).
  • richey
    richey over 3 years
    In case anyone considers this, know that this database has to be purchased.
  • Pedro Lobito
    Pedro Lobito over 3 years
    There's a free version available.
  • richey
    richey over 3 years
    oh… can you help me with an URL please? Wherever I looked, I always ended up at 3 payment options.
  • Pedro Lobito
    Pedro Lobito over 3 years
    You've to signup for GeoLite2, but it's free to download after. dev.maxmind.com/geoip/geoip2/geolite2 - "To receive access to download the GeoLite2 databases at no charge, sign up for a GeoLite2 account."
  • Malachi
    Malachi over 3 years
    it's now actually geoplugin.com.... which.... you probably can refer to the other example (above)
  • Steve Moretz
    Steve Moretz about 3 years
    It uses object reference -> but the response is array change all to [''] instead.Also should get rid of all this @ suppresses.And also using curl is much better than file_get_contents.
  • lucaswxp
    lucaswxp almost 3 years
    Database is outdated, last update 2013. There is guide on how you can create the database yourself tho, using the 4 regional registries, but I didnt test it if still works
  • AndreyP
    AndreyP over 2 years
    Debian installation: sudo apt install php-geoip
  • Petr Nagy
    Petr Nagy almost 2 years
    Suppressing errors with @ was bad practice 10 years ago and is still a bad practice now.
  • Ajowi
    Ajowi almost 2 years
    I have not tested this but voted up for using curl as allow_url_fopen is generally disabled in most servers. It should work anyway.