How to svg base64 encoding: size overhead, limits, and optimisation tips
- Step 1Estimate the output before encoding — Bare Base64 ≈ source bytes × 1.333 (rounded up to a multiple of 4 with
=padding). With the prefix on, add a fixed 26 bytes. For JSON, allow a further ~1% for any string escaping (Base64's+and/don't need escaping, but the surrounding JSON does). - Step 2Minify and scrub the source first — Run svg-metadata-scrubber to drop comments/
<metadata>/editor cruft, then svg-pro-minifier to collapse whitespace and shorten numbers. This is the only way to shrink the encoded result — the 33% itself is immovable. - Step 3Encode and read the Size overhead metric — Run the encoder. The result panel's Size overhead is
+N%against your input, prefix included. On a tiny icon with the prefix on it can read +50–70%; turn the prefix off to see the number drop toward +33%. - Step 4Decide if Base64 is still the right call — If the +33% (or more) is too costly for your context, switch tactics: percent-encoding via svg-css-data-uri for CSS, or an external cacheable file for reused assets. Base64 is worth its overhead mainly for JSON, React Native, and PDF use.
- Step 5Check the input against your tier cap — Free encodes up to 5 MB, Pro up to 50 MB, Developer up to 2 GB per job. Over the cap, the run is blocked with an explicit message — it won't truncate. 5 MB is already vast for vector art, so most users never approach it.
- Step 6Watch the destination's practical ceiling — Browsers handle multi-MB data URIs, but CSS parse time and JS string memory are the real limits. Keep individual inline Base64 SVGs well under 100 KB; for bigger, prefer an external file.
Size after encoding
Bare Base64 ≈ source × 1.333 (padded to a multiple of 4). The data: prefix adds a fixed 26 bytes — a big relative cost on tiny icons, negligible on large ones.
| Source SVG | Bare Base64 (prefix off) | With prefix (on) | Overhead metric (prefix on) |
|---|---|---|---|
| 100 bytes | ~136 bytes | ~162 bytes | ≈ +62% |
| 500 bytes | ~668 bytes | ~694 bytes | ≈ +39% |
| 2 KB | ~2.67 KB | ~2.69 KB | ≈ +35% |
| 10 KB | ~13.34 KB | ~13.37 KB | ≈ +34% |
| 100 KB | ~133.4 KB | ~133.4 KB | ≈ +33% |
Per-tier input caps and practical ceilings
Input caps are enforced before encoding (the run is blocked, not truncated). Destination ceilings are practical guidance, not hard tool limits.
| Limit | Value | Notes |
|---|---|---|
| Free tier input | 5 MB per job | Blocked above this with an explicit size message |
| Pro tier input | 50 MB per job | Same enforcement, higher cap |
| Developer tier input | 2 GB per job | Effectively unlimited for SVG |
| On-screen preview | First 2,000 chars | Display-only; copy and download give the full string |
| Inline data URI (CSS/HTML) | Keep under ~100 KB | Browsers support far more, but parse time and memory degrade |
| Output line breaks | None | Single unbroken RFC 4648 line — no MIME 76-column option exists |
Cookbook
Worked size calculations and the optimisation order that actually moves the number.
The 33% arithmetic, exactly
Base64 maps 3 input bytes to 4 output characters, then pads the last group to a multiple of 4 with = characters. That's the whole story for the bare string.
Formula: ceil(n / 3) * 4 (n = source bytes) n = 100 → ceil(100/3)=34 → 34*4 = 136 chars (+36%) n = 99 → ceil(99/3)=33 → 33*4 = 132 chars (+33.3%) n = 3000→ 1000*4 = 4000 chars (+33.3%) The smaller the file, the more padding rounding nudges it above 33%. Large files converge on exactly +33.3%.
Why the prefix makes small icons look bad
The data:image/svg+xml;base64, prefix is a constant 26 bytes. On a 100-byte icon that's a huge relative add; on a 100 KB file it vanishes into the rounding.
100-byte SVG, prefix ON: 136 (base64) + 26 (prefix) = 162 → +62% overhead metric 100 KB SVG, prefix ON: ~136,533 (base64) + 26 = ~136,559 → +33% (prefix invisible) Lesson: for JSON manifests of tiny icons, store bare Base64 (prefix off) and add the prefix once on the client.
Minify first — the only lever that works
You cannot reduce Base64's 33%, but you can reduce the input. Stripping a 4 KB SVG down to 2.5 KB saves ~2 KB in the encoded output (1.5 KB × 1.333).
Raw icon.svg: 4,000 bytes → base64 ~5,336 bytes
After scrub + minify: 2,500 bytes → base64 ~3,336 bytes
Saving: ~2,000 bytes of Base64, purely from removing
1,500 source bytes (× 1.333).
Pipeline: /svg-tools/svg-metadata-scrubber
→ /svg-tools/svg-pro-minifier
→ encodeEstimate the saving before you commit
Use the compression estimator to see how much a minify pass would save, then multiply by 1.333 to project the Base64 win — handy when deciding whether inlining is even viable.
1. Run icon.svg through /svg-tools/svg-compression-estimator → projected minified size, e.g. 4.0 KB → 2.4 KB (40% off) 2. Project Base64 win: saved source 1.6 KB × 1.333 ≈ 2.1 KB smaller encoded 3. If still too big to inline → external file instead.
When +33% tips you to a different method
For a CSS background, percent-encoding is smaller than Base64. For a reused icon, an external file adds zero inline weight. The overhead number is the signal to reconsider.
CSS background, 3 KB SVG: Base64: ~4.0 KB in the stylesheet Percent-encoded: ~3.4 KB ← use /svg-tools/svg-css-data-uri Icon reused on 30 pages: Base64 inline: 30 × ~4.0 KB shipped, no caching External file: one ~3 KB request, cached → far less total
Edge cases and what actually happens
Overhead metric reads well above 33%
ExpectedOn small icons with the prefix on, the metric can read +50–70%. That's the fixed 26-byte data: prefix dominating a tiny payload, plus Base64 padding rounding. Turn the prefix off and the number falls toward +33%. The algorithm never exceeds ~33%; the rest is the prefix and padding.
Expecting a MIME 76-column line-break option
Not supportedThe tool emits a single unbroken RFC 4648 line — there is no MIME-wrap/76-column setting (the old guide's 'Advanced option' claim was wrong). Modern data: URIs and JSON require the unbroken form. If a rare legacy MIME parser needs wrapping, wrap the copied string yourself.
Input over the tier cap
RejectedInputs above 5 MB (free) / 50 MB (Pro) / 2 GB (Developer) are blocked before encoding with File "…" exceeds the … tier per-job limit — the tool never encodes a truncated SVG. If you're near the cap, the SVG is almost certainly carrying embedded rasters or huge path data; minify or split before encoding.
Preview pane looks shorter than the real output
By designThe result <pre> shows only the first 2,000 characters with a (truncated — download for full output) note. This is cosmetic — Copy to clipboard and Download TXT always contain the complete string. Never gauge the true size from the preview; read the Output/Size metrics instead.
Trying to reduce the 33% itself
ImpossibleThe ~33% is a mathematical property of Base64 (3 bytes → 4 chars) — no option changes it. The only way to shrink the output is to shrink the input first with svg-metadata-scrubber and svg-pro-minifier. If you need a smaller encoding entirely, percent-encoding is often smaller for SVG.
Giant inline Base64 slows CSS/HTML parsing
PerformanceA multi-hundred-KB inline Base64 SVG is valid but bloats your CSS/HTML and slows parsing and memory. Keep individual inline data URIs under ~100 KB; above that, serve an external file. The encoder won't warn you — sizing is your call against the destination.
JSON payload bloat from many inlined icons
ExpectedEach Base64 icon adds ~33% over its source to the JSON. A response with dozens of inline icons grows fast. Store bare Base64 (prefix off) to skip the 26-byte prefix per entry, and for large sets consider returning URLs and letting the client fetch cacheable files instead.
Padding characters at the end of the string
CorrectTrailing = (one or two) is normal RFC 4648 padding so the length is a multiple of 4. It's part of a valid string — don't strip it; atob() and standard decoders expect it. Its absence (unpadded Base64) is a different variant some systems use, but this tool always pads.
Frequently asked questions
Why exactly 33% overhead?
Base64 encodes 3 input bytes as 4 ASCII characters — a 33.3% increase by definition. The last group is padded with = to a multiple of 4, which nudges small files slightly higher. Large files converge on exactly +33.3%. It's a fixed property of the algorithm; no setting changes it.
Why does the tool's overhead metric say more than 33%?
Because it includes the data:image/svg+xml;base64, prefix (a fixed 26 bytes) when the checkbox is on, plus Base64 padding. On a small icon that prefix is a large share of the total, so the metric reads higher. Turn the prefix off and it drops toward +33%. The metric is output ÷ input − 1, not the pure algorithmic rate.
Is there a way to reduce Base64 overhead?
Not the 33% itself — that's fixed. You reduce the output only by reducing the input: scrub metadata with svg-metadata-scrubber and minify with svg-pro-minifier before encoding. Every source byte removed is ~1.33 fewer Base64 bytes. For a genuinely smaller encoding, percent-encoding is often smaller for SVG.
What's the maximum input size?
5 MB on the free tier, 50 MB on Pro, 2 GB on Developer — enforced before encoding, so an oversized file is blocked (not truncated). 5 MB is already enormous for vector art; if you're near it, the SVG likely contains embedded rasters or massive path data worth minifying or splitting first.
What's the largest Base64 string a browser can handle?
Browsers support multi-MB data URIs (Chrome handles tens of MB), so the hard limit is rarely the issue. The practical limits are CSS parse time and JS string memory — keep individual inline Base64 SVGs under ~100 KB, and use an external file above that.
Does the tool produce standard RFC 4648 Base64?
Yes — standard RFC 4648, padded with =, on a single unbroken line. There is no MIME-style (76-column) line-break option; the old guide's claim of an 'Advanced' setting for that was incorrect. The unbroken form is exactly what data: URIs and JSON require.
How do I estimate the encoded size before encoding?
Bare Base64 ≈ ceil(bytes / 3) × 4, roughly source × 1.333. Add a fixed 26 bytes if the prefix is on. For JSON, add ~1% for the surrounding string escaping. To project a minify-then-encode result, estimate the minified size with svg-compression-estimator and multiply the saving by 1.333.
Should I store the prefix in a database?
Usually not — store bare Base64 (prefix off) so you don't repeat the 26-byte data:image/svg+xml;base64, string in every row, and let the client add it on render. Across thousands of small icons that prefix adds up. Use a TEXT/MEDIUMTEXT column, since even a small SVG's Base64 exceeds VARCHAR(255).
Does JSON escaping add to the size?
A little. Base64's character set (A–Z a–z 0–9 + / =) needs no JSON escaping itself, but the surrounding JSON structure (quotes, commas, the field name) adds a small fixed cost. Budget ~1% on top of the Base64 size for a typical field. This is far less than the escaping a percent-encoded SVG would need.
Why is my small icon's overhead so much worse than 33%?
Two reasons: the fixed 26-byte prefix is a big fraction of a tiny file, and Base64 padding rounds small inputs up. A 100-byte SVG with the prefix can read ~+62%. For manifests of many tiny icons, store bare Base64 and add the prefix once on the client to avoid paying 26 bytes per icon.
When is the 33% overhead not worth it?
For CSS backgrounds (percent-encoding is smaller — use svg-css-data-uri) and for any reused asset (an external cacheable file adds zero inline weight). Base64's overhead is worth paying for JSON fields, React Native sources, PDF libraries, and email where you can't reference a file.
Does the trailing = matter?
Yes — keep it. The one or two = characters are standard RFC 4648 padding that make the length a multiple of 4; atob() and most decoders expect them. This tool always pads. Stripping the = produces unpadded Base64, a different variant that some decoders reject.
Privacy first
Every JAD SVG tool runs entirely in your browser using the DOM API and Canvas. Your SVG files never leave your device — verified by zero outbound network requests during processing.