python-geojson-tiler is a beginner-friendly Python tool for splitting large GeoJSON datasets into XYZ tiles.
If you have ever searched for "how to serve big GeoJSON", this project is meant to be the simple answer: take one large GeoJSON file, break it into smaller tile-shaped chunks, and serve those files from a normal static web server.
This first version is intentionally simple:
- It reads a GeoJSON
FeatureorFeatureCollection - It calculates each feature's geographic bounding box
- It writes every intersecting XYZ tile as
z/x/y.geojson - It duplicates features into every tile they touch
- It does not clip geometry to tile edges yet
That trade-off keeps the code easy to understand, easy to test, and easy to extend.
For more geospatial workflow ideas, see Spatial Workflow.
Large GeoJSON files are awkward to ship directly to browsers and map clients. Tiling helps because clients can request only the small pieces they need for the current map view.
This project is useful when you want to:
- pre-split a GeoJSON file into web-friendly XYZ tile folders
- serve big GeoJSON from a basic file server or CDN
- build a simple pipeline without introducing a larger GIS stack yet
- understand the mechanics of XYZ tiling in plain Python
python3 -m venv .venv
source .venv/bin/activatepython -m pip install --upgrade pip
python -m pip install -e ".[dev]"cat > sample.geojson <<'EOF'
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {"name": "Berlin"},
"geometry": {"type": "Point", "coordinates": [13.405, 52.52]}
},
{
"type": "Feature",
"properties": {"name": "Paris"},
"geometry": {"type": "Point", "coordinates": [2.3522, 48.8566]}
}
]
}
EOFgeojson-tiler sample.geojson tiles --min-zoom 0 --max-zoom 2find tiles -maxdepth 4 -type f | sort
cat tiles/metadata.jsoncd tiles
python -m http.server 8000Your files will then be available at paths like:
http://localhost:8000/0/0/0.geojsonhttp://localhost:8000/1/1/0.geojson
geojson-tiler INPUT OUTPUT [--min-zoom MIN] [--max-zoom MAX] [--indent N] [--overwrite] [--quiet]INPUT: path to a GeoJSON file containing aFeatureorFeatureCollectionOUTPUT: directory that will receive XYZ tile folders--min-zoom: first zoom level to generate, default0--max-zoom: last zoom level to generate, default0--indent: JSON indentation level for generated files, default2--overwrite: allow writing into a non-empty output directory--quiet: skip the success summary message--version: print the installed version
The generated directory structure looks like this:
tiles/
├── metadata.json
├── 0/
│ └── 0/
│ └── 0.geojson
├── 1/
│ ├── 0/
│ │ ├── 0.geojson
│ │ └── 1.geojson
│ └── 1/
│ ├── 0.geojson
│ └── 1.geojson
└── ...
Each tile file is a valid GeoJSON FeatureCollection.
metadata.json includes:
- the original source filename
- total input feature count
- total tile count written
- a list of tile addresses and relative file paths
You can also use the tiler directly from Python:
from geojson_tiler.tiler import tile_geojson
from geojson_tiler.writer import write_tiles
geojson_data = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {"name": "Example"},
"geometry": {"type": "Point", "coordinates": [13.405, 52.52]},
}
],
}
result = tile_geojson(geojson_data, min_zoom=0, max_zoom=2)
write_tiles(result, "tiles", source_name="example.geojson")This version supports bounding-box tiling for:
PointMultiPointLineStringMultiLineStringPolygonMultiPolygonGeometryCollectionnullgeometry (skipped)
If a feature overlaps multiple tiles, the full feature is written into every intersecting tile.
That means:
- output is easy to reason about
- output may be larger than a clipped-vector-tiles workflow
- tile borders can contain repeated features
For many beginner and static-serving workflows, this is a good first step.
The tool expects standard GeoJSON coordinates in longitude/latitude order ([lon, lat]). It clamps latitude to the Web Mercator limit used by XYZ tiles.
geojson-tiler countries.geojson country-tiles --min-zoom 4 --max-zoom 4geojson-tiler roads.geojson road-tiles --min-zoom 5 --max-zoom 8geojson-tiler parcels.geojson parcel-tiles --min-zoom 10 --max-zoom 12 --overwritegeojson-tiler input.geojson public/tiles --min-zoom 0 --max-zoom 3 --quietpython -m pytestgeojson-tiler --help
python -m geojson_tiler --helppython -m pip install build
python -m buildsrc/geojson_tiler/
├── __init__.py
├── __main__.py
├── cli.py
├── geojson.py
├── tiler.py
├── writer.py
└── xyz.py
tests/
This repository now contains a complete, runnable first version, but it is still intentionally small.
Current limitations:
- no geometry clipping at tile edges
- no simplification by zoom level
- no spatial index yet
- no direct shapefile reader yet
- no hosted GitHub automation yet in this workspace
Use --overwrite if you want to write into an existing output directory.
The input file must be standard GeoJSON with a top-level Feature or FeatureCollection object.
That is expected in this version when a feature spans multiple tiles. The tool duplicates full features into every intersecting tile rather than clipping them.
When you extend this project, please keep the beginner-friendly goal in mind:
- document new behavior in
README.md - keep CLI examples copy-pasteable
- preserve the Python-only implementation unless the project scope changes
For more spatial workflow ideas and tutorials, visit https://spatialworkflow.io/.