Convert KML to GeoJSON in your browser or NodeJS app

Software Engineer • TypeScript • JavaScript • Angular • VueJS • WordPress • Ex-founder of ng-enious
Search for a command to run...

Software Engineer • TypeScript • JavaScript • Angular • VueJS • WordPress • Ex-founder of ng-enious
No comments yet. Be the first to comment.
By the time I'm writing this article, you surely may have heard of ChatGPT. This "new AI" made so many waves that I couldn't resist digging through it and writing something about it. But rather than jumping into the hype train of ChatGPT and OpenAI, ...

Hello good people! In this article, we're going to create an npm package step by step. By the end of this article you will be able to: Build your own package Use it on other projects Publish it on npm [Bonus] Publish your TypeScript types with your ...

Hello good people! In this article, I want to shed light on a very interesting console function. It's called console.timer() and might help you understand how your code runs and optimize it. This will be a rather short article. We'll go through two s...

Hello good people! In this article, I want to deep dive with you into a usually overlooked file in a project. The package.json is crucial to a lot of frontend/backend NodeJS projects. Yet a lot of developers don't really know what it can really do. W...

Tarek's /dev/log
10 posts
Everyday blogs about software engineering, Frontend Web development and everything in between.
Hello good people! In this short article, we're going to convert KML files to the GeoJSON format. The main takeaway aside from discovering something new is that I'll tell you about the popular solution, and then I'll show you the new solution I had to use due to some constraints.
KML (Keyhole Markup Language) is a specific XML format used for geographic annotation and representation. You can learn more about it in this Wikipedia article. What you need to know is that KML is commonly used in a lot of applications tied with geography and GPS tracking for example.
GeoJSON (Geographic JavaScript Object Notation) is an open standard also used for geographic representations but is more simple in its approach. Learn more about it over here in this Wikipedia article.
Both formats have pros and cons, but we're not here to discuss this. We want to convert a KML file to GeoJSON. GeoJSON is easy to display on a map for example geojson.io or directly on your web app that uses Mapbox, Leaflet or others.
Let's suppose you have this KML file that represents the future metro line 15 in the Paris region in France (source). We can easily display this KML file using Google's My Maps app. Let's quickly test out the KML file in My Maps:
Open My Maps
Click the button "Create a new map" and you'll get redirected to a map interface
Once on the map, locate the left toolbox and click the "Import" button
In the new modal that will display, you can drag and drop your KML file or simply browse it
After it's uploaded, you'll see the metro line represented in red in the south of Paris
Below is a GIF of the whole process:

Now that we're sure our file is working as expected, let's try to parse it and convert it to GeoJSON. Here is a StackBlitz environment with everything already prepared, just head to the file index.ts. Let's go through the code:
import * as toGeoJson from '@mapbox/togeojson';
import './style.css';
// Handle the dropfile event
function onDrop(event: DragEvent) {
event.preventDefault();
const reader = new FileReader();
const selectedFile = event.dataTransfer.files[0];
if (selectedFile) {
reader.onload = (ev) => {
handleDroppedFileToMap(reader.result as string);
};
reader.readAsText(selectedFile, 'text/xml');
}
}
// Suppress the default browser behavior when dragging a file in the dropzone
function dragOverHandler(ev) {
ev.preventDefault();
}
// Convert the dragged kml file
function handleDroppedFileToMap(fileResult: string) {
const geojsonFile = toGeoJson.kml(
new DOMParser().parseFromString(fileResult, 'text/xml')
);
console.log(geojsonFile);
// Display our dragged file in a fancy way
const appDiv: HTMLElement = document.getElementById('app');
appDiv.innerHTML = `<pre><code class="geojson">${JSON.stringify(
geojsonFile,
null,
4
)}</code></pre>`;
}
// Get our dropzone
const dropzone = document.querySelector('.dropzone');
// Bind the necessary event listeners to our dropzone
dropzone.addEventListener('drop', onDrop);
dropzone.addEventListener('dragover', dragOverHandler);
First, we're importing @mapbox/togeojson as a dependency. We can install it simply with npm install @mapbox/togeojson in our project.
Next, we're defining our onDrop(event: DragEvent) function. It will handle when the user drops a file. The function initializes a FileReader and gets the selected file from the drag event. Note we're assuming that the user is dropping a single file. We then prepare our FileReader instance to call a function named handleDroppedFileToMap() once the file is loaded. And we finally start reading the file as text with reader.readAsText(selectedFile, 'text/xml'); .
Next dragOverHandler, as you can see by the comment I left, this function will just suppress the browser's default behaviour where it will attempt to open your file in a new tab.
Now let's examine handleDroppedFileToMap(fileResult: string), this function takes our file in the form of a string and then passes it to this funky line of code:
const geojsonFile = toGeoJson.kml(
new DOMParser().parseFromString(fileResult, 'text/xml')
);
We're doing 3 things here:
First, we create a new DOMParser instance that will be used and then disposed of. DOMParser will help us parse our string to an XML file via the browser, this way we avoid validating and doing a lot of heavy lifting. As you can see parseFromString() takes our file in the form of a string as well as 'text/xml' which will help tell it we're trying to parse an XML file (our KML is just an XML file remember?).
Then, we pass all what we did with the DOMParser to the toGeoJson.kml() function which will convert our KML to a GeoJSON object.
Finally, we store our result in the constant geojsonFile, easy!
The final two instructions of our function are to log our GeoJSON file to view it in the console and insert it in our HTML document using a simpler innerHTML.
Finally, the last 3 lines of code are in order:
Get the HTML element of the dropzone using document.querySelector()
Bind the drop event listener to the function onDrop()
Bind the dragover event listener to the function dragOverHandler()
That's all we need! Now here is a GIF of what happens when I drop the file in the dropzone.

Now it's all good, there is only one small problem; you should not use @mapbox/togeojson ! Let me explain.
@mapbox/togeojson 🛑Let's be clear, I'm a huge fan of Mapbox as a map solution and map provider. My issue is that the @mapbox/togeojson package has not been maintained since January 2018! Since we're using this library in our client's app and their security department takes things too seriously, we need to keep all our packages updated. togeojson in this case uses minimist@1.2.0 which suffers from a security exploit. And believe me, nothing is scarier for the cybersecurity department of a big corporate than an npm security vulnerability 😅 .
Anyway, we need an alternative. And thanks to the amazing Github community, we have a great alternative called @tmcw/togeojson. Honestly, I'm surprised that I didn't know about it sooner. It features:
No dependency!
Extremely tiny at 299KB
Tested
Works on NodeJS and the browser
Has built-in TypeScript typings!
Now, let's quickly change our code to use this package, head back to index.ts and do the following:
// Replace this at line 1
import * as toGeoJson from '@mapbox/togeojson';
// With this
import { kml } from "@tmcw/togeojson";
// Replace line 24
const geojsonFile = toGeoJson.kml(
new DOMParser().parseFromString(fileResult, 'text/xml')
);
// With this
const geojsonFile = kml(new DOMParser().parseFromString(fileResult, 'text/xml'));
And that's it! We've replaced two lines and our code still works as expected. You can check out the commit diff here. And the final solution at Stackblitz is here.
In this article, we've discovered KML, GeoJSON and their purpose. We've tried to parse and convert a KML file to GeoJSON using @mapbox/togeojson. Then we discovered an alternative library that's more up-to-date and well-maintained called @tmcw/togeojson.
I hope I helped you learn something new and of course, don't hesitate to chime in the comments. I would be delighted to read you too!
Cheers!
Banner photo from Pixabay.