C# Code to get Whois information of a domain name


What is Whois ?
Whois is a protocol to fetch the registered users of a internet resource such as a domain name or an IP block, it is documented in RFC 3912.

Whois information can be used to know some basic information about a domian name like the person or the organization it is registered to, registration & expiry date etc.,

One of the popular use case for the whois information is to check the availability of a domain name, you can read more about this in my other post.

The protocol
The whois protocol is a pretty straight forward TCP based query response protocol, each TLD or top level domain(example .com, .net, .org, etc., ) will have a whois server that will listen on the port number 43 for the queries, Once a request is received the server will check its internal database for the domain name details and return the information in the response, the availability of a domain name in a particular TLD can be identified from the whois information returned, the structure of the whois might differ from server to server.

The protocol can be explained simply as follows

Connect to the service host
   TCP: service port 43 decimal
Send a single "command", ending with a new line character(ASCII CR and then ASCII LF)
Receive information in response to the command line.  The
server closes its connections as soon as the output is
finished.

Implementation In C#
To get the Whois information of any domain, we need 3 parameters

  1. Domain name
  2. Record type, which is “domain”
  3. The whois server address for the TLD of the given domain name

A collection of Whois server list is maintained by nirsoft.net which we can use to determine the correct Whois server for a given domain name based on its TLD

Once we get this, all we have to do is connect to the server on port 43 using TCP and send the query as combination of the text “domain” and your domain name, seperated by a single space character ” “, your query should always end with a new line character.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace DomainTools
{
/// <summary>
/// A class to lookup whois information.
/// </summary>
public class Whois
{
private const int Whois_Server_Default_PortNumber = 43;
private const string Domain_Record_Type = "domain";
private const string DotCom_Whois_Server = "whois.verisign-grs.com";
/// <summary>
/// Retrieves whois information
/// </summary>
/// <param name="domainName">The registrar or domain or name server whose whois information to be retrieved</param>
/// <param name="recordType">The type of record i.e a domain, nameserver or a registrar</param>
/// <returns></returns>
public static string Lookup(string domainName)
{
using (TcpClient whoisClient = new TcpClient())
{
whoisClient.Connect(DotCom_Whois_Server, Whois_Server_Default_PortNumber);
string domainQuery = Domain_Record_Type + " " + domainName + "\r\n";
byte[] domainQueryBytes = Encoding.ASCII.GetBytes(domainQuery.ToCharArray());
Stream whoisStream = whoisClient.GetStream();
whoisStream.Write(domainQueryBytes, 0, domainQueryBytes.Length);
StreamReader whoisStreamReader = new StreamReader(whoisClient.GetStream(), Encoding.ASCII);
string streamOutputContent = "";
List<string> whoisData = new List<string>();
while (null != (streamOutputContent = whoisStreamReader.ReadLine()))
{
whoisData.Add(streamOutputContent);
}
whoisClient.Close();
return String.Join(Environment.NewLine, whoisData);
}
}
}
}
view raw Whois.cs hosted with ❤ by GitHub

You can get the whois information by just calling the Whois.Lookup method with your domain name as parameter as shown in the code below.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DomainTools
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter a domain name to get the whois information.");
var domainName = Console.ReadLine();
try
{
var whoisText = Whois.Lookup(domainName);
Console.WriteLine(whoisText);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.WriteLine("Press any key to exit..");
Console.Read();
}
}
}
view raw Program.cs hosted with ❤ by GitHub

Note
Please note that this is implementation works only “.com” TLD domains, you have to change the server name to make it work for other TLD’s, you can find the implementation which works with different TLD’s in the github project I linked below

Usefull links

This post is originally published on coderbuddy.wordpress.com.

9 thoughts on “C# Code to get Whois information of a domain name

  1. Here is the extended class I hacked in a prettier version. My comment above should probably be deleted, but I couldn’t find a delete button.

    I extended this class because I work for a service provider, and I wrote an app that looks up whois information for our customer domains. I did some RegEx matching in the code to match different formats of whois records, the RegEx’s could be improved. Also, I created exceptions which I called “idn1-idn4″ or something like that, which just means “international domain name” each idn exception could use multiple TLD’s if they return whois information in the same format.

    Here is the code.

    class Whois
    {
    private static object locker = new object();
    public enum RecordType { whois, domain, nameserver, registrar, expiration };
    static string[] idns1 = new string[] { “.ca” }; //handle idn’s that have different whois formats
    static string[] idns2 = new string[] { “.uk” };
    static string[] idns3 = new string[] { “.ae” };
    static string[] idns4 = new string[] { “.ch” };
    static string[] idns5 = new string[] { “.eu” };
    static string[] idns6 = new string[] { “.info” };
    public static string getwhois(string domain) //gets the whois record string (replaces \n with \r\n) from the designated whois server for the domain’s TLD, see getwhoisserver()
    {
    TcpClient tcp = new TcpClient();
    tcp.Connect(getwhoisserver(gettopleveldomain(domain)), 43);
    string strDomain = (domain + “\r\n”);
    byte[] arrdomain = Encoding.ASCII.GetBytes(strDomain);
    Stream s = tcp.GetStream();
    s.Write(arrdomain, 0, strDomain.Length);
    StreamReader sr = new StreamReader(tcp.GetStream(), Encoding.ASCII);
    string whois = sr.ReadToEnd().Replace(“\n”, “\r\n”);
    tcp.Close();
    return whois;
    }
    public static void refreshwhois(string domain, string whoispath) //created this function for caching whois files on the server
    {
    string filename = whoispath + domain + “.whois.txt”;
    //if (!File.Exists(filename)) File.Create(filename);
    //check the fileinfo for creation date, if more than a week old delete it and refresh it
    FileInfo fi = new FileInfo(filename);
    if (File.Exists(filename) && fi.CreationTime row.Contains(“Name Servers:”)) + 1; }
    else if (idns2.Contains(gettopleveldomain(domainname))) {
    index = Array.FindIndex(whoislines, row => row.Contains(“Name servers:”)) + 1;
    return whoislines[index].Replace(“\r”, “”).Trim();
    }
    else { index = Array.FindIndex(whoislines, row => row.Contains(“Name Server: “)); }
    return whoislines[index].Split(‘:’)[1].Replace(“\r”,””).Trim();
    case RecordType.registrar:
    if (idns1.Contains(gettopleveldomain(domainname))) { index = Array.FindIndex(whoislines, row => row.Contains(“Registrar:”)) + 1; }
    else if (idns2.Contains(gettopleveldomain(domainname))) { index = Array.FindIndex(whoislines, row => row.Contains(“Registrar”)) + 2; }
    else { index = Array.FindIndex(whoislines, row => row.Contains(“Registrar:”)); }
    return whoislines[index].Split(‘:’)[1].Trim();
    case RecordType.expiration:
    if (idns1.Contains(gettopleveldomain(domainname)) || idns2.Contains(gettopleveldomain(domainname))) { index = Array.FindIndex(whoislines, row => row.Contains(“Expiry date:”)); }
    else { index = Array.FindIndex(whoislines, row => row.Contains(“Expiration Date:”)); }
    return formatexpiration(whoislines[index].Replace(“\r”,””));
    }
    return null;
    } //gets parameters from live whois queries, expensive since you’ll hit the server 3-4 times per domain iteration
    public static string getwhoisinfo(string domainname, RecordType recordType, string whoisfilename) //gets parameters from whois text file
    {
    string whois = null;
    using (StreamReader sr = new StreamReader(whoisfilename))
    {
    whois = sr.ReadToEnd();
    sr.Dispose();
    }
    string[] whoislines = Regex.Split(whois, “\r\n”);
    var index = 0;
    switch (recordType)
    {
    case RecordType.whois:
    return whois;
    case RecordType.nameserver:
    if (idns1.Contains(gettopleveldomain(domainname)))
    {
    index = Array.FindIndex(whoislines, row => row.Contains(“Name Servers:”)) + 1;
    }
    else if (idns2.Contains(gettopleveldomain(domainname))) {
    index = Array.FindIndex(whoislines, row => row.Contains(“Name servers:”)) + 1;
    return whoislines[index].Replace(“\r”, “”).Trim().ToLower();
    }
    else if (idns4.Contains(gettopleveldomain(domainname)))
    {
    index = Array.FindIndex(whoislines, row => row.Contains(“Name servers:”)) + 1;
    return whoislines[index].Replace(“\r”, “”).Trim().ToLower();
    }
    else if (idns5.Contains(gettopleveldomain(domainname)))
    {
    index = Array.FindIndex(whoislines, row => row.Contains(“Name servers:”)) + 1;
    return whoislines[index].Replace(“\r”, “”).Trim().ToLower();
    }
    else
    {
    index = Array.FindIndex(whoislines, row => row.Contains(“Name Server:”));
    }
    return whoislines[index].Split(‘:’)[1].Replace(“\r”, “”).Trim().ToLower();
    case RecordType.registrar:
    if (idns1.Contains(gettopleveldomain(domainname)) || idns5.Contains(gettopleveldomain(domainname))) { index = Array.FindIndex(whoislines, row => row.Contains(“Registrar:”)) + 1; }
    else if (idns2.Contains(gettopleveldomain(domainname))) { index = Array.FindIndex(whoislines, row => row.Contains(“Registrar”)) + 2; }
    else if (idns3.Contains(gettopleveldomain(domainname))) { index = Array.FindIndex(whoislines, row => row.Contains(“Registrar Name:”)); }
    else if (idns4.Contains(gettopleveldomain(domainname))) return null;
    else { index = Array.FindIndex(whoislines, row => row.Contains(“Registrar:”)); }
    return whoislines[index].Split(‘:’)[1].Replace(“\r”,””).Trim();
    case RecordType.expiration:
    if (idns1.Contains(gettopleveldomain(domainname)) || idns2.Contains(gettopleveldomain(domainname))) {
    index = Array.FindIndex(whoislines, row => row.Contains(“Expiry date:”));
    return formatexpiration(whoislines[index].Replace(“\r”, “”));
    }
    else if (idns3.Contains(gettopleveldomain(domainname)) || idns4.Contains(gettopleveldomain(domainname)) || idns5.Contains(gettopleveldomain(domainname)))
    {
    return null;
    }
    else if (idns6.Contains(gettopleveldomain(domainname)))
    {
    index = Array.FindIndex(whoislines, row => row.Contains(“Expiration Date:”));
    return formatexpiration(whoislines[index]);
    }
    else
    {
    index = Array.FindIndex(whoislines, row => row.Contains(“Expiration Date:”));
    return formatexpiration(whoislines[index]);
    }
    }
    return null;
    }
    public static string formatexpiration(string strexp)
    {
    string year = null;
    string month = null;
    string day = null;
    if (strexp.Contains(“Domain Expiration Date:”)) strexp = strexp.Replace(“Domain Expiration Date:”, “”);
    if (strexp.Contains(“Expiration Date:”)) strexp = strexp.Replace(“Expiration Date:”, “”);
    if (strexp.Contains(“Expiry date:”)) strexp = strexp.Replace(“Expiry date:”, “”);
    strexp = strexp.Trim();
    if (strexp.Contains(“/”) && Regex.IsMatch(strexp.Split(‘/’)[0], @”^[0-9]+$”) && Regex.IsMatch(strexp.Split(‘/’)[1], @”^[0-9]+$”) && Regex.IsMatch(strexp.Split(‘/’)[2], @”^[0-9]+$”))
    {
    //format = “yyyy/mm/dd”;
    month = DateTime.ParseExact(strexp.Split(‘/’)[1], “MM”, CultureInfo.CurrentCulture).Month.ToString();
    day = DateTime.ParseExact(strexp.Split(‘/’)[2], “dd”, CultureInfo.CurrentCulture).Day.ToString();
    year = DateTime.ParseExact(strexp.Split(‘/’)[0], “yyyy”, CultureInfo.CurrentCulture).Year.ToString();
    }
    if (Regex.IsMatch(strexp.Split(‘ ‘)[0], @”^[a-zA-Z]+$”) && Regex.IsMatch(strexp.Split(‘ ‘)[1], @”^[a-zA-Z]+$”) && Regex.IsMatch(strexp.Split(‘ ‘)[2], @”^[0-9]+$”))
    {
    //format Mon Jan 26 23:59:59 GMT 2015
    month = DateTime.ParseExact(strexp.Split(‘ ‘)[1], “MMM”, CultureInfo.CurrentCulture).Month.ToString();
    day = DateTime.ParseExact(strexp.Split(‘ ‘)[2], “dd”, CultureInfo.CurrentCulture).Day.ToString();
    year = DateTime.ParseExact(strexp.Split(‘ ‘)[5], “yyyy”, CultureInfo.CurrentCulture).Year.ToString();
    }
    if (Regex.IsMatch(strexp, @”^\d{2}-[a-zA-Z]{3}-\d{4}\s\d{2}:\d{2}:\d{2}\s[a-zA-Z]{3}$”)) //format 21-Feb-2016 00:00:00 UTC
    {
    strexp = strexp.Split(‘ ‘)[0];
    month = DateTime.ParseExact(strexp.Split(‘-‘)[1], “MMM”, CultureInfo.CurrentCulture).Month.ToString();
    day = DateTime.ParseExact(strexp.Split(‘-‘)[0], “dd”, CultureInfo.CurrentCulture).Day.ToString();
    year = DateTime.ParseExact(strexp.Split(‘-‘)[2], “yyyy”, CultureInfo.CurrentCulture).Year.ToString();
    }
    if (Regex.IsMatch(strexp.Split(‘ ‘)[0], @”^\d{2}-[a-zA-Z]{3}-\d{4}”)) //format 21-Feb-2016
    {
    month = DateTime.ParseExact(strexp.Split(‘-‘)[1], “MMM”, CultureInfo.CurrentCulture).Month.ToString();
    day = DateTime.ParseExact(strexp.Split(‘-‘)[0], “dd”, CultureInfo.CurrentCulture).Day.ToString();
    year = DateTime.ParseExact(strexp.Split(‘-‘)[2], “yyyy”, CultureInfo.CurrentCulture).Year.ToString();
    }
    return month + “/” + day + “/” + year;
    }//formats the expiration dates for different types of whois records
    public static string gettopleveldomain(string domainname)
    {
    string tld = domainname.Substring(domainname.LastIndexOf(“.”), (domainname.Length – domainname.LastIndexOf(“.”)));
    return tld;
    }//returns the tld of any given domain name string (anything after and including the last “.”)
    public static string getwhoisserver(string topleveldomain)
    {
    string whoisserver = null;
    switch (topleveldomain)
    {
    case “.com”:
    whoisserver = “whois.crsnic.net”;
    break;
    case “.net”:
    whoisserver = “whois.crsnic.net”;
    break;
    case “.org”:
    whoisserver = “whois.pir.org”;
    Thread.Sleep(15000);
    break;
    case “.edu”:
    whoisserver = “whois.crsnic.net”;
    break;
    case “.co”:
    whoisserver = “whois.nic.co”;
    break;
    case “.biz”:
    whoisserver = “whois.neulevel.biz”;
    break;
    case “.info”:
    whoisserver = “whois.afilias.info”;
    break;
    case “.us”:
    whoisserver = “whois.nic.us”;
    break;
    case “.uk”:
    whoisserver = “whois.nic.uk”;
    break;
    case “.ca”:
    whoisserver = “whois.cira.ca”;
    break;
    case “.de”:
    whoisserver = “whois.nic.de”;
    break;
    case “.ws”:
    whoisserver = “whois.nic.ws”;
    break;
    case “.au”:
    whoisserver = “whois.aunic.net”;
    break;
    case “.nu”:
    whoisserver = “whois.nic.nu”;
    break;
    case “.eu”:
    whoisserver = “whois.eu”;
    break;
    case “.ae”:
    whoisserver = “whois.aeda.net.ae”;
    break;
    case “.gov”:
    whoisserver = “whois.nic.gov”;
    break;
    case “.ch”:
    whoisserver = “whois.nic.ch”;
    break;
    }
    return whoisserver;
    }//gets the whois server name for a domain’s tld
    }

    Like

Comments are closed.