Convert KML to TCX

Converting KML to TCX wraps a Google Earth line in the activity and lap structure Garmin's training format requires. It works, and for most people it is the wrong conversion: a drawn KML carries no timestamps, so the resulting TCX declares a start of 1 January 1970 and a duration of zero. This page explains when that matters and what to do instead.

  • Where it runs In your browser. The file is never uploaded.
  • Rebuilt TCX works differently from a KML, so this is not the gradual degradation a lossy codec applies. What TCX can express is reproduced faithfully; what it has no equivalent for does not survive at all.
  • File size limit Up to 100 MB per file, free, without an account.
  • Worth knowing Positions, elevation and timestamps are carried across. Sensor streams, styling and embedded imagery are not.

Up to 100 files at once. Mixed formats are fine.

Read this before converting: the one-line test

Open the KML in a text editor and search for the string `when`. If it is there, the file holds a gx:Track with real timestamps and this conversion will produce a sensible activity. If it is not — and for anything drawn by hand it will not be — the file is a shape with no clock, and the TCX built from it will be a workout that claims to have happened at midnight on 1 January 1970 and to have taken no time at all.

That is not a bug to be worked around; it is what the source contains. TCX is a record of a training session, and a session is defined by when it started and how long it lasted before it is defined by where it went. A line drawn on a map has neither property, and no converter can supply them without making them up. If your KML fails the test, the honest destination is a route format, and the last section of this page says which.

What the epoch fallback actually writes

The TCX schema requires a `StartTime` attribute on every `<Lap>` and an `<Id>` on every `<Activity>`, and both are timestamps. With no times in the source there is nothing to read, so the Unix epoch — `1970-01-01T00:00:00.000Z` — is written into both, and `TotalTimeSeconds` is written as zero because the difference between the first and last point times cannot be computed.

The file that results is schema-valid, which is why it uploads rather than being rejected. What it does downstream is less tidy. A platform sorting activities by date puts it fifty-odd years before everything else, a training-load calculation over a zero-second session either divides by zero or discards it, and any pace derived from distance over duration is undefined. None of that is a malfunction — it is the arithmetic of a file that says it took no time.

The case where the conversion is exactly right

A gx:Track is Google's extension for recorded data: parallel lists of `<when>` timestamps and `<coord>` positions, written by tools that export GPS traces as KML rather than as GPX. It is read as its own case, and the timestamps are carried through into the `<Time>` element of every TCX trackpoint.

When that is what you have, everything downstream works properly. The lap start comes from the first point, the duration is the real elapsed time, and the activity lands in the right place in a training log. This is a genuinely useful path for anyone whose recording software exports KML and whose coach wants Garmin files, and it is the reason this conversion exists at all rather than being refused.

Distance is measured along the line you drew, not the route you would ride

A TCX lap must declare a `DistanceMeters`, and a KML stores none, so the figure is computed by summing the great-circle distance between consecutive vertices on a sphere of radius 6,371,000 metres. Against an ellipsoidal calculation that is accurate to a few parts in a thousand, which is not the source of error worth worrying about here.

The error worth worrying about is the shape of the input. A hand-drawn line has a vertex where you clicked, so every curve has been replaced by the straight chord across it. A road with fifteen switchbacks traced in six clicks is measurably shorter than the road, and the activity will claim that shorter number as fact. A route snapped to the path network by a proper planner does not have this problem, which is another reason planners are the better source for anything you intend to measure.

The fields that get neutral values because KML has no opinion

Three declarations are written with fixed values because nothing in a KML corresponds to them. The activity `Sport` is `Other`, since the schema allows only a short enumeration and a drawn line says nothing about the discipline. `<Intensity>` is `Active` and `<TriggerMethod>` is `Manual`, which are the honest readings for a lap that no device ever started or stopped.

All three are worth correcting after import if the activity is going to stay. Most platforms let you change the type after the fact, and the change matters more than it looks — training-load models, pace zones and personal-best detection are all keyed to the discipline, so a session filed as `Other` is quietly left out of most of them. The intensity and trigger values are cosmetic by comparison and can be left alone.

What happens to the pins in the file

A workout has no waypoint concept, so where the KML contains lines the point placemarks are simply left out. There is no TCX element that would hold them, and inventing one would produce a file that fails validation for every reader.

A KML made entirely of pins is handled rather than refused: the points are read as one track in document order, which produces an activity claiming a route between them. Whether that means anything depends on what the pins were. A sequence of checkpoints along a course converts into something recognisable; a scatter of unrelated sites converts into an activity describing a journey nobody made, at a distance nobody travelled, dated 1970.

Elevation zeros land in the altitude field

The third value of a KML coordinate becomes `<AltitudeMeters>` on the trackpoint. Google Earth, drawing a line clamped to the terrain, writes that value as `0` on every vertex because the renderer ignores it, so a converted TCX commonly carries an altitude of zero from start to finish.

A training platform reading that file reports no ascent and a flat profile, which is the correct interpretation of the numbers it was handed. Where the KML omits the third value entirely — which My Maps exports often do — no altitude element is written at all, and most platforms will then fill in elevation from their own terrain model, producing a better answer than the zeros would have. The absence is more useful than the false value, which is an unusual thing to be able to say.

Coarse vertices make an implausible trackpoint sequence

Beyond the distance figure, the vertex count affects how the activity looks once it is in a training log. A recorded ride has a point every second; a drawn route might have one every kilometre. Charts built from the second kind are made of a handful of samples, and any per-point speed a platform computes from timestamps that do not exist is not computed at all.

The result is an activity that renders as a line on a map and as an empty space everywhere else — no pace graph, no elevation graph, no splits. That is a fair reflection of a file containing forty coordinates and no clock, and it is the clearest practical argument for treating the thing as a route rather than dressing it as a session.

The route format that fits what you actually have

If the KML is a plan, convert it to GPX and load it as a route or a course. Every platform and device has that feature — Garmin calls it a course, Strava and Komoot call it a route — and none of them requires a start time or a duration, because a plan is not supposed to have either. The line will navigate, the waypoints will come with it, and nothing in the file claims to be a measurement.

The activity you want will exist afterwards, recorded by the device that follows the course, with real times and real sensor data attached. That is the ordering the tools were built around, and it is a great deal less work than importing a fabricated session and correcting its date, its type and its duration by hand.

Converted in the tab, whichever route you decide on

The KML is parsed and the TCX is written in this browser. No request carries the file anywhere, which the network panel confirms during a conversion, and the page works offline once loaded.

For a planned route the sensitivity is not the same as for a recorded one, but it is not nothing. A drawn line says where somebody intends to be, and a My Maps layer of client visits, property viewings or survey stops is commercially confidential before it is personal. Converting locally means the plan does not acquire a copy on somebody else's disk as a side effect of changing its file extension.

How to convert KML to TCX

  1. Drop your KML file onto this page, or click to choose one.
  2. The line is wrapped in TCX activity and lap structure in your browser.
  3. Download the TCX — and check the date before you upload it.

A drawn KML line against the demands of TCX

KML compared with TCX
KMLTCX
Full nameKeyhole Markup LanguageTraining Center XML
File extension.kml.tcx
Media typeapplication/vnd.google-earth.kml+xmlapplication/vnd.garmin.tcx+xml
First published2007
Published byKeyholeGarmin
SpecificationOGC KML 2.3Training Center XML
LicensingOpen standardPublished, not standardised
Standing todayCurrentCurrent
Opens in a browserNo browserNo browser
Considered insteadKMZ, GPXGPX, FIT

Opening the result

The usual programs do not overlap: KML opens in Google Earth, QGIS and ArcGIS, TCX in Garmin Connect, Strava and TrainingPeaks — so whoever receives the result needs something from the second list.

What each format is for

The two are aimed at different work: KML at mapping, TCX at fitness tracking. That is worth weighing before converting, because the reason one exists is usually the reason the other is awkward.

KML is Keyhole's format. The specification is OGC KML 2.3, and it is worth reading if the file has to outlive the tool that wrote it.

TCX comes from Garmin and dates from 2007, specified as Training Center XML. Garmin Connect, Strava and TrainingPeaks all read it.

KML to TCX: the epoch date and the missing duration

Are my KML files uploaded anywhere?

No. This conversion runs entirely inside your browser, so the file never leaves your device. You can confirm it yourself: open the network tab of your browser's developer tools and convert something. You will see the page load, plus the analytics and advertising the site is paid for with — and nothing carrying your file.

Why is my converted activity dated 1 January 1970?

Because the KML held no timestamps. TCX requires every lap to declare a start time, so when there is none to read the Unix epoch is written as a placeholder and the duration comes out as zero.

Can a drawn KML route become a real activity?

No. An activity is defined by when it happened and how long it took, and a line drawn on a map records neither. Nothing added afterwards would be measurement rather than invention.

When does this conversion work properly?

When the KML holds a gx:Track — Google's geometry that stores timestamps alongside coordinates. Then the start, the duration and the point times are all read from the file.

Where does the distance come from?

It is summed along the drawn line, one great-circle leg at a time. Because a drawn line cuts corners, that figure is systematically shorter than the route you would actually travel.

What sport will it be?

`Other`. The TCX schema restricts the value to a short list and a KML says nothing about what the line is for, so the neutral value is written rather than a guess.

What should I use instead?

Convert the KML to GPX and load it as a route or a course. That is the feature every platform has for a planned line, and it does not require a start time.

More about these formats