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.

What Tippecanoe does between reading a feature and writing a tileFeatures are read and assigned to layers, sorted into a temporary quadtree index, simplified per zoom, dropped or coalesced where a tile exceeds the budget, and serialised into the output archive.EXECUTION MODELReadGeoJSON · NDJSONassign layersIndexsort into a quadtreetemp files on diskthe memory-hungry stageSimplifyper zoom levelDrop / coalesceenforce 500 KBthe only feature-losing stageWrite.mbtiles · .pmtiles
Only the middle two stages are lossy, and they are the only two most flags touch. Reading and writing are I/O; the fidelity decisions happen in between.

Prerequisites

System dependencies

Tippecanoe is a C++17 application. Required packages on Debian/Ubuntu:

bash
sudo apt-get install -y build-essential libsqlite3-dev zlib1g-dev

On macOS with Homebrew:

bash
brew install tippecanoe

To build from source (always produces the most recent version):

bash
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:

bash
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:

bash
# 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:

text
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:

bash
# 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:

bash
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

What each simplification step buys and costsMean tile size and a vertex-retention percentage plotted against Tippecanoe simplification values from 0 to 20 on the same z13 road build.MEASURED64048032016000246101420--simplification valueMean tile size (KB)Vertices retained (%)
The curve flattens past about 10. Beyond that point each step removes visible geometry and returns almost no bytes — which is where over-simplified builds come from.

Tippecanoe applies Douglas-Peucker simplification to reduce vertex count at lower zooms. Two flags govern the intensity:

bash
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

Which dropping strategy suits which dataFour data shapes mapped to the Tippecanoe strategy that preserves what matters about each: dense points, uniform polygons, dense polygons and data that must not be thinned at all.DECIDEWhat must survive when a tile will not fit?Dense points,pattern matters--drop-densest-as-neededkeeps the distributionAdjacent polygons,shape matters--coalesce-densest-as-neededmerges neighboursEvery feature mustappear--extend-zooms-if-still-droppingadds levels insteadChoropleth — nofeature may vanishReduce attributes andsimplify; never drop

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:

bash
# 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:

bash
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:

bash
# 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.


Reading Tippecanoe’s Output

Tippecanoe writes its progress and its warnings to stderr, which means a pipeline that captures only stdout throws away everything worth reading. Three lines in that stream carry most of the diagnostic value.

The per-zoom feature counts show where the data actually lives. A sudden collapse between two zooms means a minzoom doing something unintended rather than a simplification effect.

The tile-too-large warnings name the exact z/x/y of every tile that hit the budget and what was done about it. A build that reports a handful of these on a dense downtown is healthy; one that reports thousands has a zoom threshold set past what the data supports.

The final summary gives the largest tile in the archive, which is the single number worth asserting in a gate. It is measured, not sampled, so a build that reports a worst tile of 460 KB genuinely has no tile above 460 KB.

Capturing stderr and asserting on those three is the cheapest observability available in this whole pipeline, and it requires no additional tooling at all.

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:

bash
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:

bash
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:

python
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:

bash
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:

bash
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:

bash
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:

bash
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:

bash
# 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:

bash
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.


FAQ

Which flags should always be set explicitly?

--layer, the zoom range, a dropping strategy and an attribute include list. Each has a default, and each default is silent — indistinguishable from a decision nobody made.

Why does Tippecanoe write progress to stderr?

So that stdout can carry tile data when writing to a pipe. A pipeline capturing only stdout discards the per-zoom feature counts, the oversized-tile warnings and the final summary.

What does --force actually do?

Overwrites an existing output file. Without it a rerun fails, which is correct for interactive use and wrong for an automated build that must be safe to retry.

How much memory does a build need?

Roughly two to four times the uncompressed input, driven by the temporary quadtree index. Streaming the input reduces peak memory but not the index, which is what usually sets the requirement.

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.


Next reading Controlling Tile Size with Drop and Coalesce Flags Next reading Essential Tippecanoe Flags for Production Builds Next reading Using tippecanoe-decode to Inspect Build Output