How to Optimize SVG in Node.js

·7 min read

There are three practical approaches to SVG optimization in Node.js: using SVGO directly, using the @svg.dog/svgdog SDK, or calling the svg.dog REST API withfetch. Here’s a complete guide to each.

Option 1: SVGO directly

SVGO is the most widely used SVG optimizer and has a full Node.js API. Install it as a dependency:

npm install svgo

Basic usage — optimize a file from disk:

import { optimize } from 'svgo';
import fs from 'node:fs';

const input = fs.readFileSync('icon.svg', 'utf-8');

const result = optimize(input, {
  path: 'icon.svg',      // improves error messages
  multipass: true,       // run until no more improvements
});

fs.writeFileSync('icon.min.svg', result.data);
console.log(`Saved ${input.length - result.data.length} bytes`);

Custom SVGO config

SVGO is configured per-invocation or via svgo.config.js. A common pattern is to keep IDs for SVGs that are referenced by CSS or JavaScript:

const result = optimize(input, {
  multipass: true,
  plugins: [
    {
      name: 'preset-default',
      params: {
        overrides: {
          // Keep IDs — needed when CSS targets SVG elements
          cleanupIds: false,
          // Keep viewBox — needed for responsive scaling
          removeViewBox: false,
        },
      },
    },
  ],
});

Option 2: @svg.dog/svgdog SDK

The official Node.js SDK wraps the svg.dog API with TypeScript types and a clean interface. Install it:

npm install @svg.dog/svgdog

Optimize a file:

import { optimize } from '@svg.dog/svgdog';
import fs from 'node:fs';

const result = await optimize(fs.readFileSync('icon.svg'), {
  apiKey: process.env.SVGDOG_API_KEY,
});

fs.writeFileSync('icon.min.svg', result.svg);
console.log(`Saved ${result.savingsPercent.toFixed(1)}%`);

The SDK handles multipart encoding, error handling, and response parsing. It returns a typed result with svg, originalSize, optimizedSize, andsavingsPercent.

See the full SDK reference in the API documentation.

Option 3: Fetch API (no dependencies)

Node.js 18+ has a built-in fetch. You can call the svg.dog API directly without installing any SDK:

import fs from 'node:fs';

async function optimizeSvg(inputPath, outputPath) {
  const form = new FormData();
  form.append('file', new Blob([fs.readFileSync(inputPath)]), 'icon.svg');

  const res = await fetch('https://api.svg.dog/v1/optimize', {
    method: 'POST',
    headers: { Authorization: `Bearer ${process.env.SVGDOG_API_KEY}` },
    body: form,
  });

  if (!res.ok) throw new Error(`API error: ${res.status}`);

  const buffer = await res.arrayBuffer();
  fs.writeFileSync(outputPath, Buffer.from(buffer));

  console.log(`Savings: ${res.headers.get('x-savings-percent')}%`);
}

await optimizeSvg('icon.svg', 'icon.min.svg');

Optimizing multiple files

For folders of SVG files, run in parallel with a concurrency limit:

import { optimize } from 'svgo';
import fs from 'node:fs';
import path from 'node:path';

const icons = fs.readdirSync('./icons').filter(f => f.endsWith('.svg'));

let saved = 0;
for (const file of icons) {
  const full = path.join('./icons', file);
  const input = fs.readFileSync(full, 'utf-8');
  const result = optimize(input, { multipass: true });
  fs.writeFileSync(full, result.data);
  saved += input.length - result.data.length;
}

console.log(`Total saved: ${(saved / 1024).toFixed(1)} KB`);

For larger pipelines, see batch SVG optimization.

Which approach to choose

ApproachWorks offlineAlways latest SVGOTypeScript types
SVGO directYesNo (pin version)Yes
@svg.dog/svgdogNoYesYes
fetch APINoYesManual

Use SVGO directly when you need offline builds or fine-grained plugin control. Use the SDK or API when you want zero-maintenance optimization that’s always up to date.

Next steps

Once you have optimization working in Node.js, consider adding it to your CI/CD pipeline so it runs automatically on every pull request.

Optimize SVGs instantly — no setup needed

500 free optimizations per month. No credit card required.

Get a free API key →