[c#] Get user location by IP address

I have an ASP.NET website written in C#.

On this site I need to automatically show a start page based on the user's location.

Can I get name of user's city based on the IP address of the user ?

This question is related to c# asp.net

The answer is


Use http://ipinfo.io , You need to pay them if you make more than 1000 requests per day.

The code below requires the Json.NET package.

public static string GetUserCountryByIp(string ip)
{
    IpInfo ipInfo = new IpInfo();
    try
    {
        string info = new WebClient().DownloadString("http://ipinfo.io/" + ip);
        ipInfo = JsonConvert.DeserializeObject<IpInfo>(info);
        RegionInfo myRI1 = new RegionInfo(ipInfo.Country);
        ipInfo.Country = myRI1.EnglishName;
    }
    catch (Exception)
    {
        ipInfo.Country = null;
    }
    
    return ipInfo.Country;
}

And the IpInfo Class I used:

public class IpInfo
{
    [JsonProperty("ip")]
    public string Ip { get; set; }

    [JsonProperty("hostname")]
    public string Hostname { get; set; }

    [JsonProperty("city")]
    public string City { get; set; }

    [JsonProperty("region")]
    public string Region { get; set; }

    [JsonProperty("country")]
    public string Country { get; set; }

    [JsonProperty("loc")]
    public string Loc { get; set; }

    [JsonProperty("org")]
    public string Org { get; set; }

    [JsonProperty("postal")]
    public string Postal { get; set; }
}

Using the Request of following web site

http://ip-api.com/

Following is C# code for returning Country and Country Code

public  string GetCountryByIP(string ipAddress)
    {
        string strReturnVal;
        string ipResponse = IPRequestHelper("http://ip-api.com/xml/" + ipAddress);

        //return ipResponse;
        XmlDocument ipInfoXML = new XmlDocument();
        ipInfoXML.LoadXml(ipResponse);
        XmlNodeList responseXML = ipInfoXML.GetElementsByTagName("query");

        NameValueCollection dataXML = new NameValueCollection();

        dataXML.Add(responseXML.Item(0).ChildNodes[2].InnerText, responseXML.Item(0).ChildNodes[2].Value);

        strReturnVal = responseXML.Item(0).ChildNodes[1].InnerText.ToString(); // Contry
        strReturnVal += "(" + 

responseXML.Item(0).ChildNodes[2].InnerText.ToString() + ")";  // Contry Code 
 return strReturnVal;
}

And following is Helper for requesting url.

public string IPRequestHelper(string url) {

      HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
      HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();

      StreamReader responseStream = new StreamReader(objResponse.GetResponseStream());
      string responseRead = responseStream.ReadToEnd();

      responseStream.Close();
      responseStream.Dispose();

  return responseRead;
}

you can

using System.Net;
using System.IO;
using Newtonsoft.Json.Linq;
public ActionResult geoPlugin()
    {

        var url = "http://freegeoip.net/json/";
        var request = System.Net.WebRequest.Create(url);

        using (WebResponse wrs = request.GetResponse())
        using (Stream stream = wrs.GetResponseStream())
        using (StreamReader reader = new StreamReader(stream))
        {
            string json = reader.ReadToEnd();
            var obj = JObject.Parse(json);
            var City = (string)obj["city"];
            // - For Country = (string)obj["region_name"];                    
            //- For  CountryCode = (string)obj["country_code"];
            Session["CurrentRegionName"]= (string)obj["country_name"];
            Session["CurrentRegion"] = (string)obj["country_code"];
        }
        return RedirectToAction("Index");
    }

I was able to achieve this in ASP.NET MVC using the client IP address and freegeoip.net API. freegeoip.net is free and does not require any license.

Below is the sample code I used.

String UserIP = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (string.IsNullOrEmpty(UserIP))
{
    UserIP = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
}
string url = "http://freegeoip.net/json/" + UserIP.ToString();
WebClient client = new WebClient();
string jsonstring = client.DownloadString(url);
dynamic dynObj = JsonConvert.DeserializeObject(jsonstring);
System.Web.HttpContext.Current.Session["UserCountryCode"] = dynObj.country_code;

You can go through this post for more details.Hope it helps!


Following Code work for me.

Update:

As I am calling a free API request (json base ) IpStack.

    public static string CityStateCountByIp(string IP)
    {
      //var url = "http://freegeoip.net/json/" + IP;
      //var url = "http://freegeoip.net/json/" + IP;
        string url = "http://api.ipstack.com/" + IP + "?access_key=[KEY]";
        var request = System.Net.WebRequest.Create(url);
        
         using (WebResponse wrs = request.GetResponse())
         using (Stream stream = wrs.GetResponseStream())
         using (StreamReader reader = new StreamReader(stream))
         {
          string json = reader.ReadToEnd();
          var obj = JObject.Parse(json);
            string City = (string)obj["city"];
            string Country = (string)obj["region_name"];                    
            string CountryCode = (string)obj["country_code"];
        
           return (CountryCode + " - " + Country +"," + City);
           }

  return "";

}

Edit : First, it was http://freegeoip.net/ now it's https://ipstack.com/ (and maybe now it's a paid service- Free Up to 10,000 request/month)


I have tried using http://ipinfo.io and this JSON API works perfectly. First, you need to add the below mentioned namespaces:

using System.Linq;
using System.Web; 
using System.Web.UI.WebControls;
using System.Net;
using System.IO;
using System.Xml;
using System.Collections.Specialized;

For localhost it will give dummy data as AU. You can try hardcoding your IP and get results:

namespace WebApplication4
{
    public partial class WebForm1 : System.Web.UI.Page
    {

        protected void Page_Load(object sender, EventArgs e)
         {

          string VisitorsIPAddr = string.Empty;
          //Users IP Address.                
          if (HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null)
          {
              //To get the IP address of the machine and not the proxy
              VisitorsIPAddr =   HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();
          }
          else if (HttpContext.Current.Request.UserHostAddress.Length != 0)
          {
              VisitorsIPAddr = HttpContext.Current.Request.UserHostAddress;`enter code here`
          }

          string res = "http://ipinfo.io/" + VisitorsIPAddr + "/city";
          string ipResponse = IPRequestHelper(res);

        }

        public string IPRequestHelper(string url)
        {

            string checkURL = url;
            HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
            HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
            StreamReader responseStream = new StreamReader(objResponse.GetResponseStream());
            string responseRead = responseStream.ReadToEnd();
            responseRead = responseRead.Replace("\n", String.Empty);
            responseStream.Close();
            responseStream.Dispose();
            return responseRead;
        }


    }
}

It's good sample for you:

public class IpProperties
    {
        public string Status { get; set; }
        public string Country { get; set; }
        public string CountryCode { get; set; }
        public string Region { get; set; }
        public string RegionName { get; set; }
        public string City { get; set; }
        public string Zip { get; set; }
        public string Lat { get; set; }
        public string Lon { get; set; }
        public string TimeZone { get; set; }
        public string ISP { get; set; }
        public string ORG { get; set; }
        public string AS { get; set; }
        public string Query { get; set; }
    }
 public string IPRequestHelper(string url)
    {
        HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
        HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();

        StreamReader responseStream = new StreamReader(objResponse.GetResponseStream());
        string responseRead = responseStream.ReadToEnd();

        responseStream.Close();
        responseStream.Dispose();

        return responseRead;
    }

    public IpProperties GetCountryByIP(string ipAddress)
    {
        string ipResponse = IPRequestHelper("http://ip-api.com/xml/" + ipAddress);
        using (TextReader sr = new StringReader(ipResponse))
        {
            using (System.Data.DataSet dataBase = new System.Data.DataSet())
            {
                IpProperties ipProperties = new IpProperties();
                dataBase.ReadXml(sr);
                ipProperties.Status = dataBase.Tables[0].Rows[0][0].ToString();
                ipProperties.Country = dataBase.Tables[0].Rows[0][1].ToString();
                ipProperties.CountryCode = dataBase.Tables[0].Rows[0][2].ToString();
                ipProperties.Region = dataBase.Tables[0].Rows[0][3].ToString();
                ipProperties.RegionName = dataBase.Tables[0].Rows[0][4].ToString();
                ipProperties.City = dataBase.Tables[0].Rows[0][5].ToString();
                ipProperties.Zip = dataBase.Tables[0].Rows[0][6].ToString();
                ipProperties.Lat = dataBase.Tables[0].Rows[0][7].ToString();
                ipProperties.Lon = dataBase.Tables[0].Rows[0][8].ToString();
                ipProperties.TimeZone = dataBase.Tables[0].Rows[0][9].ToString();
                ipProperties.ISP = dataBase.Tables[0].Rows[0][10].ToString();
                ipProperties.ORG = dataBase.Tables[0].Rows[0][11].ToString();
                ipProperties.AS = dataBase.Tables[0].Rows[0][12].ToString();
                ipProperties.Query = dataBase.Tables[0].Rows[0][13].ToString();

                return ipProperties;
            }
        }
    }

And test:

var ipResponse = GetCountryByIP("your ip address or domain name :)");

Return country

static public string GetCountry()
{
    return new WebClient().DownloadString("http://api.hostip.info/country.php");
}

Usage:

Console.WriteLine(GetCountry()); // will return short code for your country

Return info

static public string GetInfo()
{
    return new WebClient().DownloadString("http://api.hostip.info/get_json.php");
}

Usage:

Console.WriteLine(GetInfo()); 
// Example:
// {
//    "country_name":"COUNTRY NAME",
//    "country_code":"COUNTRY CODE",
//    "city":"City",
//    "ip":"XX.XXX.XX.XXX"
// }

You need an IP-address-based reverse geocoding API... like the one from ipdata.co. I'm sure there are plenty of options available.

You may want to allow the user to override this, however. For example, they could be on a corporate VPN which makes the IP address look like it's in a different country.


An Alternative to using an API is to use HTML 5 location Navigator to query the browser about the User location. I was looking for a similar approach as in the subject question but I found that HTML 5 Navigator works better and cheaper for my situation. Please consider that your scinario might be different. To get the User position using Html5 is very easy:

function getLocation()
{
    if (navigator.geolocation)
    {
        navigator.geolocation.getCurrentPosition(showPosition);
    }
    else
    {
        console.log("Geolocation is not supported by this browser.");
     }
}

function showPosition(position)
{
      console.log("Latitude: " + position.coords.latitude + 
  "<br>Longitude: " + position.coords.longitude); 
}

Try it yourself on W3Schools Geolocation Tutorial


IPInfoDB has an API that you can call in order to find a location based on an IP address.

For "City Precision", you call it like this (you'll need to register to get a free API key):

 http://api.ipinfodb.com/v2/ip_query.php?key=<your_api_key>&ip=74.125.45.100&timezone=false

Here's an example in both VB and C# that shows how to call the API.


What you need is called a "geo-IP database". Most of them cost some money (albeit not too expensive), especially fairly precise ones. One of the most widely used is MaxMind's database. They have a fairly good free version of IP-to-city database called GeoLity City - it has lots of restrictions, but if you can cope with that that would be probably your best choice, unless you have some money to spare for a subscription to more accurate product.

And, yeah, they do have a C# API to query geo-IP databases available.


    public static string GetLocationIPAPI(string ipaddress)
    {
        try
        {
            IPDataIPAPI ipInfo = new IPDataIPAPI();
            string strResponse = new WebClient().DownloadString("http://ip-api.com/json/" + ipaddress);
            if (strResponse == null || strResponse == "") return "";
            ipInfo = JsonConvert.DeserializeObject<IPDataIPAPI>(strResponse);
            if (ipInfo == null || ipInfo.status.ToLower().Trim() == "fail") return "";
            else return ipInfo.city + "; " + ipInfo.regionName + "; " + ipInfo.country + "; " + ipInfo.countryCode;
        }
        catch (Exception)
        {
            return "";
        }
    }

public class IPDataIPINFO
{
    public string ip { get; set; }
    public string city { get; set; }
    public string region { get; set; }
    public string country { get; set; }
    public string loc { get; set; }
    public string postal { get; set; }
    public int org { get; set; }

}

==========================

    public static string GetLocationIPINFO(string ipaddress)
    {            
        try
        {
            IPDataIPINFO ipInfo = new IPDataIPINFO();
            string strResponse = new WebClient().DownloadString("http://ipinfo.io/" + ipaddress);
            if (strResponse == null || strResponse == "") return "";
            ipInfo = JsonConvert.DeserializeObject<IPDataIPINFO>(strResponse);
            if (ipInfo == null || ipInfo.ip == null || ipInfo.ip == "") return "";
            else return ipInfo.city + "; " + ipInfo.region + "; " + ipInfo.country + "; " + ipInfo.postal;
        }
        catch (Exception)
        {
            return "";
        }
    }

public class IPDataIPAPI
{
    public string status { get; set; }
    public string country { get; set; }
    public string countryCode { get; set; }
    public string region { get; set; }
    public string regionName { get; set; }
    public string city { get; set; }
    public string zip { get; set; }
    public string lat { get; set; }
    public string lon { get; set; }
    public string timezone { get; set; }
    public string isp { get; set; }
    public string org { get; set; }
    public string @as { get; set; }
    public string query { get; set; }
}

==============================

    private static string GetLocationIPSTACK(string ipaddress)
    {
        try
        {
            IPDataIPSTACK ipInfo = new IPDataIPSTACK();
            string strResponse = new WebClient().DownloadString("http://api.ipstack.com/" + ipaddress + "?access_key=XX384X1XX028XX1X66XXX4X04XXXX98X");
            if (strResponse == null || strResponse == "") return "";
            ipInfo = JsonConvert.DeserializeObject<IPDataIPSTACK>(strResponse);
            if (ipInfo == null || ipInfo.ip == null || ipInfo.ip == "") return "";
            else return ipInfo.city + "; " + ipInfo.region_name + "; " + ipInfo.country_name + "; " + ipInfo.zip;
        }
        catch (Exception)
        {
            return "";
        }
    }

public class IPDataIPSTACK
{
    public string ip { get; set; }
    public int city { get; set; }
    public string region_code { get; set; }
    public string region_name { get; set; }
    public string country_code { get; set; }
    public string country_name { get; set; }
    public string zip { get; set; }


}

You'll probably have to use an external API, most of which cost money.

I did find this though, seems to be free: http://hostip.info/use.html