geojsonkit.org
GeoJSON utilities, in the browser
Say hi →

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

updated 8 June 2026

Drop a .geojson file, or

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 null or 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. Set properties.name on 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 a properties.coordTimes array (the togeojson convention) as <time> per point; waypoints use a single properties.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 a key: value line 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.