As seen on Category5 Technology TV Episode 426 - www.category5.tv

We're checking 173.194.123.63...

See how accurate the Geocode by IP address is—roughly 3.4 miles from the actual location: https://www.google.ca/maps/place/H+Ln%2C+Mountain+View%2C+CA+94043%2C+USA/@37.4192,-122.0574,14z
Note the link: we have converted the IP address to both a physical address and geocoordinates.

Don't believe us? Click this link to see where we think your node is located (based on your IP address): https://www.google.ca/maps/place/44161+Paget+Terrace%2C+Ashburn%2C+VA+20147%2C+USA/@39.0481,-77.4729,14z
Pretty close?


Now, let's pretend we actually know the physical address. This would be the case for say, a real estate listing (obviously we'd have the physical address, not an IP address).

Look how accurate the Geocode by Physical Address is (perfect match): https://www.google.com/maps/preview/@37.4224082,-122.0856086,20z
Note the link: we're not sending Google Maps the address—we have converted it with perfect precision to geocoordinates.


Code for this page:
<?php
  /*
    Geocode from Category5 Technology TV Episode 426
    By Robbie Ferguson, 2015
    Do you like this tutorial? Please become a Patron! https://patreon.com/Category5

    Geocode by IP: Can change xml to json or csv
      freegeoip.net/xml/173.194.123.63
      
    Geocode by Address: Can change xml? to json?, can optionally add &key=YOUR_API_KEY
      https://maps.googleapis.com/maps/api/geocode/xml?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA
      
    Reverse Geocode: convert from geocoords to address (approximate) Can change xml? to json?, can optionally add &key=YOUR_API_KEY
      https://maps.googleapis.com/maps/api/geocode/xml?latlng=37.4192,-122.0574

    Run your own Geocode by IP Address server for free:
      Download:
        http://freegeoip.net/
        
      Help:
        ./freegeoip -h
        
      Run daemon (Linux):
        ./freegeoip -http :8888 -public /var/www/

  */

  $server = 'http://freegeoip.net'; // free public server, 10,000 requests per hour limit
  //$server = 'http://localhost:8888'; // our own private server, unlimited requests and faster
  $ip = '173.194.123.63'; // IP Address to geocode, we're using Google for our demo

  echo 'As seen on Category5 Technology TV Episode 426 - <a href="http://www.category5.tv" target="_blank">www.category5.tv</a><br /><br />';
  echo 'We\'re checking ' . $ip . '...<br /><br />';
  
  // We're going to do an XML version, but freegeoip also supports CSV or JSON
  $freegeoip = @simplexml_load_file($server . '/xml/' . $ip);
  /*
    Provides the following $freegeoip object:
      SimpleXMLElement Object
      (
          [IP] => 173.194.123.63
          [CountryCode] => US
          [CountryName] => United States
          [RegionCode] => CA
          [RegionName] => California
          [City] => Mountain View
          [ZipCode] => 94043
          [TimeZone] => America/Los_Angeles
          [Latitude] => 37.4192
          [Longitude] => -122.0574
          [MetroCode] => 807
      )
  */

  // Reverse Geocode based on the Latitude/Longitude we found
  $reversegeo = @simplexml_load_file('https://maps.googleapis.com/maps/api/geocode/xml?latlng=' . $freegeoip->Latitude . ',' . $freegeoip->Longitude);
  /*
    Provides this big long response. The main thing we are interested in is $reversegeo->result[0]->formatted_address
      SimpleXMLElement Object
      (
          [status] => OK
          [result] => Array
              (
                  [0] => SimpleXMLElement Object
                      (
                          [type] => route
                          [formatted_address] => Walcott Ave, Mountain View, CA 94043, USA
                          [address_component] => Array
                              (
                                  [0] => SimpleXMLElement Object
                                      (
                                          [long_name] => Walcott Avenue
                                          [short_name] => Walcott Ave
                                          [type] => route
                                      )

                                  [1] => SimpleXMLElement Object
                                      (
                                          [long_name] => Mountain View
                                          [short_name] => Mountain View
                                          [type] => Array
                                              (
                                                  [0] => locality
                                                  [1] => political
                                              )

                                      )

                                  [2] => SimpleXMLElement Object
                                      (
                                          [long_name] => Santa Clara County
                                          [short_name] => Santa Clara County
                                          [type] => Array
                                              (
                                                  [0] => administrative_area_level_2
                                                  [1] => political
                                              )

                                      )

                                  [3] => SimpleXMLElement Object
                                      (
                                          [long_name] => California
                                          [short_name] => CA
                                          [type] => Array
                                              (
                                                  [0] => administrative_area_level_1
                                                  [1] => political
                                              )

                                      )

                                  [4] => SimpleXMLElement Object
                                      (
                                          [long_name] => United States
                                          [short_name] => US
                                          [type] => Array
                                              (
                                                  [0] => country
                                                  [1] => political
                                              )

                                      )

                                  [5] => SimpleXMLElement Object
                                      (
                                          [long_name] => 94043
                                          [short_name] => 94043
                                          [type] => postal_code
                                      )

                              )

                          [geometry] => SimpleXMLElement Object
                              (
                                  [location] => SimpleXMLElement Object
                                      (
                                          [lat] => 37.4191395
                                          [lng] => -122.0585256
                                      )

                                  [location_type] => GEOMETRIC_CENTER
                                  [viewport] => SimpleXMLElement Object
                                      (
                                          [southwest] => SimpleXMLElement Object
                                              (
                                                  [lat] => 37.4177885
                                                  [lng] => -122.0598809
                                              )

                                          [northeast] => SimpleXMLElement Object
                                              (
                                                  [lat] => 37.4204865
                                                  [lng] => -122.0571829
                                              )

                                      )

                                  [bounds] => SimpleXMLElement Object
                                      (
                                          [southwest] => SimpleXMLElement Object
                                              (
                                                  [lat] => 37.4186591
                                                  [lng] => -122.0587873
                                              )

                                          [northeast] => SimpleXMLElement Object
                                              (
                                                  [lat] => 37.4196159
                                                  [lng] => -122.0582765
                                              )

                                      )

                              )

                          [place_id] => ChIJseEB3GC3j4ARu6QkhmorVN8
                      )
                  ...
      
  */

  // Generate a map link to show how accurate this is
  // If you do a distance comparison to Googleplex, we can see it is pretty accurate; just 3.4 miles off
  $maplink = 'https://www.google.ca/maps/place/' . urlencode($reversegeo->result[0]->formatted_address) . '/@' . $freegeoip->Latitude . ',' . $freegeoip->Longitude . ',14z';
  echo 'See how accurate the Geocode <u>by IP address</u> is&mdash;roughly 3.4 miles from the actual location: <a href="' . $maplink . '" target="_blank">' . $maplink . '</a><br />Note the link: we have converted the IP address to both a physical address and geocoordinates.<br /><br />' . PHP_EOL;

  // Perform the same lookup but with the user's IP address
  $userip = ($_SERVER['HTTP_CF_CONNECTING_IP'] ?: $_SERVER['REMOTE_ADDR']); // We use cloudflare, so check for that first
  $freegeoip = @simplexml_load_file($server . '/xml/' . $userip);
  $reversegeo = @simplexml_load_file('https://maps.googleapis.com/maps/api/geocode/xml?latlng=' . $freegeoip->Latitude . ',' . $freegeoip->Longitude);
  $maplink = 'https://www.google.ca/maps/place/' . urlencode($reversegeo->result[0]->formatted_address) . '/@' . $freegeoip->Latitude . ',' . $freegeoip->Longitude . ',14z';
  echo 'Don\'t believe us? Click this link to see where we think <u>your</u> node is located (based on your IP address): <a href="' . $maplink . '" target="_blank">' . $maplink . '</a><br />Pretty close?<br /><br />' . PHP_EOL;


  /*
    What if you don't know the IP address (say, a real estate listing) but still want to find the longitude and latitude?
    This is where Google's Geocode by Address comes in.
    This is much also significantly more accurate than IP Address geocoding
    since IP addresses are based on the node, not the actual physical endpoint.
  */
  $address = '1600 Amphitheatre Pkwy, Mountain View, CA 94043, United States';
  $geobyaddr = @simplexml_load_file('https://maps.googleapis.com/maps/api/geocode/xml?address=' . urlencode($address));
    /*
      Check out how perfectly accurate the output is:
      SimpleXMLElement Object
      (
          [status] => OK
          [result] => SimpleXMLElement Object
              (
                  [type] => street_address
                  [formatted_address] => 1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA
                  [address_component] => Array
                      (
                          [0] => SimpleXMLElement Object
                              (
                                  [long_name] => 1600
                                  [short_name] => 1600
                                  [type] => street_number
                              )

                          [1] => SimpleXMLElement Object
                              (
                                  [long_name] => Amphitheatre Parkway
                                  [short_name] => Amphitheatre Pkwy
                                  [type] => route
                              )

                          [2] => SimpleXMLElement Object
                              (
                                  [long_name] => Mountain View
                                  [short_name] => Mountain View
                                  [type] => Array
                                      (
                                          [0] => locality
                                          [1] => political
                                      )

                              )

                          [3] => SimpleXMLElement Object
                              (
                                  [long_name] => Santa Clara County
                                  [short_name] => Santa Clara County
                                  [type] => Array
                                      (
                                          [0] => administrative_area_level_2
                                          [1] => political
                                      )

                              )

                          [4] => SimpleXMLElement Object
                              (
                                  [long_name] => California
                                  [short_name] => CA
                                  [type] => Array
                                      (
                                          [0] => administrative_area_level_1
                                          [1] => political
                                      )

                              )

                          [5] => SimpleXMLElement Object
                              (
                                  [long_name] => United States
                                  [short_name] => US
                                  [type] => Array
                                      (
                                          [0] => country
                                          [1] => political
                                      )

                              )

                          [6] => SimpleXMLElement Object
                              (
                                  [long_name] => 94043
                                  [short_name] => 94043
                                  [type] => postal_code
                              )

                      )

                  [geometry] => SimpleXMLElement Object
                      (
                          [location] => SimpleXMLElement Object
                              (
                                  [lat] => 37.4220352
                                  [lng] => -122.0841244
                              )

                          [location_type] => ROOFTOP
                          [viewport] => SimpleXMLElement Object
                              (
                                  [southwest] => SimpleXMLElement Object
                                      (
                                          [lat] => 37.4206862
                                          [lng] => -122.0854734
                                      )

                                  [northeast] => SimpleXMLElement Object
                                      (
                                          [lat] => 37.4233842
                                          [lng] => -122.0827754
                                      )

                              )

                      )

                  [place_id] => ChIJ2eUgeAK6j4ARbn5u_wAGqWA
              )

      )

    */

    // Generate a map link
    echo '<hr>Now, let\'s pretend we actually know the physical address. This would be the case for say, a real estate listing (obviously we\'d have the physical address, not an IP address).<br /><br />';
    $maplink = 'https://www.google.com/maps/preview/@' . $geobyaddr->result->geometry->location->lat . ',' . $geobyaddr->result->geometry->location->lng . ',20z';
    echo 'Look how accurate the Geocode <u>by Physical Address</u> is (perfect match): <a href="' . $maplink . '" target="_blank">' . $maplink . '</a><br />Note the link: we\'re not sending Google Maps the address&mdash;we have converted it with perfect precision to geocoordinates.<br /><br />' . PHP_EOL;

    echo '<hr>Code for this page:<pre>' . htmlentities(file_get_contents('geocode.txt')) . '</pre>';
?>