Tippecanoe CLI Fundamentals
Tippecanoe converts GeoJSON or NDJSON feature collections into Mapbox Vector Tile (MVT) tilesets packaged as MBTiles or PMTiles — the core translation step in any automated generation pipeline. This page covers the full operational sequence: environment setup, the ingest-simplify-tile-package execution model, the flag groups that govern that model, optimisation trade-offs, and the failure modes specific to CLI invocations.
Pipeline overview
The diagram below shows how Tippecanoe sits in the wider data flow. Raw geometry enters on the left; rendered tiles leave on the right through a tile server or CDN.
Prerequisites
System dependencies
Tippecanoe is a C++17 application. Required packages on Debian/Ubuntu:
sudo apt-get install -y build-essential libsqlite3-dev zlib1g-dev
On macOS with Homebrew:
brew install tippecanoe
To build from source (always produces the most recent version):
git clone https://github.com/felt/tippecanoe.git
cd tippecanoe
make -j$(nproc)
sudo make install
tippecanoe --version
Supported input formats
| Format | Flag / method | Notes |
|---|---|---|
| GeoJSON (RFC 7946) | positional arg | WGS84 (EPSG:4326) required |
| NDJSON | positional arg | one feature per line, no FeatureCollection wrapper |
| CSV with lat/lon | --csv |
explicit column names required |
| stdin stream | - |
combine with -P for parallel read |
| GeoParquet (via conversion) | pipe from ogr2ogr or pyarrow |
see GeoParquet Input Processing |
Tippecanoe assumes EPSG:4326 on input and encodes tile geometry in EPSG:3857 internally. Any other CRS must be reprojected before ingestion — a projection mismatch produces geometrically valid but geographically wrong tiles with no error message.
Environment variables
Set these before any large run to prevent silent failures:
export LC_ALL=C.UTF-8
export SQLITE_TMPDIR=/mnt/fast-nvme/tippecanoe-tmp # must have headroom ≥ 3× input file size
SQLITE_TMPDIR controls where SQLite stages intermediate B-tree data during tile packing. Default /tmp is often on a small tmpfs; redirect it to a volume with adequate I/O throughput when processing continental-scale feature collections.
Input validation
Validate GeoJSON schema and coordinate system before invoking Tippecanoe:
# confirm valid FeatureCollection
jq -e '.type == "FeatureCollection" and (.features | length) > 0' input.geojson
# confirm all coordinates are finite (catches NaN/Inf from projection errors)
jq '[.features[].geometry.coordinates | .. | numbers | isnan or isinfinite] | any' input.geojson
# quick layer/schema audit
ogrinfo -al -so input.geojson
For teams managing tabular formats in object storage, GeoParquet Input Processing covers bbox spatial filtering and column pushdown before the NDJSON stream reaches Tippecanoe stdin.
Core concept: the execution model
Tippecanoe follows a four-stage deterministic pipeline that maps directly to its flag taxonomy:
ingest → simplify → tile → package
| Stage | What happens | Controlling flags |
|---|---|---|
| Ingest | Features read into SQLite scratch DB; layer names assigned | -l, -L, -P, --csv |
| Simplify | Vertex reduction per zoom level; feature dropping | -S, --simplification, -r, --drop-rate, --drop-densest-as-needed |
| Tile | Features sliced to MVT coordinate grid (4096 units/tile) | -Z, -z, -B, --full-detail, --low-detail |
| Package | Tiles written to SQLite MBTiles or individual .pbf files |
-o, -e, --output-to-directory, PMTiles extension |
Understanding which stage a flag belongs to tells you exactly when its effect materialises and which other flags it interacts with.
Step-by-step implementation
Step 1 — Assign layers explicitly
Tippecanoe infers layer names from input filenames. In multi-layer builds that ambiguity causes hard-to-debug style mismatches. Use explicit assignment from the start:
# single file, single layer
tippecanoe -o parcels.mbtiles -l parcels parcels.geojson
# multiple files → multiple named layers in one tileset
tippecanoe -o city.mbtiles \
-L parcels:parcels.geojson \
-L roads:roads.geojson \
-L buildings:buildings.geojson
The layer name string maps directly to the source-layer property referenced in MapLibre GL JSON style documents. Rename a layer at the Tippecanoe step rather than patching the style.
Verify: tippecanoe-decode parcels.mbtiles 0 0 0 | jq 'keys' — layer names must match what your style expects.
Step 2 — Configure zoom range and base zoom
Define the zoom window to control output size and rendering fidelity:
tippecanoe -o parcels.mbtiles -l parcels \
-Z 10 -z 16 \
-B 12 \
parcels.geojson
| Flag | Meaning | Typical value |
|---|---|---|
-Z / --minimum-zoom |
Lowest zoom tile generated | 0–6 for global layers |
-z / --maximum-zoom |
Highest zoom tile generated | 14–16 for parcel/building data |
-B / --base-zoom |
Zoom at which all features are included without dropping | 2 below max-zoom |
For zoom selection guidance tied to dataset density and storage budgets, see Zoom Level Optimization Strategies.
Verify: wc -c parcels.mbtiles gives a rough size check. A z10–z16 parcel tileset for a mid-size city should land between 50 MB and 400 MB.
Step 3 — Apply geometry simplification
Tippecanoe applies Douglas-Peucker simplification to reduce vertex count at lower zooms. Two flags govern the intensity:
tippecanoe -o roads.mbtiles -l roads \
-Z 8 -z 14 \
--simplification=2 \
--no-simplification-of-shared-nodes \
roads.geojson
| Flag | Default | Effect |
|---|---|---|
--simplification=N |
1 | Multiplies default tolerance; 2 = coarser, 0.5 = finer |
--no-simplification-of-shared-nodes |
off | Preserves shared polygon edges; prevents seams between adjacent polygons |
--simplify-only-low-zooms |
off | Restricts simplification to zooms below base-zoom |
The performance trade-off between Visvalingam-Whyatt and Douglas-Peucker algorithms — and when each produces better results for administrative boundaries versus road networks — is covered in Visvalingam vs Douglas-Peucker in Tile Generation.
Verify: tippecanoe-decode roads.mbtiles 10 511 341 | jq '.features[0].geometry.coordinates | length' — compare vertex counts at z10 vs z14 to confirm simplification is active.
Step 4 — Control feature dropping to enforce the 500 KB tile budget
The Mapbox Vector Tile spec imposes no hard size limit, but browser decompression stalls and TTFB penalties become significant above 500 KB per tile. Three mutually exclusive dropping strategies:
# density-aware drop (recommended for most datasets)
tippecanoe -o buildings.mbtiles -l buildings \
-Z 12 -z 16 \
--drop-densest-as-needed \
--extend-zooms-if-still-dropping \
buildings.geojson
| Strategy flag | Behaviour | Best for |
|---|---|---|
--drop-densest-as-needed |
Removes features from densest tiles first; preserves spatial distribution | Urban point/polygon datasets |
--drop-fraction-as-needed |
Removes a uniform percentage from every tile over budget | Uniform-density global layers |
--coalesce-densest-as-needed |
Merges adjacent same-attribute polygons before dropping | Administrative boundaries, land cover |
Combine --drop-densest-as-needed with --extend-zooms-if-still-dropping to avoid silently truncating high-density areas; Tippecanoe will add zoom levels until every feature fits rather than discarding data.
Verify: after build, scan for oversized tiles:
sqlite3 buildings.mbtiles \
"SELECT zoom_level, tile_column, tile_row, length(tile_data) AS bytes
FROM tiles WHERE length(tile_data) > 512000
ORDER BY bytes DESC LIMIT 10;"
Step 5 — Package as MBTiles or PMTiles
Choose the output container based on the downstream delivery architecture:
# MBTiles — single SQLite file; suitable for martin, tileserver-gl
tippecanoe -o output.mbtiles -l parcels --force parcels.geojson
# PMTiles — cloud-optimised single file; HTTP range requests, no server
tippecanoe -o output.pmtiles -l parcels --force parcels.geojson
# individual .pbf tiles — for CDN directories or custom tile servers
tippecanoe -e ./tiles -l parcels parcels.geojson
The structural differences between the two container formats — SQLite page layout, index structure, read amplification under range requests — are covered in MBTiles Architecture and Limits.
--force skips the interactive overwrite prompt and is mandatory in any scripted or CI/CD context.
Verify: tippecanoe-decode output.mbtiles 14 8213 4950 | jq '.features | length' — confirm feature counts at the target zoom tile.
Optimization knobs
Three tuning dimensions dominate production Tippecanoe runs. Adjust them in order: zoom range first, then simplification, then detail level.
| Parameter | Flag | Lower value | Higher value | Primary trade-off |
|---|---|---|---|---|
| Simplification scale | --simplification=N |
Finer geometry, larger tiles | Coarser geometry, smaller tiles | Tile size vs rendering fidelity |
| Tile detail grid | --full-detail=N |
More precise coordinates | Larger tile payloads | Coordinate precision vs payload size |
| Drop rate | --drop-rate=N |
More features at lower zooms | Fewer features at lower zooms | Visual density vs tile budget at low zoom |
The detail grid defaults to 12 bits (4096 units per tile edge). Reducing --full-detail to 10 (1024 units) cuts geometry size noticeably with minimal visual impact at z10 and below.
For a complete flag inventory with interaction effects between --drop-densest-as-needed, --coalesce-densest-as-needed, and --no-simplification-of-shared-nodes, see Essential Tippecanoe Flags for Production Builds.
Integration with adjacent pipeline stages
Upstream: attribute filtering before tiling
Carrying unused properties into the tile increases payload with no rendering benefit. Strip attributes at the Tippecanoe stage rather than in a pre-processing step:
tippecanoe -o parcels.mbtiles -l parcels \
-y parcel_id -y owner_name -y land_use_code \
--drop-densest-as-needed \
parcels.geojson
-y whitelists properties to retain; all others are dropped. For complex filtering logic — retaining different attributes per zoom level or per geometry type — see Attribute Filtering Rules and specifically Dropping Unused Attributes to Reduce Tile Size.
Downstream: MBTiles to tile server
An MBTiles file is an SQLite container that tile servers such as martin or tileserver-gl serve over HTTP. The handoff is a single path reference:
martin --config config.yaml # config references output.mbtiles path
PMTiles files skip the server entirely — a JavaScript client fetches byte ranges directly from R2 or S3 storage. For style-side wiring of vector tile sources to MapLibre GL layer definitions, the source-layer value must exactly match the -l name used at tile generation time.
Python subprocess wrapper
For teams embedding Tippecanoe in a Python orchestration layer:
import subprocess
import sys
from pathlib import Path
def run_tippecanoe(
input_path: str,
output_path: str,
layer: str,
min_zoom: int = 10,
max_zoom: int = 16,
) -> None:
cmd = [
"tippecanoe",
f"--output={output_path}",
f"--layer={layer}",
f"--minimum-zoom={min_zoom}",
f"--maximum-zoom={max_zoom}",
"--drop-densest-as-needed",
"--extend-zooms-if-still-dropping",
"--no-simplification-of-shared-nodes",
"--force",
input_path,
]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
print(f"tippecanoe failed:\n{result.stderr}", file=sys.stderr)
sys.exit(1)
if not Path(output_path).exists():
print("Output file not created — check disk space and SQLITE_TMPDIR", file=sys.stderr)
sys.exit(1)
Capture stderr explicitly: Tippecanoe writes Dropping features at zoom X warnings there, not to stdout. These warnings are the earliest signal of a tile-budget problem.
Troubleshooting
1. Error: No room left / build aborts mid-run
Diagnosis:
df -h $SQLITE_TMPDIR # check available space
du -sh input.geojson # rule of thumb: temp space ≥ 3× input
Fix: Redirect SQLITE_TMPDIR to a volume with headroom, or split the input spatially:
ogr2ogr -spat -80 25 -70 35 southeast.geojson input.geojson
2. Tiles render correctly at z14 but features vanish at z10
Cause: --drop-densest-as-needed is dropping features at lower zooms; --base-zoom is too high.
Diagnosis:
tippecanoe-decode output.mbtiles 10 256 256 | jq '.features | length'
tippecanoe-decode output.mbtiles 14 4096 4096 | jq '.features | length'
Fix: Lower --base-zoom or add --extend-zooms-if-still-dropping so Tippecanoe retains features rather than discarding them.
3. Adjacent polygon seams visible in MapLibre GL JS
Cause: Shared-node simplification is misaligning polygon edges.
Fix: Add --no-simplification-of-shared-nodes. If seams persist, also set --buffer=8 (default 4) to widen the tile overlap buffer:
tippecanoe -o zoning.mbtiles -l zoning \
--no-simplification-of-shared-nodes \
--buffer=8 \
zoning.geojson
4. tippecanoe: GeoJSON does not begin with a FeatureCollection on piped NDJSON
Cause: Piping a full GeoJSON FeatureCollection to stdin instead of a feature-per-line NDJSON stream. Fix:
# correct: unwrap features to NDJSON
jq -c '.features[]' input.geojson | tippecanoe -o output.mbtiles -l layer -
5. Oversized tiles at max zoom despite --drop-densest-as-needed
Cause: --no-tile-size-limit left in a debug invocation, or feature geometries have thousands of vertices that survive simplification.
Diagnosis:
sqlite3 output.mbtiles \
"SELECT zoom_level, count(*) AS n_tiles, max(length(tile_data)) AS max_bytes
FROM tiles GROUP BY zoom_level ORDER BY zoom_level;"
Fix: Increase --simplification for the offending zoom range, or pre-simplify with ogr2ogr -simplify 0.0001 simplified.geojson input.geojson.
Further Reading
Essential Tippecanoe Flags for Production Builds — a focused reference for the six flags that form a reliable production baseline (--drop-densest-as-needed, --extend-zooms-if-still-dropping, --maximum-zoom, --coalesce-densest-as-needed, --no-simplification-of-shared-nodes, --force), covering interaction effects and CI/CD validation steps.
Controlling Tile Size with Drop and Coalesce Flags — how --drop-densest-as-needed, --coalesce-smallest-as-needed, -r/--drop-rate, and --extend-zooms-if-still-dropping decide which features are shed to keep every tile under 500 KB.
Up to parent
Automated Generation Pipelines with Tippecanoe — the parent section covering the full Tippecanoe-based pipeline from input pre-processing through tile delivery.
Related
- Geometry Simplification Algorithms — how Tippecanoe’s simplification stage works, including the choice between Douglas-Peucker and Visvalingam-Whyatt for different geometry types.
- Attribute Filtering Rules — controlling which properties survive into the tile to keep payloads under the 500 KB budget.
- GeoParquet Input Processing — converting columnar GeoParquet files from object storage into the NDJSON stream that feeds Tippecanoe stdin.
- MBTiles Architecture and Limits — SQLite page layout, concurrent read limits, and when to choose PMTiles for cloud delivery instead.