GeoJSON to GPX
Paste GeoJSON, get a GPX 1.1 file ready for Garmin, Strava, Komoot, AllTrails, and Locus Map. Points become <wpt>, lines become <trk> with one <trkseg> per segment. Everything runs in your browser.
GeoJSON to GPX
What this tool does
It turns GeoJSON into a GPX 1.1 file — the XML format GPS devices and services read. Paste a FeatureCollection, a single Feature, or a bare geometry, click Convert, and download a .gpx you can drop into Garmin, Strava, Komoot, AllTrails, or Locus Map.
The intent it closes: "I have track or point data as GeoJSON and my GPS app only takes GPX." GPX has a fixed, narrow schema, so the conversion is one-directional and a little lossy by nature — this tool is honest about exactly what survives the trip. Going the other way? Use GPX to GeoJSON.
How this tool works
One click runs the conversion, entirely in your browser. There's nothing to configure — the output is fixed GPX 1.1, and the file's creator attribute is hardcoded to geojsonkit.org.
1. Parse
Your text goes through the browser's JSON parser. If it isn't valid JSON — a trailing comma, an unclosed bracket, a smart quote — the status bar shows JSON parse error. and nothing is written to the output pane. A clean parse is the only entry requirement.
2. Walk the geometries
I flatten your input to a list of features, then map each geometry to its GPX equivalent. The coordinate flip is handled automatically: GeoJSON is [lon, lat, ele], but GPX uses lat="…" lon="…" attributes.
Point/MultiPoint→ one waypoint (<wpt>) each.LineString→ one track (<trk>) with a single<trkseg>.MultiLineString→ one track with one<trkseg>per line, preserving the gaps between segments.Polygon→ a track built from the outer ring only — interior rings (holes) are dropped. This is lossy; GPX has no polygon type.MultiPolygon→ each polygon's outer ring as a separate segment in one track (holes again dropped).GeometryCollection→ expanded recursively, so each child geometry is converted on its own.- A
nullor unsupported geometry is skipped and counted as dropped.
3. Carry what fits
GPX's vocabulary is small, so only some properties survive. For waypoints I read name, desc (or description), and time; for tracks I read name, desc/description, and a coordTimes array (one ISO-8601 string per vertex) that becomes a <time> on each <trkpt>. A finite third coordinate becomes <ele>. Every other property is serialized into <desc> as key: value lines, so nothing silently vanishes — it's at least visible inside a Garmin or Strava popup.
4. Report and download
The status bar reports the tally — Converted to GPX 1.1. N waypoint(s) · N track(s) · N dropped. — and Download .gpx saves the result as converted.gpx. Everything runs locally; your data never leaves the tab.
Example
Input (GeoJSON Feature with elevation):
{
"type": "Feature",
"properties": { "name": "Summit" },
"geometry": { "type": "Point", "coordinates": [-122.0, 37.5, 1430] }
}
Output (GPX 1.1, the <wpt> element):
<wpt lat="37.5" lon="-122"><ele>1430</ele><name>Summit</name></wpt>
Notice the flip — [-122.0, 37.5, 1430] becomes lat="37.5" lon="-122", and the third coordinate lands in <ele>.
Tips & common pitfalls
- Naming matters. Garmin Connect and most consumer apps display the
<name>tag prominently. Setproperties.nameon each feature so your tracks aren't a wall of "Untitled". - Elevation needs a third coordinate. If your points are
[lon, lat]only, the<ele>tag is omitted and some devices show altitude as zero. Enrich from a DEM first if you need it. - Timestamps come from
coordTimes. Tracks pick up aproperties.coordTimesarray (thetogeojsonconvention) as<time>per point; waypoints use a singleproperties.time. - Polygons are flattened. Only the outer ring becomes a track; interior holes are dropped. Fine for a park boundary, wrong for hydrology with islands.
- Extra properties land in
<desc>. Anything outside the GPX vocabulary becomes akey: valueline there. Most apps render it on tap; some show only the first line.
Troubleshooting
The status says "No features" / output is just an empty <gpx> element.
Your GeoJSON parsed cleanly but held no convertible geometries — likely all null geometries or unsupported types. Run the Validator first to confirm the structure.
I get a "JSON parse error." message.
The input isn't valid JSON. Check for missing quotes around keys, unclosed brackets, smart quotes, or trailing commas before Convert.
Garmin Connect won't import the file.
Garmin sometimes rejects GPX with no <trk> at all (only waypoints) for activity import. Either upload it as a "course" or convert your points to a single LineString first.
The track shows but the elevation profile is flat.
Your input had only 2D coordinates, so no <ele> tags were written. Add a third value to each coordinate, or enrich with a DEM before converting.
FAQ
What GPX version does this output?
GPX 1.1 with the standard Topografix namespace — the version every modern device and service expects. The creator attribute is fixed to geojsonkit.org.
Are extensions (heart rate, cadence, power) supported?
Not as dedicated tags. GPX extensions live in vendor-specific namespaces with a huge surface area. If your GeoJSON has those properties they appear in the <desc> dump, not in extension elements.
How are MultiLineStrings handled?
One <trk> per feature, one <trkseg> per line in the multi. That preserves the gaps between segments — useful where the recording paused.
Will the output validate against the GPX 1.1 XSD?
For point and line conversions, yes. Polygon → track conversion produces valid GPX but may be semantically odd (a closed loop track). Run xmllint --schema if you need certainty.
Is my data uploaded?
Never. All conversion runs as plain JavaScript in your browser. You can disconnect your network and refresh — the page still works.