Mapshaper: a GIS workbench that runs in the browser and on the command line
Tools for editing Shapefile, GeoJSON, TopoJSON and CSV files
At a glance
- What is it?
- One JavaScript codebase for shapefiles, GeoJSON, TopoJSON and GeoTIFF, with the same commands in a terminal and a web UI. The size limits are the part worth reading first.
- Who is it for?
- Mapshaper earns its place in a geospatial workflow by being the same program in two places. The commands you learn on a 200MB shapefile are the commands that work on a 20MB GeoJSON in a browser tab, and the fact that processing happens in the browser is what makes the public site usable on data you cannot upload anywhere.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 9, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Two front ends, one command set
The README describes a tool with three command line programs and a web interface, and the important property is that they are the same tool. The commands are not reimplemented for the browser, which is why the web UI can be a genuinely capable editor rather than a viewer with an upload widget.
* `mapshaper` Runs mapshaper commands.
* `mapshaper-xl` Works the same as `mapshaper`, but runs with more RAM to support larger files.
* `mapshaper-gui` Runs the mapshaper Web interface locally.That gives you four reasonable deployment shapes. You can install from npm and script it, you can clone the repository and build the development code, you can run the GUI locally so nothing leaves the machine, or you can use the public site at mapshaper.org. The README states the privacy property plainly: all processing is done in the browser, so your data stays private even on the public site. That claim is about the editing path, and it is the reason the tool is usable at all for data under any kind of embargo.
The task list is cartographic rather than analytical. Simplifying shapes, editing attribute data, clipping, erasing, dissolving and filtering are the operations, and the documentation calls them essential map making tasks. Dissolve in particular comes up constantly in search queries about Mapshaper, and it is the operation people usually come for: collapsing many features sharing an attribute value into one geometry.
There is also an R package, rmapshaper by Andy Teucher, which gives R users access to many of the same editing commands without leaving R.
The size limits are stated, specific, and hard
The README's large file section is the most useful part of the documentation, because it names actual numbers instead of saying large files are unsupported.
There are hard limits for reading and writing most file types. The maximum output size of a single file of any type is 2GB. Some file types (GeoJSON, CSV, .shp, .dbf) are read incrementally, so much larger files can be imported.Two separate constraints there. The 2GB output ceiling is about writing, and it reads like a filesystem or format limit rather than something Mapshaper chose, which means it applies no matter how much memory you give the process. The incremental read path is the escape valve: GeoJSON, CSV, .shp and .dbf can be read in pieces, so a much larger input is possible as long as the output stays under the cap. If your workflow is simplify and then export, you are inside the limit. If your workflow is join and then write every intermediate step back out as a separate file, you may not be.
Memory is the second constraint, and it is a Node constraint that Mapshaper surfaces rather than hides.
When working with very large files, mapshaper may become unresponsive or crash with the message "JavaScript heap out of memory."The documented fix is a different binary. mapshaper-xl allocates 8GB of heap by default instead of Node's default, and the README shows how to go further and run it directly against Node's own flag.
$ node --max-old-space-size=16000 `which mapshaper` <mapshaper commands>The doubled space in that line is in the README, not a typo introduced here. On the browser side the numbers are softer: the README says Firefox can load shapefiles and GeoJSON over 1GB, while Chrome is still prone to out-of-memory errors above several hundred megabytes.
The dependency list is the format list
There is no separate parser to install, because each format is a package in dependencies. Reading package.json is the fastest way to see what Mapshaper can open, and it covers considerably more than the Shapefile, GeoJSON, TopoJSON and CSV named in the repository description.
The geometry and format side includes delaunator for triangulation, flatbush as a spatial index, flatgeobuf for the FlatGeobuf binary format, @ngageoint/geopackage for GeoPackage, @placemarkio/tokml for KML, @tmcw/togeojson for raster-adjacent conversion, and @bokuweb/zstd-wasm which puts Zstandard compression in the browser through WebAssembly. That last one is the interesting choice, since it means a compressed format works client-side without a native module.
Archive and XML handling is handled by adm-zip and @xmldom/xmldom, with fflate pinned to an exact version for general compression and commander at ^14 as the argument parser. The three d3 packages, d3-color, d3-interpolate and d3-scale-chromatic, are about rendering rather than geometry, and d3-color plus d3-scale-chromatic are pinned to exact versions rather than ranges.
"@bokuweb/zstd-wasm": "^0.0.27",
"@ngageoint/geopackage": "^4.2.6",
"@placemarkio/tokml": "^0.3.3",
"@tmcw/togeojson": "^5.6.0",
"@xmldom/xmldom": "^0.8.6",
"adm-zip": "^0.5.9",
"commander": "^14.0.3",If you are adding Mapshaper to a project, note that this is a dependency list optimized for a bundled single-file CLI, not for a shared library you import. There is no exports map and no module entry, only a main field.
"main": "./mapshaper.js",So importing Mapshaper as a library dependency is not a supported shape. The supported shapes are the executables and the bundled browser build.
MPL 2.0 in two places and noassertion in a third
The license is the one place where the repository's own metadata and its files disagree, and the disagreement is worth naming rather than resolving.
The README has a License section stating the software is licensed under MPL 2.0, and quoting Mozilla's own FAQ on why file-level copyleft works.
This software is licensed under [MPL 2.0](http://www.mozilla.org/MPL/2.0/).package.json agrees, and gives the SPDX identifier rather than only prose.
"license": "MPL-2.0",The repository metadata, the value a client gets back from the GitHub API, reports the license as unasserted, which is GitHub's way of saying it did not recognize the license from the files. That happens when the detection heuristic does not match, often with an unusual license file layout. Both of the authoritative in-repo sources say MPL-2.0, so for compliance purposes the LICENSE file and package.json are what to read, and the API field is not evidence of anything.
The acknowledgement section adds context on provenance. It credits colleagues at The New York Times with suggestions and bug reports, and credits Mark Harrower for collaborating on the original MapShaper program at the University of Wisconsin-Madison. So this is a rewrite of an older tool rather than a greenfield project, and the original lineage is Python-era while the current implementation is JavaScript. The README also credits Mapbox for donating basemap services to mapshaper.org.
Documentation built for tools that read documentation
The README leads with a documentation convention that is increasingly common and rarely explained. There is an llms.txt index of every docs page in machine-readable form, every page is also available as Markdown by appending .md to its URL, and the full corpus is available as one file at llms-full.txt.
That means you can point an assistant or any tool that reads documentation at a single URL and get structured access to the complete command reference instead of scraping HTML. The example the README gives is a command line essentials page with the .md suffix appended.
One wrinkle is worth knowing before you plan to consume it from the npm package. The files array in package.json excludes exactly those documents from the published tarball.
"files": [
"/bin/**",
"/www/**",
"!/www/nacis/**",
"/mapshaper.js",
"!.DS_Store",
"!/www/docs/**",
"!/www/llms*",
"!/www/ai-config.js"
],So the docs and the llms.txt files live in the www directory of the repository and are deployed to the website, but the npm tarball deliberately omits them. That is a sensible size decision for a CLI install, and it means the machine-readable documentation is available over HTTP rather than inside the installed package. If you are building tooling that vendors Mapshaper's docs, fetch them from mapshaper.org rather than expecting them under node_modules.
The docs build itself is a script, npm run docs calling build-docs.mjs, and there is a separate roadmap script, so the site is generated from the repository rather than maintained by hand elsewhere.
Runtime requirements, releases, and the build surface
package.json states the Node requirement precisely, where the README only says Mapshaper requires Node.js.
"engines": {
"node": ">=20.11.0"
},That is a specific floor rather than a vague modern Node note, and it matters because the memory options in the README depend on Node's own flag handling.
Bun is supported as an alternative runtime, and the README gives the one-liner.
bunx mapshaper [commands]The engines field does not mention Bun, which is normal since engines describes Node compatibility, but it does mean the Node floor is the only one the package asserts.
Three releases landed within about nineteen hours in September 2026: v0.7.64 modified Hobby's algorithm to stop the text path spline ballooning under certain geometries, v0.7.65 fixed label dragging bugs, and v0.7.66 added the ability to select groups of labels by criteria from the right-click context menu along with interface improvements. Two of those are label geometry problems and one is a label selection feature, which tells you where the recent effort has gone. The version is 0.7.66 in package.json, matching the newest tag, and the default branch is master rather than main.
The build and test surface is visible in the scripts. Rollup produces both the CLI and the web UI modules, Mocha runs the unit tests through test/mocha-hooks.mjs, Playwright runs the browser tests fully parallel with six workers, and there is a separate raster resampling benchmark gated behind an environment variable so it does not run in the normal suite.
"test:browser": "playwright test --fully-parallel --workers=6",
"benchmark:raster": "MAPSHAPER_RUN_BENCHMARKS=1 playwright test browser-tests/raster-resampling-benchmark.spec.mjs --project=chromium --workers=1"Publish is gated: prepublishOnly runs the unit tests, then the browser tests, then a pre-publish script, and postpublish runs a web UI release script followed by a GitHub version release script. A SECURITY.md is present at the root as well.
Editorial conclusion
Mapshaper earns its place in a geospatial workflow by being the same program in two places. The commands you learn on a 200MB shapefile are the commands that work on a 20MB GeoJSON in a browser tab, and the fact that processing happens in the browser is what makes the public site usable on data you cannot upload anywhere. Three things to know before you rely on it. There is a hard 2GB ceiling on the output size of any single file, which is a format and filesystem limit rather than a Mapshaper one, so anything bigger has to be split. The command line runs in a single Node process with a default heap, so large files need mapshaper-xl or an explicit --max-old-space-size rather than more flags. And the repository metadata reports the license as unasserted while package.json and the README both say MPL 2.0, so if license compliance matters to your organization, read the LICENSE file rather than the API response.
Frequently asked questions
How does Mapshaper work?
It is JavaScript software for editing geospatial data, with three command line programs, mapshaper, mapshaper-xl and mapshaper-gui, plus a browser interface at mapshaper.org. The commands are shared between the two front ends, covering simplifying shapes, editing attribute data, clipping, erasing, dissolving and filtering. The README states that all processing happens in the browser, so data stays private even on the public site.
How can I open a shapefile online?
Mapshaper's public site at www.mapshaper.org does it in the browser with no upload, because the README states all processing is done in the browser. You can also run mapshaper-gui locally so nothing leaves your machine. The same conversion can be scripted from a terminal with mapshaper after installing from npm, and the README notes Firefox can load shapefiles over 1GB while Chrome tends to run out of memory above several hundred megabytes.
How do you handle a shapefile that is too large for Mapshaper?
The README sets a hard ceiling of 2GB on the output size of any single file, while GeoJSON, CSV, .shp and .dbf are read incrementally so larger inputs can be imported. For memory, run mapshaper-xl instead of mapshaper, which allocates 8GB of heap by default and accepts an argument such as mapshaper-xl 20gb, or invoke Node directly with --max-old-space-size.
Can Mapshaper be used as a JavaScript library in another project?
Not as a documented integration. package.json has a main field pointing at the bundled ./mapshaper.js and no exports map, and the README documents only the three executables and the web interface. The supported ways to use it are the CLI, the local GUI, the public site, and the rmapshaper R package, which wraps many of the editing commands.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/mbloch-mapshaper)