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

TopoJSON to GeoJSON

TopoJSON is a transfer format, not a working one. Almost nothing renders it directly — d3 wants topojson.feature() called first, and every other map library wants plain GeoJSON. This does that step without the library: arcs stitched back together, delta encoding undone, the quantisation grid mapped back to degrees.

TopoJSON to GeoJSON

updated 31 August 2026

Drop a .topojson file, or

What this tool does

It reads a TopoJSON Topology and writes a GeoJSON FeatureCollection. Every geometry in a topology stores indices into a shared arcs array rather than its own coordinates; this walks those indices, pastes the runs back together in order, and hands you shapes that carry their coordinates again.

The intent it closes: "I downloaded the boundary file everyone uses and my map library says it is not GeoJSON." Most published boundary data — Natural Earth builds, the US Atlas files, anything produced by geo2topo — ships as TopoJSON because it is three to ten times smaller. That saving is on the wire. The moment the file lands you need the other format back.

How this tool works

Three encodings are layered on top of each other, and they have to come off in order.

1. Undo the delta encoding

Inside an arc only the first position is absolute. Everything after it is the step from the position before, which is a small number and therefore a short one. Reading an arc means running a cursor along it and adding each step to the last result.

2. Apply the transform

If the topology carries a transform, the positions are integers on a grid rather than degrees. Multiply by transform.scale and add transform.translate and you are back in longitude and latitude. A topology without a transform was never quantised and its positions are already absolute floats — the tool says which case it found in the status line.

3. Stitch the arcs

A ring or line is a list of arc indices. Consecutive arcs meet at a shared position, so the first point of every arc after the first is dropped — otherwise every junction would appear twice. A negative index means that arc traversed backwards: -1 is arc 0 reversed, -2 is arc 1 reversed, because the encoding is ~i rather than -i. That is how two countries share one border and still each trace their own outline in the right direction.

Options

Object

A topology can hold several named objects — counties and states in the same file, sharing one arc pool. The picker is filled from whatever you paste, so the names come from the file rather than from memory. all objects flattens every one of them into a single collection.

Tag features with their object name

Only does anything when you convert more than one object at once: each feature gets an object property holding the name it came from, so a flattened collection can be split apart again with filter features. An existing object property is never overwritten.

Keep properties

On, each geometry's properties and id come across unchanged. Off drops the properties and keeps the ids — worth it when the attributes are half the file and you only want the shapes.

Example

The two-square topology, with the shared edge stored once:

{"type":"Topology",
 "objects":{"data":{"type":"GeometryCollection","geometries":[
   {"type":"Polygon","arcs":[[0,1]],"properties":{"n":"a"}},
   {"type":"Polygon","arcs":[[2,-1]],"properties":{"n":"b"}}]}},
 "arcs":[[[1,0],[1,1]],[[1,1],[0,1],[0,0],[1,0]],[[1,0],[2,0],[2,1],[1,1]]]}

Output:

{"type":"FeatureCollection","features":[
 {"type":"Feature","properties":{"n":"a"},"geometry":{"type":"Polygon",
  "coordinates":[[[1,0],[1,1],[0,1],[0,0],[1,0]]]}},
 {"type":"Feature","properties":{"n":"b"},"geometry":{"type":"Polygon",
  "coordinates":[[[1,0],[2,0],[2,1],[1,1],[1,0]]]}}]}

The second polygon's -1 became arc 0 read backwards — [[1,1],[1,0]] — which is why its outline runs the opposite way along the shared edge from the first one's. Both rings come back closed even though the arcs never repeat their first point.

Tips & common pitfalls

  • The output is bigger, and that is the whole point. The status line shows the growth. Duplicated borders and full coordinates are exactly what the topology was compressing; you are paying that back to get a file things can draw.
  • Quantisation does not come back. If the file was quantised at 1e4, the positions are on that grid for good — decoding returns the grid points in degrees, not the coordinates the file was built from. That is a property of the source, not of this tool.
  • The round trip through GeoJSON to TopoJSON is lossless without quantisation. Choose none there and convert back here and the coordinates match to the last digit. Ring starting points can rotate, because an arc split has to begin somewhere — the shape is identical.
  • Elevation is already gone. TopoJSON is two-dimensional. If the topology came from a GPS track, the third coordinate was dropped when it was encoded and nothing here can recover it.
  • Check the arc count in the status line. It reports how many of the file's arcs any geometry actually referenced. A large gap usually means you converted one object out of several — arcs are shared across the whole file, so the unused ones belong to the objects you left behind.

FAQ

Which TopoJSON version does it read?

The 1.0 specification, which is what every producer in circulation emits — geo2topo, the topojson CLI, QGIS exports, the Natural Earth and US Atlas builds. All seven geometry types are handled, plus nested GeometryCollection, and an object that is a bare geometry rather than a collection.

Why do my polygons look inside out?

Winding order. Some producers write TopoJSON rings in the opposite direction from the GeoJSON convention, and a spherical renderer will fill the wrong side of the world. Nothing here reorders them — run fix winding order on the output and it becomes RFC 7946 compliant.

Can it handle a file with several objects?

Yes. Convert them one at a time with the picker, or choose all objects to flatten everything into one collection. In the flattened case each feature can be tagged with the object it came from, so nothing becomes ambiguous.

It says "this is not a topology". What now?

The top-level type has to be Topology. A file whose type is FeatureCollection is already GeoJSON and needs no conversion; a .json from a mapping tool is often plain GeoJSON with a misleading extension. Paste it into the validator to see which you have.

Is it fast on a big file?

Each arc is decoded once and cached, so a border referenced by both of its countries costs nothing the second time. The work is linear in the number of positions, and the slow part of a large file is JSON.parse, not the decoding.