Converting a Shapefile to GeoJSON sounds trivial — it's a one-line ogr2ogr command. In practice, half the conversions go subtly wrong because of CRS mismatches, attribute encoding, or oversized output. This guide walks through three working approaches and points out where each one breaks.
Before you start: what you should have
A valid Shapefile is a bundle, not a single file. At minimum you need:
your_data.shp— geometryyour_data.shx— positional indexyour_data.dbf— attribute tableyour_data.prj— projection (technically optional, practically essential)
If any of the first three are missing, the dataset is dead. If the .prj is missing, the output GeoJSON will not be reprojectable downstream — you'll have to guess the source CRS or ask the supplier.
If the supplier handed you a .zip, unzip it first and check the contents. The .shp/.shx/.dbf/.prj files must all sit directly in the archive root or in the same folder — not in nested sub-folders.
Approach 1: QGIS (the GUI route)
Best for: one-off conversions, when you want to inspect the data first.
- Open QGIS (3.x). Drag the
.shpinto the canvas — QGIS will read the bundle automatically. - The layer appears in the Layers panel. Click it once, then check the bottom-right CRS indicator. It should match the CRS you expect. If it says "Unknown CRS", right-click the layer → Set CRS → Layer CRS, and choose the correct EPSG code.
- Right-click the layer → Export → Save Features As.
- In the dialog, set Format to GeoJSON.
- Set File name to your output path.
- Critically: in CRS, choose EPSG:4326. RFC 7946 requires WGS 84.
- (Optional) Under Layer Options, set
COORDINATE_PRECISIONto 6 — more than enough for sub-metre accuracy and dramatically smaller than the default 15. - Click OK.
QGIS will reproject (if needed) and write a GeoJSON file. Inspect the output by dragging it back into QGIS or opening it in a text editor.
Approach 2: GDAL ogr2ogr (the command-line route)
Best for: scripting, batch conversions, CI pipelines.
Install GDAL if you haven't (brew install gdal, apt install gdal-bin, or conda install -c conda-forge gdal). Then:
ogr2ogr -f GeoJSON output.geojson input.shpThat's the happy path. In reality you'll almost always want a few flags:
ogr2ogr \
-f GeoJSON \
-t_srs EPSG:4326 \
-lco RFC7946=YES \
-lco COORDINATE_PRECISION=6 \
output.geojson input.shpWhat each flag does:
-t_srs EPSG:4326reprojects to WGS 84. Skip only if you know the source is already in WGS 84.-lco RFC7946=YESenforces RFC 7946 conformance (right-hand winding order, no CRS member, proper antimeridian handling).-lco COORDINATE_PRECISION=6truncates coordinates to six decimal places, saving 30–50% on file size with no visible loss for web maps.
For encoding issues, add -oo ENCODING=UTF-8 (or whatever the source actually is — -oo ENCODING=ISO-8859-1 for legacy Western European Shapefiles).
Approach 3: Online (the no-install route)
Best for: one-off conversions when you don't have GDAL or QGIS installed, and the file is under 50 MB.
- Zip your Shapefile bundle. All four files (
.shp/.shx/.dbf/.prj) must be at the root of the archive, not in a sub-folder. - Open the Shapefile to GeoJSON converter.
- Drop the
.ziponto the upload area. - The backend runs GDAL on an isolated, short-lived worker (Fly.io, Frankfurt/EU). Conversion typically completes in a few seconds.
- Download the resulting
.geojson.
No files are stored on the server; your upload is processed in a per-request temporary directory and deleted in full immediately after the response — even on error. No database, no persistent storage.
The four things that go wrong
1. Coordinates appear in the wrong place. Usually because the .prj was missing or wrong. Fix by re-running with -s_srs EPSG:<correct_code> -t_srs EPSG:4326.
2. Accented characters become `?` or `é`. Encoding mismatch. The .dbf is probably Windows-1252 but your reader assumed UTF-8 (or vice versa). Add -oo ENCODING=ISO-8859-1 (or the correct codepage) when reading.
3. Output file is huge. Two culprits: too many coordinate decimals, and an exploded geometry. Add -lco COORDINATE_PRECISION=6. If the file is still huge, consider TopoJSON — for adjacent polygons it cuts size by 60–80%.
4. Attribute names are truncated. This happens going the other direction (GeoJSON → Shapefile). The .dbf field-name limit is 10 characters. There is no workaround in Shapefile; either accept the truncation or pick GeoPackage as your target.
Validating the result
After conversion, run the output through our GeoJSON validator to confirm RFC 7946 conformance. Common issues the validator catches: unclosed polygon rings (rare but devastating), coordinates outside the valid range, and mixed geometry types in a collection.
For very large files, validate locally with ogrinfo -ro -al -so output.geojson to see the layer summary without loading the whole file.
When not to convert
If the destination is also a desktop GIS tool, consider GeoPackage instead of GeoJSON. You'll keep the long attribute names, gain a spatial index, and end up with a smaller file. Our Shapefile to GeoPackage converter handles that path.
If the destination is a web map but the dataset is over 50 MB, consider vector tiles via tippecanoe instead of plain GeoJSON. Tiles load by viewport rather than all at once, so a multi-gigabyte source dataset can still render at 60 fps in a browser.