CSV to KML Converter

A CSV to KML converter turns a spreadsheet of coordinates into placemarks that Google Earth, Google My Maps, QGIS and ArcGIS can open. This one writes the lon,lat tuples KML requires, groups your pins into folders from any column you choose, and keeps every other field as ExtendedData so clicking a pin shows the whole row. The file stays on your machine.

Need to filter or clean the rows first? Open the app

The comma with no space after it

KML's coordinate syntax is unforgiving in a specific way. A tuple is longitude,latitude,altitude, comma separated, with no spaces inside the tuple. Separate tuples are separated by whitespace. So a line is -0.0877,51.5079 -0.0962,51.5071, and the spaces and the commas mean opposite things.

Two errors follow from this and both produce a file that opens without complaint. Putting a space after the comma splits one coordinate into two malformed ones, and Earth quietly draws nothing. Putting the latitude first plots your point somewhere else on the planet, and Earth quietly draws it there. Neither is an error message. You find out by looking.

This converter reads your headings, works out which column is which, and writes the tuple correctly. If your columns are named latitude and longitude, or lat and lng, it needs nothing from you. If they are named something else, the dropdowns list the columns of the file you just loaded and show which one was picked, so what is on screen always matches what is about to be written.

A worked example

Three stores, with a region column to fold them by:

name,region,latitude,longitude,staff,code
London Bridge,Europe,51.5079,-0.0877,14,01730
Paris Chatelet,Europe,48.8583,2.3470,22,00412
Manhattan Midtown,North America,40.7549,-73.9840,31,00907

Pick region as the folder column and you get a document whose sidebar has two folders, each holding its placemarks:

<Folder>
  <name>Europe</name>
  <Placemark>
    <name>London Bridge</name>
    <styleUrl>#emd-pin</styleUrl>
    <ExtendedData>
      <Data name="region"><value>Europe</value></Data>
      <Data name="staff"><value>14</value></Data>
      <Data name="code"><value>01730</value></Data>
    </ExtendedData>
    <Point><coordinates>-0.0877,51.5079</coordinates></Point>
  </Placemark>
  ...

Three things are worth noticing. The coordinates are longitude first, reversed from the CSV. The store code keeps its leading zero, because it is written as text and not as a number. And every non-coordinate column is a named Data element, which is what makes Earth's balloon show staff: 14 rather than a wall of unlabelled values.

ExtendedData is the part that matters later

The quick way to get a row's data into a placemark is to concatenate it into the <description>, usually as an HTML table. It renders, so it looks like it worked. What it costs you shows up a week later.

A description is a blob of markup. Google Earth cannot filter on it, My Maps cannot use it to style your pins by category, and converting the file back to a table hands you one column of HTML instead of the eight columns you started with. Our own KML to CSV converter has to run a rescue routine to unpick exactly this, because Google My Maps writes its exports that way.

<ExtendedData> with one <Data name="..."> per column is the structured form. Earth renders it as a labelled table in the balloon by default, My Maps reads it as the layer's columns and offers each one for styling and filtering, and a round trip back to CSV returns exactly the columns you started with. The description element is left for the column you actually want as prose, which you choose separately.

Folders, and why a flat list stops working

Twenty pins are fine as a flat list. Four hundred are not. Google Earth's sidebar becomes a scroll with no structure, and there is no way to hide a group to see what is underneath it.

Pick a column and every distinct value becomes a <Folder> with its own checkbox. Region, category, status, owner, quarter: anything with a manageable number of distinct values works. Turning off three of five regions to look at the other two is the single thing that makes a large KML usable, and it costs one dropdown here.

If your grouping column has hundreds of distinct values, folders will not help, and the answer is usually to filter the CSV down first. The app will do that in the browser before you come back here.

Switching the geometry to paths changes the grouping's meaning: instead of a folder per value you get one <LineString> per value, drawn through that group's rows in file order. That is how a table of GPS pings with a trip column becomes a set of routes. A group with only one point cannot be a line, and that is reported rather than written as a degenerate shape.

Escaping, and the rows that cannot be plotted

KML is XML, so five characters cannot appear literally in a value. A store called Fenwick & Sons and a note containing <br> both break the document if written straight through, and a broken KML does not open at all: Earth shows a parse error and stops. Every name, description and data value here is escaped, so the output is well formed whatever is in your cells.

Rows without a usable coordinate are left out and reported. The warning gives the count against the total and lists the first ten by their line number in the source file, with the value that failed:

3 of 128 rows had no usable coordinate and were left out:
row 19: coordinate cell is blank;
row 44: "N/A", "2.35" is not a number;
row 91: longitude 512000 is outside -180 to 180.

That last one is the most useful line in the tool. A longitude of 512000 is a projected coordinate in metres, which means the whole file needs reprojecting to WGS 84 before any of it can become KML. Being told immediately beats opening an empty map in Google Earth and working backwards.

Questions

Why is the coordinate order in KML longitude first?

Because OGC KML defines a coordinate tuple as longitude,latitude,altitude, comma separated with no spaces. It is the reverse of how a spreadsheet lists them and the reverse of how anyone says them out loud. Google Earth opens a file with the pair swapped without complaining, which is what makes the mistake so easy to ship. The order is applied for you here from your column names.

Will my other columns show up when I click a pin?

Yes. Every column that is not a coordinate is written as an ExtendedData Data element with its heading as the name, so Google Earth's balloon shows the whole row as labelled fields. The shortcut most converters take, pasting the row into the description as loose HTML, loses the field names and cannot be queried or styled.

Can I organise the pins into folders?

Pick a column and every distinct value in it becomes a Folder. A region, a category or a status column turns Google Earth's sidebar into something you can navigate and switch on and off a group at a time. Without it, 400 pins are one flat list, which is the difference between a usable map and a scroll.

Can it draw lines rather than pins?

Yes. Switch the geometry to paths and pick a grouping column, and each distinct value becomes one LineString built from its rows in file order. A delivery run with a driver column, or a GPS trace with a trip identifier, becomes one path per driver or trip rather than a cloud of dots.

What happens to rows with a bad coordinate?

They are left out, counted, and listed. The warning names the first ten by their line number in the original file with the value that failed, so you can go and fix the CSV. Blank cells, text where a number should be, and out-of-range values are all caught separately, because each one means something different about what went wrong upstream.

Will this open in Google My Maps as well as Google Earth?

Yes. My Maps imports KML directly and reads ExtendedData as the layer's columns, so the fields you see in Earth's balloon are the fields My Maps offers for styling and filtering. My Maps has its own import limits, currently around 2,000 features and 5 MB per layer, so a very large file needs splitting into layers.

What is a .kmz, and can I make one?

A .kmz is a zip archive containing a .kml plus any icons or images it references. This converter writes plain .kml, which Google Earth, My Maps, QGIS and ArcGIS all open directly. If you need a .kmz, zip the .kml file and rename the archive; nothing else is required for a document with no custom icon files.

Convert your CSV to KML

No sign-up, no upload, no row cap. Foldered placemarks, every field as ExtendedData, coordinate order handled.

Back to the converter