# Geocoding Addresses for Use in KML

*Mano Marks, Google Geo Team
Authored: December 2007
Updated: December 2013*

## Objective

This tutorial is intended for developers who are familiar with
scripting languages and want to learn how to use the [Google
Geocoding API](https://developers.google.com/maps/documentation/geocoding) to geocode addresses and incorporate them into a KML file. While the code samples
are presented in Python, they can be adapted fairly easily to most other programming languages.


*Geocoding* is the process of converting an address into a set of latitude/longitude
coordinates, making it possible to indicate addresses on a map. You may want to geocode addresses
and put them directly into a KML file. This is common, for example, when data is being entered into
a form and you are generating KML files in response to requests. These KML files could be
stored in a database, in a file system or returned to a NetworkLink that connects to your file.
Note that when using this technique, you must observe the [Terms of Service](https://developers.google.com/maps/terms)
for the Geocoding API as there are some limitations on the time the results can be stored for, as
well as the number of elements that you can geocode each day.

This tutorial shows you how to use Python to take the string
"`1600 Amphitheatre Pkwy, Mountain View, CA 94043`" and turn it into this:

```
<?xml version='1.0' encoding='UTF-8'?> 
<kml xmlns='http://earth.google.com/kml/2.2'>
  <Document>
    <Placemark>
      <description>1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA</description>
      <Point>
        <coordinates>-122.081783,37.423111,0</coordinates>
      </Point>
    </Placemark>
  </Document>
</kml>
```

## Create a KML Document

KML is an XML markup language, so we can use Python's built in
[xml.dom.minidom](http://docs.python.org/lib/module-xml.dom.minidom.html)
functions to create a KML document. Python's minidom is a [DOM](http://www.w3.org/DOM/)
implementation, and DOM is supported in most programming languages, so this process should be easy
to port into another programming language. Here are the steps:

1. Create the document using Python's `xml.dom.minidom.Document()`.
2. Create the root `<kml>` element using `createElementNS.`
3. Append it to the document using `appendChild`.
4. Create a Document element using `createElement`.
5. Append it to the `<kml>` element using `appendChild`.
6. For each address, create a `<Placemark>` element using `createElement`, and append it to the `Document` element. Then, create a `<description>` element, assign it the value of the address, and append it to the `<Placemark>` element.
7. Create a `<Point>` element, add a child `<coordinates>` element, and append it to the `<Placemark>` element.
8. Send the address to the Maps API Geocoder, which sends a response in either JSON or XML. Use `urllib.urlopen()` to retrieve the file and read it into a string.
9. Parse the response and extract the longitude and latitude elements.
10. Create a text node in the `<coordinates>` element and assign the longitude/latitude string as its value.
11. Write the KML document to a text file.

## Sample Python Code


Note that the sample code below uses a dummy mapsKey variable---you'll need to replace this key with your
[own key](https://code.google.com/apis/console/?noredirect).

Sample code for geocoding with Python 2.7 and JSON output is shown below:

```python
import urllib
import xml.dom.minidom
import json 

def geocode(address, sensor=False):
 # This function queries the Google Maps API geocoder with an
 # address. It gets back a csv file, which it then parses and
 # returns a string with the longitude and latitude of the address.

 # This isn't an actual maps key, you'll have to get one yourself.
 # Sign up for one here: https://code.google.com/apis/console/
  mapsKey = 'abcdefgh'
  mapsUrl = 'https://maps.googleapis.com/maps/api/geocode/json?address='
     
 # This joins the parts of the URL together into one string.
  url = ''.join([mapsUrl,urllib.quote(address),'&sensor=',str(sensor).lower()])
#'&key=',mapsKey])
  jsonOutput = str(urllib.urlopen(url).read ()) # get the response 
  # fix the output so that the json.loads function will handle it correctly
  jsonOutput=jsonOutput.replace ("\\n", "")
  result = json.loads(jsonOutput) # converts jsonOutput into a dictionary 
  # check status is ok i.e. we have results (don't want to get exceptions)
  if result['status'] != "OK": 
    return ""
  coordinates=result['results'][0]['geometry']['location'] # extract the geometry 
  return str(coordinates['lat'])+','+str(coordinates['lng'])

def createKML(address, fileName):
 # This function creates an XML document and adds the necessary
 # KML elements.

  kmlDoc = xml.dom.minidom.Document()
  
  kmlElement = kmlDoc.createElementNS('http://earth.google.com/kml/2.2','kml')

  kmlElement = kmlDoc.appendChild(kmlElement)

  documentElement = kmlDoc.createElement('Document')
  documentElement = kmlElement.appendChild(documentElement)

  placemarkElement = kmlDoc.createElement('Placemark')
  
  descriptionElement = kmlDoc.createElement('description')
  descriptionText = kmlDoc.createTextNode(address)
  descriptionElement.appendChild(descriptionText)
  placemarkElement.appendChild(descriptionElement)
  pointElement = kmlDoc.createElement('Point')
  placemarkElement.appendChild(pointElement)
  coorElement = kmlDoc.createElement('coordinates')

  # This geocodes the address and adds it to a  element.
  coordinates = geocode(address)
  coorElement.appendChild(kmlDoc.createTextNode(coordinates))
  pointElement.appendChild(coorElement)

  documentElement.appendChild(placemarkElement)

  # This writes the KML Document to a file.
  kmlFile = open(fileName, 'w')
  kmlFile.write(kmlDoc.toprettyxml(' '))  
  kmlFile.close()

if __name__ == '__main__':
  createKML('1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA', 'google.kml')
```

## Other Things to Consider

### Timing the Geocode Requests


Geocoding requests will be subject to the geocoder's maximum query rate daily limits. Please refer
to the [Google Geocoding API](https://developers.google.com/maps/documentation/geocoding) documentation for more
information about these limits. To ensure you don't send queries too rapidly to the geocoder, you
can specify a delay between each geocode request. You can increase this delay each time you receive
an `OVER_QUERY_LIMIT` status, and use a `while` loop to ensure you've
successfully geocoded an address before iterating to the next one.

### Changing the Base Country


The geocoder is programmed to bias its results depending on the originating domain.
For example, entering "syracuse" in the search box on maps.google.com will geocode the city of
"Syracuse, NY", while entering the same query on *maps.google.it* (Italy's domain) will
find the city of "Siracusa" in Sicily. You would get the same results by sending that query
through HTTP geocoding to *maps.google.it* instead of *maps.google.com* ,
which you can do by modifying the `mapsUrl` variable in the sample code above.
Refer to the Geocoding API documentation for more information on
[Region Biasing](https://developers.google.com/maps/documentation/geocoding#RegionCodes).

**Note:** You cannot send a request to a nonexistent
maps.google.\* server, so ensure that a country domain exists before redirecting your geocoding
queries to it. For geocode support by country, check out
[this
post](http://googlemapsapi.blogspot.com/2007/11/is-google-maps-in-your-neck-of-woods.html).

## Conclusion

Using the code above, you can now geocode an address using Python, create a KML
`<Placemark>` out of it, and save it to disk. If you find that you need to
geocode more addresses per day than the limits allow, or that the Google geocoder doesn't cover the
regions you're interested in, then consider using additional geocoding web services.

Now that you know how to geocode your addresses, check out the articles on
[Using KML in Google Mashup Editor](https://developers.google.com/kml/articles/kmlgme) and
[Using PHP and MySQL to create KML](https://developers.google.com/kml/articles/phpmysqlkml).
If you have any problems with or questions about this tutorial, please post in the [Stack Overflow](https://developers.google.com/maps/support)
forum.