24

Note: This is not a library recommendation question. It is rather about possible approaches to the problem.

Question: What approaches are possible to retreive WhoIs information from given IP address in Python 3? The result should contain at least:

  • Registration country
  • ISP name, address, abuse email
  • If registered, the domain name
  • Registration and expiery dates
  • Bonus points if the result is not plain text and is the above info is structured

I am not looking for wrappers around the shell "whois" command as the program must work under Windows.

Before asking this question, google gave me the following libraries:

The following throw errors when installing via pip or when during importing:

  • BulkWhois
  • WhoisClient
  • cymruwhois
  • dwhois
  • ipwhois
  • pyiptools
  • python-whois
  • pywhois
  • uwhoisd
  • whois
  • whoislookup
  • whoispy

The following libraries do work in Python 3, however they do the reverse of what I want - they look up by domain name, not by IP address:

  • nicnames
  • pythonwhois

I have looked into the following questions before asking:

Community
  • 1
  • 1
Babken Vardanyan
  • 14,090
  • 13
  • 68
  • 87
  • Um. Yes, it is. I'm confused what you're asking for here, if not for a library or service. Googling around for a moment found several, RESTy/JSONy services. – Michael Petrotta Jul 04 '14 at 20:25
  • So you basically want to replicate what the whois command does? the source code is not specially long so you can start there: [whois.c](https://searchcode.com/codesearch/view/32617104/). Here's an example in python: [link](http://www.admon.org/programming/query-domain-name-whois-info-by-python/) – user3557327 Jul 04 '14 at 20:28
  • @user3557327 Well, that C file requires Unix/other? headers. Add the complexity of importing C functions to python. – Babken Vardanyan Jul 04 '14 at 20:32
  • @MichaelPetrotta Let me lookup what those services are. – Babken Vardanyan Jul 04 '14 at 20:33
  • you can use `socket.gethostbyaddr` and pass it to `whois.whois` – Padraic Cunningham Jul 04 '14 at 21:08
  • @PadraicCunningham The `whois` module throws this error when importingto Python 3: `...ImportError: cannot import name 'WhoisEntry'` – Babken Vardanyan Jul 05 '14 at 07:07
  • @MichaelPetrotta Exactly! That's what the question is about - a (different) approach you described is to manually use parse a response from online service. Now if you write your commant as an answer here and suggest some free JSON/REST service, I'll accept your answer. (I looked into first 10 results of google search for `whois json` and all of them are either paid or lookup only by domain name) – Babken Vardanyan Jul 05 '14 at 07:37
  • uwhoisd currently doesn't support IP lookups, though it's something I'd like to add. What errors did you get when installing it? Currently the documentation isn't what it could be, though I'm hoping to fix that soon. – Keith Gaughan May 03 '16 at 17:00
  • @KeithGaughan http://pastie.org/10823660 – Babken Vardanyan May 04 '16 at 10:20
  • @BabkenVardanyan Thanks! I see the issue. Unfortunately, Diesel is stuck on Python 2, and it's using unqualified relative imports there. I'm hoping to get rid of Diesel shortly and replace it with something that works on Python 2 and Python 3. – Keith Gaughan May 04 '16 at 16:58

2 Answers2

31

Install the stable release of dnspython from here

Then pip3 install ipwhois.

In [37]: from ipwhois import IPWhois

In [38]: obj = IPWhois('74.125.225.229')

In [39]: res=obj.lookup()

In [40]: res["nets"][0]['country']
Out[40]: 'US'

In [41]: res["nets"][0]['abuse_emails']
Out[41]: 'arin-contact@google.com'

In [42]: from pprint import pprint

In [43]: pprint(res)
{'asn': '15169',
 'asn_cidr': '74.125.225.0/24',
 'asn_country_code': 'US',
 'asn_date': '2007-03-13',
 'asn_registry': 'arin',
 'nets': [{'abuse_emails': 'arin-contact@google.com',
           'address': '1600 Amphitheatre Parkway',
           'cidr': '74.125.0.0/16',
           'city': 'Mountain View',
           'country': 'US',
           'created': '2007-03-13T00:00:00',
           'description': 'Google Inc.',
           'misc_emails': None,
           'name': 'GOOGLE',
           'postal_code': '94043',
           'state': 'CA',
           'tech_emails': 'arin-contact@google.com',
           'updated': '2012-02-24T00:00:00'}],
 'query': '74.125.225.229',
 'raw': None}

HTTP:

In [44]: res=obj.lookup_rws()

In [45]: pprint(res)
{'asn': '15169',
 'asn_cidr': '74.125.225.0/24',
 'asn_country_code': 'US',
 'asn_date': '2007-03-13',
 'asn_registry': 'arin',
 'nets': [{'abuse_emails': 'arin-contact@google.com',
           'address': '1600 Amphitheatre Parkway',
           'cidr': '74.125.0.0/16',
           'city': 'Mountain View',
           'country': 'US',
           'created': '2007-03-13T12:09:54-04:00',
           'description': 'Google Inc.',
           'misc_emails': None,
           'name': 'GOOGLE',
           'postal_code': '94043',
           'state': 'CA',
           'tech_emails': 'arin-contact@google.com',
           'updated': '2012-02-24T09:44:34-05:00'}],
 'query': '74.125.225.229',
 'raw': None}

The API has changed, for the legacy ipwhois IPWhois.lookup() is deprecated as of v0.12.0 and will be removed. Legacy whois lookups were moved to IPWhois.lookup_whois()..

You can access that method, I have disabled warnings to be able to see the output, there are deprecated warnings that should be taken into account in real use cases:

In [30]: from warnings import filterwarnings

In [31]: filterwarnings( action="ignore")

In [32]: from ipwhois import IPWhois

In [33]: obj = IPWhois('74.125.225.229')

In [34]: obj.lookup_whois()
Out[34]: 
{'asn': '15169',
 'asn_cidr': '74.125.225.0/24',
 'asn_country_code': 'US',
 'asn_date': '2007-03-13',
 'asn_description': 'GOOGLE - Google Inc., US',
 'asn_registry': 'arin',
 'nets': [{'address': '1600 Amphitheatre Parkway',
   'cidr': '74.125.0.0/16',
   'city': 'Mountain View',
   'country': 'US',
   'created': '2007-03-13',
   'description': 'Google Inc.',
   'emails': ['arin-contact@google.com', 'network-abuse@google.com'],
   'handle': 'NET-74-125-0-0-1',
   'name': 'GOOGLE',
   'postal_code': '94043',
   'range': '74.125.0.0 - 74.125.255.255',
   'state': 'CA',
   'updated': '2012-02-24'}],
 'nir': None,
 'query': '74.125.225.229',
 'raw': None,
 'raw_referral': None,
 'referral': None}

The docs state, IPWhois.lookup_rdap() is now the recommended lookup method. RDAP provides a far better data structure than legacy whois and REST lookups (previous implementation). RDAP queries allow for parsing of contact information and details for users, organizations, and groups. RDAP also provides more detailed network information.

But following the usage example verbatim, or adding the asn_methods=["whois"]), stills gives deprecation warnings so, again, that is something that needs to be addressed in actual use cases.

In [31]: from ipwhois import IPWhois

In [32]: obj = IPWhois('74.125.225.229')
/usr/local/lib/python3.6/site-packages/ipwhois/net.py:138: UserWarning: allow_permutations has been deprecated and will be removed. It is no longer needed, due to the deprecation of asn_alts, and the addition of the asn_methods argument.
  warn('allow_permutations has been deprecated and will be removed. '

In [33]:  obj.lookup_rdap(asn_methods=["whois"])
/usr/local/lib/python3.6/site-packages/ipwhois/asn.py:302: UserWarning: IPASN._parse_fields_whois() has been deprecated and will be removed. You should now use IPASN.parse_fields_whois().
  warn('IPASN._parse_fields_whois() has been deprecated and will be '
Out[33]: 
{'asn': '15169',
 'asn_cidr': '74.125.225.0/24',
 'asn_country_code': 'US',
 'asn_date': '2007-03-13',
 'asn_description': 'GOOGLE - Google Inc., US',
 'asn_registry': 'arin',
 'entities': ['GOGL'],
 'network': {'cidr': '74.125.0.0/16',
  'country': None,
  'end_address': '74.125.255.255',
  'events': [{'action': 'last changed',
    'actor': None,
    'timestamp': '2012-02-24T09:44:34-05:00'},
   {'action': 'registration',
    'actor': None,
    'timestamp': '2007-03-13T12:09:54-04:00'}],
  'handle': 'NET-74-125-0-0-1',
  'ip_version': 'v4',
  'links': ['https://rdap.arin.net/registry/ip/074.125.000.000',
   'https://whois.arin.net/rest/net/NET-74-125-0-0-1'],
  'name': 'GOOGLE',
  'notices': [{'description': 'By using the ARIN RDAP/Whois service, you are agreeing to the RDAP/Whois Terms of Use',
    'links': ['https://www.arin.net/whois_tou.html'],
    'title': 'Terms of Service'}],
  'parent_handle': 'NET-74-0-0-0-0',
  'raw': None,
  'remarks': None,
  'start_address': '74.125.0.0',
  'status': None,
  'type': None},
 'nir': None,
 'objects': {'GOGL': {'contact': {'address': [{'type': None,
      'value': '1600 Amphitheatre Parkway\nMountain View\nCA\n94043\nUNITED STATES'}],
    'email': None,
    'kind': 'org',
    'name': 'Google Inc.',
    'phone': None,
    'role': None,
    'title': None},
   'entities': ['ABUSE5250-ARIN', 'ZG39-ARIN'],
   'events': [{'action': 'last changed',
     'actor': None,
     'timestamp': '2017-01-28T08:32:29-05:00'},
    {'action': 'registration',
     'actor': None,
     'timestamp': '2000-03-30T00:00:00-05:00'}],
   'events_actor': None,
   'handle': 'GOGL',
   'links': ['https://rdap.arin.net/registry/entity/GOGL',
    'https://whois.arin.net/rest/org/GOGL'],
   'notices': None,
   'raw': None,
   'remarks': None,
   'roles': ['registrant'],
   'status': None}},
 'query': '74.125.225.229',
 'raw': None}
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
  • 1
    I can just `pip3 install dnspython3` btw :) – Babken Vardanyan Jul 05 '14 at 13:39
  • 3
    `AttributeError: 'IPWhois' object has no attribute 'lookup'`. Instead use `ipwhois_obj.lookup_whois()` or `ipwhois_obj.lookup_rdap()` – gies0r Sep 06 '17 at 11:39
  • 1
    @gies0r, you can use `lookup_whois()`, lookup was deprecated a while back and removed in more recent versions, even using the latest examples, there are still warnings, so opening an issue on github may be worth following up on. – Padraic Cunningham Sep 06 '17 at 12:13
5

An alternative easy solution that works with Python 3 now:

First import the following package:

pip install python-whois

Then execute the code:

import whois
w = whois.whois('74.125.225.229')
Rene B.
  • 6,557
  • 7
  • 46
  • 72