How to Optimize SVG in Node.js
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 svgoBasic 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/svgdogOptimize 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
| Approach | Works offline | Always latest SVGO | TypeScript types |
|---|---|---|---|
| SVGO direct | Yes | No (pin version) | Yes |
| @svg.dog/svgdog | No | Yes | Yes |
| fetch API | No | Yes | Manual |
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 →