Basics
Short Mapshaper examples for common tasks. The filenames and field names are illustrative — substitute your own. Most recipes also work in the web app's console: drop the leading mapshaper and the input filename; the GUI should already your data loaded.
Looking for the syntax of a particular command or option? See the command reference. For the JS expression context used by
-each,-filter,calc=and other commands, see JavaScript expressions.
Inspecting and exploring
Print a summary of a dataset
mapshaper input.shp -info
-info prints the geometry type, feature count, CRS (if known), bounding box, and the name and type of every attribute field. It's the fastest way to remind yourself what a file actually contains. Add save-to=info.json to capture it as JSON.
Count features grouped by a field
mapshaper counties.shp \
-drop geometry \
-dissolve STATE calc='N = count(), POP = sum(POP)' \
-o state_data.csv
A dissolve with a calc= clause is an idiomatic way to aggregate data values.
Filtering and selecting
Keep features matching a condition
mapshaper countries.geojson -filter 'CONTINENT == "Asia" && POP > 1e7' \
-o output.geojson
-filter keeps features for which the expression returns true.
Keep features inside a bounding box
mapshaper world.shp -clip bbox=-10,35,30,60 -o europe.shp
The four bbox numbers are xmin,ymin,xmax,ymax in the layer's own coordinates.
Keep the top N features by some attribute
mapshaper cities.geojson \
-sort POP descending \
-filter 'this.id < 50' \
-o top50.geojson
-sort POP descending orders by population from largest to smallest. Features have numerical ids starting with 0, so this.id < 50 keeps the first 50.
Drop features with empty geometry
mapshaper messy.geojson -filter remove-empty -o clean.geojson
The remove-empty flag drops features with missing or empty geometry.
Editing attributes
Add derived fields
mapshaper counties.shp \
-each 'STATE_FIPS = COUNTY_FIPS.substr(0, 2),
AREA_KM2 = round(this.area / 1e6, 1)' \
-o out.shp
-each runs a JS expression on each feature; assigning to a bare name creates or updates a field. round(x, 1) is Mapshaper's rounding helper (one decimal here). On unprojected lat/long data, this.area returns square meters, dividing by 1e6 converts to square kilometers.
Rename and filter fields
mapshaper data.csv \
-rename-fields POPULATION=POP,MEDIAN_INCOME=MEDIAN_INC \
-filter-fields STATE,COUNTY,POPULATION,MEDIAN_INCOME \
-o cleaned.csv
-rename-fields takes NEW=OLD pairs. -filter-fields keeps only the listed fields, in the listed order — convenient for shaping CSV output.
Preserve leading zeros from a CSV
mapshaper -i counties.csv string-fields=FIPS,STATEFIPS \
-o counties.shp
By default Mapshaper parses any numeric-looking CSV column as a number, which silently drops leading zeros from FIPS, ZIP and similar identifier columns. string-fields= forces the named columns to stay as strings.
Joining data
Join a CSV to a Shapefile by key
mapshaper states.shp \
-join demographics.csv keys=STATE_FIPS,FIPS string-fields=FIPS \
-o states_with_data.shp
keys=A,B means "match the target's A field to the source's B field". string-fields=FIPS (passed through to the CSV import) keeps the FIPS code as a string so "06" matches "06" rather than being parsed to 6. To pull just a few columns from the source, add fields=FIELD_A,FIELD_B.
Spatial join: tag points with the polygon they fall in
mapshaper crimes.geojson \
-join precinct_polygons.shp \
-o crimes_with_precinct.geojson
When keys= is omitted, -join falls back to a spatial join based on the geometry types involved. Here, every point inherits the attributes of the polygon containing it. Use fields=PRECINCT_ID,DIVISION to keep just specific columns.
Many-to-one join with an aggregation
mapshaper precincts.shp \
-join crimes.geojson calc='N = count(), AVG_SEVERITY = mean(SEVERITY)' \
-o precincts_with_stats.shp
A polygon-to-many-points join can use calc= to summarize the matched source records into one or more new fields per target feature. The functions in calc= are the same set documented under -calc.
Simplifying
Simplify a polygon layer for the web
mapshaper provinces.shp \
-simplify 5% keep-shapes \
-clean \
-o format=topojson provinces.topojson
-simplify 5% keeps 5% of the original vertices using the default weighted Visvalingam algorithm. keep-shapes prevents simplification from wiping out very small polygons. -clean mops up any topology errors introduced by aggressive simplification. TopoJSON output is usually 2–5x smaller than the equivalent GeoJSON.
Simplify multiple files with shared topology
mapshaper -i states.shp counties.shp combine-files \
-simplify 10% \
-o out/
combine-files merges the inputs into one dataset before Mapshaper builds its arc topology, so vertices shared between layers stay shared after simplification — no gaps or overlaps along state/county boundaries. Each input still gets written back out as a separate file in out/. In the web app, add combine-files in the Advanced options field at import time to get the same behavior.
Repair topology errors
mapshaper messy.shp -clean -o cleaned.shp
-clean snaps near-duplicate vertices, removes tiny gaps and overlaps between polygons, and fixes self-intersecting lines. It's a safe first step before any spatial operation. You can tune gap-fill-area=, sliver-control= or snap-interval= if necessary.
Aggregating
Dissolve to a parent geography
mapshaper counties.shp -dissolve STATE -o states.shp
-dissolve merges adjacent polygons that share a value in the named field.
Dissolve while computing per-group stats
mapshaper counties.shp \
-dissolve STATE calc='N = count(),
POP = sum(POP),
MEDIAN_INC = median(MEDIAN_INC)' \
-o states_with_stats.shp
calc= works inside -dissolve as well as -join. The named functions (count, sum, mean, median, mode, min, max, quartile1/2/3, iqr, quantile, collect, every, some, first, last) all see the same per-feature context as -each.
Convert points to population-weighted centroids
mapshaper cities.shp \
-dissolve STATE_FIPS weight=POPULATION \
-o state_centers.shp
Dissolve groups of points that share a STATE_FIPS value into a single weighted centroid per group. The weight= option accepts a field name or a JS expression. Omitting a grouping field dissolves all points into one centroid.
Spatial operations
Erase one layer from another
mapshaper land.shp -erase lakes.shp -o land_no_lakes.shp
-erase removes the parts of the target layer that fall inside the source layer's polygons. Useful for masking out water, parks, or any "do-not-count" region. The inverse is -clip, which keeps the inside instead.
Compute interior boundaries
mapshaper counties.shp -innerlines -o county_borders.shp
-innerlines returns the shared boundaries between polygons as a polyline layer, which is usually used for adding a stroke to interior boundaries on a styled map. Use -lines instead if you want to retain both outer and inner boundaries.
Generate a hex grid covering a layer
mapshaper region.shp \
-grid type=hex interval=10km name=hex \
-o hex.shp
-grid builds a regular grid (square, hex, hex2) covering the target's bounding box. Pair it with a spatial join to style the grid cells using interpolated count data (-join interpolate=POPULATION).
Reprojection
Project to a named CRS
mapshaper world.geojson -proj robinson -o world_robinson.geojson
-proj accepts EPSG codes (EPSG:3857), PROJ strings (+proj=tmerc +lon_0=...), or short aliases (wgs84, webmercator, robinson, albersusa). See the Projections guide for details.
Match the projection of another file
mapshaper points.shp -proj match=basemap.shp -o points_aligned.shp
match= reads the CRS of another file and projects the target to match it — handy when assembling multiple datasets that need to share a coordinate system.
Classification and styling
Quantile-classify into a color ramp
mapshaper covid_cases.geojson \
-classify save-as=fill quantile classes=6 color-scheme=Oranges \
-o themed.geojson
-classify writes a class index or a derived value (here, a fill color) into the named field. The default is sequential quantile classification, but you can switch to equal-interval, nice, categorical or non-adjacent. Run mapshaper -colors to list the built-in color schemes.
Add SVG styling for export
mapshaper boundaries.shp \
-style stroke="#444" stroke-width=0.5 fill=none \
-style where='RANK == 0' stroke="#000" stroke-width=1.5 \
-o map.svg
-style writes SVG presentation attributes onto each feature; the where= form lets you set them conditionally. The result is a valid SVG you can drop into a print or web layout.
Output and conversion
Convert Shapefile ↔ GeoJSON
mapshaper input.shp -o input.geojson
mapshaper input.geojson -o input.shp
The output format is inferred from the file extension. Use format= to force it (e.g. -o format=topojson out.json). When writing a Shapefile, Mapshaper produces .shp, .shx, .dbf, and .prj. If no output filename is given, the output file takes the name of the targeted layer.
Quantized TopoJSON
mapshaper boundaries.shp -o boundaries.topojson
TopoJSON output is quantized by default — Mapshaper picks a quantization level based on the data's coordinate range. Quantization rounds coordinates to a grid, which dramatically shrinks file size. The default can be overridden with quantization= (e.g. quantization=1e5). Combined with -simplify and TopoJSON's shared-arc encoding, quantized output is routinely 2–5× smaller than equivalent GeoJSON.
Output as ndjson
mapshaper big.geojson -o ndjson big.ndjson
Newline-delimited JSON is friendlier to line-oriented tools like jq, BigQuery, and DuckDB. One Feature per line, no enclosing FeatureCollection.
Split a layer into multiple files
mapshaper counties.shp \
-split STATE \
-o out/ extension=geojson
-split FIELD partitions features into separate layers by the value of FIELD; -o to a directory then writes one file per layer, named after the field value.
Workflow patterns
Run a chain of commands from a file
# build.txt
mapshaper
-i counties.shp
-rename-fields POP=POPULATION
-dissolve STATE calc='POP = sum(POP)'
-simplify 5%
-o out/states.topojson
mapshaper -run build.txt
# or simply:
mapshaper build.txt
Long pipelines can be kept in a command file.
Parameterize a command file
mapshaper -vars YEAR=2024 PCT=10 -run build.txt
# build.txt
mapshaper
-defaults YEAR=2020 PCT=5
-i sources/counties_{{YEAR}}.shp
-simplify {{PCT}}%
-o out/counties_{{YEAR}}.shp
{{VAR}} placeholders are substituted at parse time. -defaults sets values that the caller can override with -vars (or with {{env.NAME}} for environment variables).
Stop a pipeline early on bad input
mapshaper input.csv \
-calc 'N = count()' \
-if 'global.N == 0' \
-print 'No records, exiting' \
-stop \
-endif \
-o out.csv
-calc expressions can publish values to the global object via simple assignment. -if/-stop then guard the rest of the pipeline. Useful in scripts where bad upstream data should fail loudly rather than silently produce empty output.
Increase the heap for very large files
mapshaper-xl 16gb counties_5m.shp -simplify 10% -o counties_5m.topojson
mapshaper-xl is a wrapper that launches Node with extra heap space (default 8 GB; pass a size to override). Use it whenever you see "JavaScript heap out of memory" errors.
See also
- Command reference — every command and option
- JavaScript expressions — the syntax and context used by
-each,-filter,calc=, etc.