npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

svg-path-simplify

v0.3.6

Published

Simplify Bézier paths while maintaining their shape

Readme

npm version license CDN CDN

Watch the curve, not the file size!

While this library reduces SVG markup sizes significantly by removing commands it prioritizes visual quality over numeric compression gains. Unlike most existing approaches (e.g in graphic applications), it checks where simplifications are suitable and stops simplification at the right »point« (literally).

simplification
Fira Sans (based on truetype/glyph quadratic commands) converted to cubic Bèziers. Right:Original; Left:optimized

Features – what it does

  • reduces the number of SVG commands (both Bèziers and lines) by converting/combining adjacent:

    • Béziers (C, Q)
    • flat Béziers to Linetos
    • colinear lines (L)
  • reorders path starting points to replace unnecessary closing linetos by Z commands

  • optimizes SVG file size by contextually converting to:

    • shorthand commands (C => S, Q => T, L=>H or V)
    • cubics to quadratic Béziers (only 1 control point)
    • cubic arc-like segments to A (elliptic arc)
  • adaptive coordinate rounding: small or large details can be auto-detected to find a suitable floating point accuracy without guessing the decimal value (3 decimals may not be the silver bullet=)

  • split segments at extremes – only useful for manual editing

  • optimize either path data strings or SVG markup code

  • create curves from polylines (curve-fitting)

TOC

Usage

Browser

Example 1: parse and simplify (using defaults)

<script src="https://cdn.jsdelivr.net/npm/svg-path-simplify@latest/dist/svg-path-simplify.min.js"></script>
let pathDataString = 
`
M 57.13 15.5
c 13.28 0 24.53 8.67 28.42 20.65
c 0.94 2.91 1.45 6.01 1.45 9.23
`

// try to simplify
let pathDataOpt = svgPathSimplify(pathDataString);

// simplified pathData
console.log(pathDataOpt)
// returns `M 57.1 15.5c16.5 0 29.9 13.4 29.9 29.9`

ESM version

import { svgPathSimplify } from '../dist/svg-path-simplify.esm.min.js'

let pathDataString =
`
M 57.13 15.5
c 13.28 0 24.53 8.67 28.42 20.65
c 0.94 2.91 1.45 6.01 1.45 9.23
`

// try to simplify
let pathDataOpt = svgPathSimplify(pathDataString);

// simplified pathData
console.log(pathDataOpt)
// returns `M 57.1 15.5c16.5 0 29.9 13.4 29.9 29.9`

node.js

Install module via npm:

npm install svg-path-simplify

To simplify entire SVG documents in node.js we need to emulate the browsers DOM methods DOMParser and XMLSerializer. I opted for linkedom. Just make sure to import the svg-path-simplify/node module. It will load linkedom's methods DOMParser and add a polyfill for XMLSerializer

/**
 * load node polyfills for DOM parsing
 * loads linkedom npm module for DOM parsing and emulation 
 */
import 'svg-path-simplify/node';

// use it as in the above examples
import { svgPathSimplify  } from 'svg-path-simplify';

let pathDataString =  `M 57.13 15.5c 13.28 0 24.53 8.67 28.42 20.65c 0.94 2.91 1.45 6.01 1.45 9.23`;
let pathDataOpt = svgPathSimplify(pathDataString);

Web worker

Similar to node.js usage we need linkedom to polyfill missing DOMParser functionality in a headless environment.

import './svg-path-simplify.worker.polyfills.js';
import { svgPathSimplify } from './svg-path-simplify.esm.js';

Import the polyfill module from the dist folder. It imports the worker version of linkedom. See svg-path-simplify.worker.js.

Example 2: Apply options

The following example would return a detailed object containing the stringified "normalized" pathdata (all absolute and "longhand" command notation).

let options = {
 extrapolateDominant: false,
 decimals: 3,
 toRelative: false,
 toShorthands = false,
 minifyD: 2,
 getObject: true
}

let input = `M717 208c-35 12-74 14-135 14 54 25 82 64 82 117 0 93-68 157-177 157-21 0-40-3-59-9-14 10-22 27-22 43 0 26 20 38 60 38h74c93 0 158 55 158 128 0 90-75 141-217 141-149 0-198-44-198-141h73c0 56 25 77 125 77 97 0 135-23 135-71 0-44-34-66-93-66h-73c-78 0-119-38-119-88 0-30 18-59 51-82-54-28-78-68-78-128 0-93 78-161 178-161 73 1 120-6 152-17 16-6 36-14 60-24zm-235 27c-61 0-96 41-96 103s36 105 98 105 97-39 97-106-33-102-99-102z`;

let simplified = svgPathSimplify(input, options);
let {svg, d, report} = simplified;

console.log(simplified)

/*
// returns 
{
"svg": "",
"d": "M 717 208
C 682 220 643 222 582 222
C 636 247 664 286 664 339
C 664 432 596 496 487 496
C 466 496 447 493 428 487
C 414 497 406 514 406 530
C 406 556 426 568 466 568
L 540 568
C 633 568 698 623 698 696
C 698 786 623 837 481 837
C 332 837 283 793 283 696
L 356 696
C 356 752 381 773 481 773
C 578 773 616 750 616 702
C 616 658 582 636 523 636
L 450 636
C 372 636 331 598 331 548
C 331 518 349 489 382 466
C 328 438 304 398 304 338
C 304 245 382 177 482 177
C 555 178 602 171 634 160
C 650 154 670 146 694 136
Z 
M 482 235
C 421 235 386 276 386 338
C 386 400 422 443 484 443
C 546 443 581 404 581 337
C 581 270 548 235 482 235
Z 
",
 "report": {
  "original": 29,
  "new": 29,
  "saved": 0,
  "compression": 148.46,
  "decimals": 0
 },
 "inputType": "pathDataString",
 "mode": 0
}
*/

API

let options = {}
let output = svgPathSimplify(input, options);

The first parameter is the SVG input:

  • a path data string – as used in SVG <path> element's d attribute
  • a polygon string – as used in SVG <polygon> element's points attribute
  • an entire <svg> markup

While svg-path-simplify aims at a convenient config-free usage you can tweak the simplification and output via these options passed as an object.

Simplification parameters

These params control shich simplifications are applied. The default settings aim at a safe or balanced performance-to-minification ratio. However if your main goal is to get the most compact result you can enable additional options which also require more processing time. | parameter | effect | type | default | | -- | -- | -- | -- | | simplifyBezier | main Bézier simplification. When disabled you get the common optimization similar to SVGO (rounding, to all relative and shorthand conversions) | Boolean | true | | tolerance | increase or decrease tolerance: higher values allow more distortions, lower ones more shape fidelity | Number | 1 | | optimizeOrder | reorders commands to get more adjacent simplification candidates. Improves optimization efficiency | Boolean | true | | removeColinear | removes unnecessary zero-length or colinear lineto commands | Boolean | true | | flatBezierToLinetos | replaces flat Béziers with linetos which also can be stripped via previous colinear removal | Boolean | true | | revertToQuadratics | replaces cubic Béziers with quadratic (more compact) ones when applicable | Boolean | true | | keepExtremes | skips simplification accross x/y extrema – improves shape fidelity | Boolean | true | | keepCorners | skips simplification corners – improves shape fidelity | Boolean | true | | keepInflections | retains commands introducing direction changes – adds complexity but may help for editing in a graphic application | Boolean | false |

Advanced simplifications

| parameter | effect | type | default | | -- | -- | -- | -- | | refineExtremes | tries to combine commands close to an adjacent x/y extreme segment | Boolean | false | | addExtremes | adds commands at x/y extrema – adds complexity but may help for editing in a graphic application – when using this option enable refineExtremes as well to avoid tiny adjacent segments | Boolean | false | | simplifyCorners | replaces Bézier segments enclosed by linetos with single quadratic commands – handy to reduce overly complex tiny corner roundings. See example in webapp | Boolean | false | | cubicToArc | replaces Bézier segments by elliptic arc A commands where applicable – can reduce complexity for semi- or full circles | Boolean | false | | simplifyRound | replaces small round segments encloses by linetos – helps to simplify shapes like gears/cogs | Boolean | false |

Path direction

| parameter | effect | type | default | | -- | -- | -- | -- | | fixDirections | alternates sub path directions to fulfill non-zero. Makes fill-rule attribute obsolete and render correct in other environments e.g when converting to fonts | Boolean | false | | reversePath | simply reverses drawing direction - sometimes needed for line animations | Boolean | false |

Polygon options

| parameter | effect | type | default | | -- | -- | -- | -- | | smoothPoly | Curve-fitting: Converts polylines to cubic beziers | Boolean | false |

Output options

| parameter | effect | type | default | | -- | -- | -- | -- | | getObject | whether to return the SVG/pathdata markup directly or a detailed object (containing more info) | Boolean | true |

SVG output optimizations

| parameter | effect | type | default | | -- | -- | -- | -- | | autoAccuracy | calculates a suitable floating point precision for coordinate rounding. Usually rather conservative – decreasing by one decimal should work without significant distortions | Boolean | true | | decimals | manual floating point rounding precision – overriden when autoAccuracy is enabled | Number | 3 | | minifyD | path data microoptimization: removes recurring command type tokens, whitespace and leading zeroes: 0: maximum optimization; 1: "verbose" dont't omit command type tokes; 2: "beautify" separate each command with new lines (e.g for educational purposes) | Number | 0 | | toRelative | converts all commands to relative – reduces file size | Boolean | true | | toShorthands | converts all commands to shorthand when applicable – reduces file size | Boolean | true |

SVG scaling

Scaling only indirectly affects file size analogous to rounding. Use it only for very large or small SVGs. Finding the »sweet spot« where all coordinates can be expressed in integers can reduce file size as no decimal separators are required.

| parameter | effect | type | default | | -- | -- | -- | -- | | scale | scales all pathdata, viewBox, width and height attributes | Boolean | true | | scaleTo | scales to a specified max width | Boolean | false |

SVG input normalization

| parameter | effect | type | default | | -- | -- | -- | -- | | quadraticToCubic | converts all quadratic Béziers to cubics – recommended for efficiency | Boolean | true | | arcToCubic | converts elliptic arc A commands to cubic approximations – not recommended | Boolean | false | | removeHidden | removes hidden elements for SVG inputs | Boolean | true | | mergePaths | concatenates paths into single one – does not respect individual styles! | Boolean | false | | shapesToPaths | converts shapes to paths - usually not recommended as shapes are most often more compact. But useful for path concatenation | Boolean | false | | stylesToAttributes | consolidates styles and set them to attributes. Also removes invalid attributes (e.g font-family for paths) | Boolean | false |

Lite version – only path data

Since the library aims at a complete toolset it might be an overkill for your needs. For this use case you can opt for the lighter pathdata only version »svg-path-simplify.pathdata.esm.min«. Minified filesize is ~41 KB / 17 KB gzipped (compared to the full library with ~72/27 KB)

The API is compatible but simply missing some options such as:

  • polygon smoothing/curve fitting
  • svg processing - only path data is allowed
  • no scaling
  • no path direction fixes


import { simplifyPathData } from '../dist/svg-path-simplify.pathdata.esm.js'

let pathDataString =
`
M 57.13 15.5
c 13.28 0 24.53 8.67 28.42 20.65
c 0.94 2.91 1.45 6.01 1.45 9.23
`
// try to simplify
let pathDataOpt = simplifyPathData(pathDataString);

/*
 or with options let pathDataOpt = simplifyPathData(pathDataString, options);
*/

Demos

Web app

You can easily test this library via the webapp or by checking the demo folder.

web app

Features

  • test all provided simplification option - export settings as JS object
  • preview different settings
  • accepts SVG files
  • path data strings
  • supports multi file batch processing
  • open results in codepen or svg-path-editor
  • download self contained SVG

Demo files

Limitations

Optimization of complete SVG files

This lib's focus is on path data optimizations. While it also provides some basic cleanup options for entire SVG documents (e.g removal of hidden elements or path merging) – if you need a full blown document optimization better opt for SVGO or the GUI SVGOMG. SVGO comes with a plethora of options to remove document overhead like unused definitions like gradients, defs, styles etc.

»Natural« limitations of vector/curve simplification

Unlike raster images we can't reduce information in vector graphics in a predictable fashion. While we can apply brute force and remove points – it won't work:

We always need to respect the complexity of a graphic: if we remove too many segments – we significantly change the appearance.

Scaling down can only help if we're dealing with an either huge or microscopic coordinate space: large numbers vs. small ones requiring too many floating point decimals. For instance scaling down a 100x100 viewBox to 24x24 won't significantly reduce the ultimate file size or even result in larger markup sizes due too more floating point values.

The sad truth about »gigantic« SVG files

SVGs > 1 MB are most of the time not salvagable. At least if they contain 10K+ of path data. Quite often their size comes from the complexity itself not from overhead or simplifyable geometries. This is especially true for many CAD exports containing a rubbish structure with way too many separate line elements that can't easily be combined to curves.

Recommendation: If a simplification still doesn't result in a significantly smaller file size or better rendering – a Hi-res raster image is often the only reasonable workaround. Bear in mind, most rendering pipelines for raster images are more optimized than vector renderers (e.g often benefitting from gpu accelleration) so a 1MB raster image (png, webp, jpeg etc) won't let your renderer scream in agony – a 1MB SVG does!

Changelog, Updates and rollback

Changelog

  • 0.3.0 webapp adds support for multi file batch optimizations, web worker support, drawing direction fix option (for fill rules)
  • 0.2.0 added features for polygon curve fitting
  • 0.1.0 fixed node support for complete svg files

Rollback

If you encounter any issues with the recent versions you can rollback to a previous version.
See all versions on

Bug reporting

If you found a bug - feel free to file an issue.
For debugging you may also test your example in the webapp. You can also post in the discussions if you have ideas for missing features.

Related libraries

Other SVG related projects

Credits