Discovering public IP programmatically Discovering public IP programmatically python python

Discovering public IP programmatically


This may be the easiest way. Parse the output of the following commands:

  1. run a traceroute to find a router that is less than 3 hops out from your machine.
  2. run ping with the option to record the source route and parse the output. The first IP address in the recorded route is your public one.

For example, I am on a Windows machine, but the same idea should work from unix too.

> tracert -d www.yahoo.comTracing route to www-real.wa1.b.yahoo.com [69.147.76.15]over a maximum of 30 hops:  1    <1 ms    <1 ms    <1 ms  192.168.14.203  2     *        *        *     Request timed out.  3     8 ms     8 ms     9 ms  68.85.228.121  4     8 ms     8 ms     9 ms  68.86.165.234  5    10 ms     9 ms     9 ms  68.86.165.237  6    11 ms    10 ms    10 ms  68.86.165.242

The 68.85.228.121 is a Comcast (my provider) router. We can ping that:

> ping -r 9 68.85.228.121 -n 1Pinging 68.85.228.121 with 32 bytes of data:Reply from 68.85.228.121: bytes=32 time=10ms TTL=253    Route: 66.176.38.51 ->           68.85.228.121 ->           68.85.228.121 ->           192.168.14.203

Voila! The 66.176.38.51 is my public IP.

Python code to do this (hopefully works for py2 or py3):

#!/usr/bin/env pythondef natIpAddr():  # Find next visible host out from us to the internet  hostList = []  resp, rc = execute("tracert -w 100 -h 3 -d 8.8.8.8") # Remove '-w 100 -h d' if this fails  for ln in resp.split('\n'):    if len(ln)>0 and ln[-1]=='\r': ln = ln[:-1]  # Remove trailing CR    if len(ln)==0: continue    tok = ln.strip().split(' ')[-1].split('.') # Does last token look like a dotted IP address?    if len(tok)!=4: continue    hostList.append('.'.join(tok))    if len(hostList)>1: break  # If we found a second host, bail      if len(hostList)<2:    print("!!tracert didn't work, try removing '-w 100 -h 3' options")    # Those options were to speed up tracert results  else:    resp, rc = execute("ping -r 9 "+hostList[1]+" -n 1")    ii = resp.find("Route: ")    if ii>0: return resp[ii+7:].split(' ')[0]  return none     def execute(cmd, showErr=True, returnStr=True):  import subprocess  if type(cmd)==str:    cmd = cmd.split(' ')  # Remove ' ' tokens caused by multiple spaces in str               cmd = [xx for xx in cmd if xx!='']  proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)  out, err = proc.communicate()  if type(out)==bytes:  # Needed for python 3 (stupid python)    out = out.decode()    try:      err = err.decode()    except Exception as ex:       err = "!!--"+str(type(ex))+"--!!"    if showErr and len(err)>0:    out += err  if returnStr and str(type(out))=="<type 'unicode'>":    # Trying to make 'out' be an ASCII string whether in py2 or py3, sigh.    out = out.encode()  # Convert UNICODE (u'xxx') to string  return out, proc.returncodeif __name__ == "__main__":  print("(This could take 30 sec)")  print(natIpAddr())

Use it from the command line (on Windows) or from a python program:

import natIpAddrmyip = natIpAddr.natIpAddr()print(myip)


I have made a program that connects to http://automation.whatismyip.com/n09230945.aspit is is written in D an getting someone else to tell you what they see your ip as is probably the most reliable way:

/*    Get my IP address*/import tango.net.http.HttpGet;import tango.io.Stdout;void main(){      try      {          auto page = new HttpGet ("http://automation.whatismyip.com/n09230945.asp");          Stdout(cast(char[])page.read);      }      catch(Exception ex)      {          Stdout("An exception occurred");      }}

Edit python code should be like:

from urllib import urlopenprint urlopen('http://automation.whatismyip.com/n09230945.asp').read()


I like the ipify.org:

  • it's free to use (even programmatically and allows even heavy traffic)
  • the response contains only the IP address without any garbage (no need for parsing)
  • you can also request a response in JSON
  • works for both IPv4 and IPv6
  • it's hosted in a cloud
  • it's open-source
$ curl api.ipify.org167.220.196.42$ curl "api.ipify.org?format=json"{"ip":"167.220.196.42"}