SVG Steganography Hider
Hide data in vector graphics using 5 XML-native embedding methods (comment, metadata, data attributes, float-coordinate LSB, colour LSB). Optional AES-256-GCM. Processed in your browser, not uploaded.
Try the demo instantly
Loads a sample logo SVG — no upload needed
Drop SVG file here, or click to browse
Supports: .svg (any valid SVG/XML file) · Max 20 MB
Processed in your browser
Your SVG is processed in this browser tab and not sent to a server. Usage statistics may record which options were used, never your file.
How to hide data in an SVG (5 steps)
- Upload your SVG file as the carrier
- Type your secret message or upload a file to hide
- Choose an embedding method (Quick mode uses Metadata; Standard and Forensic add the others)
- Add a password to encrypt the payload (optional)
- Click Encode — download your stego SVG
5 SVG Embedding Methods Compared
| Method | Capacity | Visibility and survival | Best For |
|---|---|---|---|
| XML Comment | 2 MiB policy cap | Visible in View Source; removed by SVGO defaults | Quick demos |
| Metadata | 2 MiB policy cap | Visible in View Source; removed by SVGO defaults | Standard use |
| Data attributes | 100 stored bytes per eligible element (total = elements × 100) | Visible in View Source; survived SVGO defaults (measured) | Web dev SVGs |
| Color RGB LSB | 1 bit per hex colour byte (3 bytes per #rrggbb) | Changes existing colour values; survived SVGO defaults on an illustration fixture, lost on a flat-icon fixture whose colours SVGO shortens | Illustration SVGs with many different colours |
| Float coord LSB | 1 bit per coordinate with 4+ decimals | Changes existing numbers; removed by SVGO defaults (it rounds coordinates) | Path-heavy SVGs |
SVG Steganography: What This Tool Does
An SVG file is XML text, so there are several places to put extra data in it without drawing anything: a comment, a metadata element, extra attributes, or tiny changes to numbers the drawing already contains. This tool hides your message in one of five such places, or in several at once, and the Extractor on this site reads it back. Everything runs in your browser.
The five methods are XML Comment, Metadata, Data attributes, Color RGB LSB and Float coordinate LSB. The first three add identifiable text to the SVG source, so anyone who opens the file as text can see that something extra is there. The last two instead change numbers that are already in the file, so nothing new appears in the source, but the changes can be found by comparing with the original or by statistical analysis. None of them is encryption: add a password to encrypt the message with AES-256-GCM before it is hidden.
Hiding a message in an SVG that already holds an earlier message from this tool replaces the earlier message for the methods you choose. Open the Extractor page to read a file back, or the PDF, Image and Text Hiders to hide data in other kinds of carrier.
What Changes in the File
XML Comment adds one comment, <!--STGDATA:…-->, just before the closing </svg>. Metadata adds one element, <metadata id="stgmeta">, right after the opening <svg> tag. Both hold the message as base64 text. Data attributes adds data-stg-N attributes (each holding up to 100 bytes of stored data) to existing shape, group, text and image elements, plus one data-stgc attribute on the <svg> element.
Color RGB LSB changes the last bit of the red, green and blue byte of each fill="#rrggbb" and stroke="#rrggbb" value, so a colour channel changes by at most 1 out of 255. Float coordinate LSB sets the fourth decimal digit of each number with four or more decimals inside d="…" path data to 0 (bit 0) or 5 (bit 1), so a coordinate moves by at most 0.0009. Only that one digit is overwritten: the sign, any digits after the fourth (-12.34567 becomes -12.34557) and numbers with fewer than four decimals are left as they were. Three-digit colours, named colours, rgb() colours and shorter numbers are not used and are not touched.
In our tests nothing else in the file changes: with Float coordinate LSB only the d="…" values differ, with Color RGB LSB only the fill and stroke hex values differ, and comments, CDATA sections, <script> and <style> text are left as they were. The picture is almost, not exactly, the same after the two number-changing methods (we did not compare rendered pixels). If the file's root is written as <svg …/> it is rewritten as <svg …></svg> so there is a place for the data.
Copies for Several Recipients
After a message is hidden, the result page has a Watermark Batch Export section. Enter one recipient per line and the tool makes one SVG per recipient, each hiding a different ID (the Metadata method is used), and gives you a ZIP of the copies plus a watermark_keys.json file that maps each ID to its recipient. When the embedded ID is still present in a copy, the Extractor can use watermark_keys.json to tell you which recipient it was made for; the key file alone cannot identify a copy whose ID has been removed. If a copy cannot be made, for example because the SVG cannot hold the tag, that recipient is left out of the ZIP and listed instead, so the number of files can be lower than the number of recipients. This only identifies a copy while the hidden data is still in the file: SVGO's default settings remove Metadata.
Choosing a Method
Quick mode uses Metadata: it needs nothing special in the SVG and has the largest capacity (a fixed 2 MiB cap on the stored data; Comment has the same cap separately). It is also the easiest to find and the first thing SVGO's default settings remove. Standard and Forensic mode add Data attributes, Color RGB LSB and Float coordinate LSB. If the file will be run through an optimizer, the SVGO table below is the evidence we have: Data attributes survived on both test files, Color RGB LSB on one of the two.
Forensic mode lets you select two or more methods at once; the full message is then stored in every selected layer, and the Extractor needs only one of them to survive. It also adds Reed-Solomon error correction (repairs a few changed bytes, not removed content), a bit-order seed for the two number-changing methods, and the two Plausible Deniability options. Capacity is set by the smallest chosen layer.
Capacity by Method (Computed by the Tool)
Largest message in bytes for a generated 1,000-path illustration (each path has four numbers with 5 decimals, a #rrggbb fill and a #rrggbb stroke), computed by the tool's own capacity function. The 8-byte frame, the 48 bytes a password adds and Reed-Solomon parity (RS-10) are all counted, and a message of exactly this size is accepted while one byte more is refused. XML Comment and Metadata each hold up to 2,097,152 bytes of stored data whatever the file (the two caps are separate); Data attributes are limited by this tool to 100 bytes of stored data per eligible element.
| Method | Raw capacity | No password | Password | RS-10 | Password + RS-10 |
|---|---|---|---|---|---|
| XML Comment | 2,097,152 B | 2,097,144 B | 2,097,096 B | 2,007,118 B | 2,007,070 B |
| Metadata | 2,097,152 B | 2,097,144 B | 2,097,096 B | 2,007,118 B | 2,007,070 B |
| Data attributes | 100,000 B | 99,992 B | 99,944 B | 95,676 B | 95,628 B |
| Color RGB LSB | 750 B | 742 B | 694 B | 686 B | 638 B |
| Float coordinate LSB | 500 B | 492 B | 444 B | 446 B | 398 B |
Where Each Method Stores Data
| Method | Where | What changes | Visible in View Source? |
|---|---|---|---|
| XML Comment | A comment before </svg> | One added comment (base64) | Yes |
| Metadata | A <metadata id="stgmeta"> element after <svg …> | One added element (base64 in CDATA) | Yes |
| Data attributes | data-stg-N on existing elements, data-stgc on <svg> | Added attributes (100 stored bytes each, shown as 136 base64 characters) | Yes |
| Color RGB LSB | Last bit of each #rrggbb byte in fill and stroke | A colour channel changes by at most 1 of 255 | Only as slightly different colour values |
| Float coordinate LSB | Fourth decimal digit of numbers in d="…" | Digit set to 0 or 5: a coordinate moves by at most 0.0009 | Only as slightly different numbers |
What Survives SVGO (Default Settings)
Measured with SVGO 3.3.2, default preset, on two generated 120-path files (`npm run test:measure:svg-svgo`, needs SVGO installed outside the repo): an illustration with cubic paths, 4-decimal coordinates and many different #rrggbb colours, and a flat icon with integer or half-step coordinates and a palette of ten colours. A 13-byte message was hidden with each method, the file was optimized, and the Extractor's Auto Detect was run on the result. Two files, one SVGO version and one configuration: treat it as an indication.
| Method | Illustration (120 paths) | Flat icon (10 colours) | Why |
|---|---|---|---|
| XML Comment | Lost | Lost | SVGO removes comments |
| Metadata | Lost | Lost | SVGO removes the <metadata> element |
| Data attributes | Survived | Survived | SVGO keeps data-* attributes |
| Color RGB LSB | Survived | Lost | SVGO shortens colours such as #aabbcc to #abc, which drops the hidden bits |
| Float coordinate LSB | Lost | Not possible | SVGO rounds coordinates (and the flat icon has no 4-decimal numbers) |
Examples
Input: A 100-path SVG, the 30-character message "Meet at the old bridge at 9pm.", Metadata, no password
Result: One element of 98 bytes is added after the <svg> tag: <metadata id="stgmeta"><![CDATA[U0dGUwAAAB5NZWV0IGF0IHRoZSBvbGQgYnJpZGdlIGF0IDlwbS4=]]></metadata>. 38 bytes are stored: 8 for the frame plus the 30 message bytes.
Meaning: The base64 starts U0dGUw because the frame begins with the letters SGFS. The Extractor's Auto Detect finds this element and returns the same sentence. Anyone who opens the source sees an odd metadata element, so this is hiding in a quiet place, not secrecy.
Input: The same SVG and message, but Color RGB LSB, then Float coordinate LSB
Result: 38 stored bytes are 304 bits. Color RGB LSB writes them into the last bit of the first 304 of the 600 colour bytes (88 of the 200 fill and stroke values end up different); Float coordinate LSB writes them into the first 304 of the 400 four-decimal slots (76 of the 100 d values end up different).
Meaning: About half of the written bits already match the existing digit, so fewer values change than bits are stored. No colour channel changes by more than 1 and no coordinate by more than 0.0009. The file size does not change.
Input: Hide "FIRST" with XML Comment, then upload the result and hide "SECOND" with XML Comment again
Result: The Extractor returns SECOND, and the file holds exactly one STGDATA comment: the earlier comment from this tool was removed when the new one was written.
Meaning: Before this was fixed the Extractor returned FIRST and the file kept two comments. Data written by other tools is never removed, only this tool's own blocks for the methods you select.
Input: A one-line SVG whose root is self-closing, <svg xmlns="http://www.w3.org/2000/svg" width="1" height="1"/>, hidden with Metadata (1-byte message)
Result: The output is <svg xmlns="http://www.w3.org/2000/svg" width="1" height="1"><metadata id="stgmeta"><![CDATA[U0dGUwAAAAF4]]></metadata></svg>.
Meaning: A self-closing root has nowhere to put a child element, so it is written out as an open and a close tag first. Without that the result would have been invalid XML.
How the SVG Hider Works
Read the SVG as text
The file is read in your browser. No XML parser is needed to hide data: the tool finds the places it can use with text patterns that skip comments, CDATA, scripts and style text.
Prepare the message
Your text or file is optionally encrypted with AES-256-GCM (PBKDF2 key, random salt and IV, 48 bytes added) and optionally given Reed-Solomon parity.
Add the frame
The result gets an 8-byte frame: the letters SGFS and the length. The Extractor uses it to know a payload is present and where it ends. It is not encryption and not a checksum.
Check capacity
The stored size is compared with the smallest chosen method's capacity. If it does not fit, nothing is written and you get both numbers.
Clear and write
This tool's earlier data for the chosen methods is removed, a self-closing root is opened, then each chosen layer is written: comment, metadata, data attributes, colours, coordinates.
Download and verify
You download a new SVG. Verify reads the output back with the Extractor's code, using the first method you selected and no password, and reports how many bytes it found. That confirms the payload is present and has a valid length. It does not confirm that the message is correct: for a password-protected payload it cannot decrypt, so open the Extractor and enter the password to check the recovered content.
What the results mean
| Result | What it means | What to do |
|---|---|---|
| Green summary after encoding | The message was written and the preview shows the encoded SVG as your browser draws it. | Download the file; use Verify if you want a read-back. |
| Payload too large for a method | The stored size (message, 8-byte frame, 48 bytes for a password, parity) is bigger than that method's capacity. | Shorten the message, remove Reed-Solomon, or pick Metadata or Comment. |
| A method is unavailable for this SVG | The file has no eligible content for it: no 4-decimal coordinates for Float, no six-digit fill or stroke colours for Color, none of the eligible elements (path, rect, circle, ellipse, line, polygon, polyline, g, text, image) for Data attributes. | Choose another method; the cards for unavailable methods are greyed out. |
| Verify reports N bytes read back | The Extractor's code found N bytes in the output (for the first selected method only, read without a password). With a password it cannot decrypt here, so it says the data is still encrypted; it has then checked presence and length, not the message. | Open the Extractor, enter the password and compare the text. |
| N copies in the ZIP; M could not be made | Shown after Watermark Batch Export. Some recipients could not be given a copy (for example the SVG cannot hold the tag); they are listed under the button and in watermark_keys.json. | Fix the cause or remove those recipients; the ZIP holds only the copies that were made. |
Limitations
- Nothing here hides the data from someone who opens the source: Comment, Metadata and Data attributes are plain text, and the two number-changing methods can be found by comparing with the original.
- Optimizers and editors can remove or change the data. Only SVGO 3.3.2 with default settings was tested, on two generated files; other versions, configurations, optimizers and editors (Illustrator, Inkscape, Figma) and websites were not tested.
- Reed-Solomon repairs a few changed bytes; it cannot restore a removed comment, element or attribute.
- Gzipped .svgz files are not supported (decompress first), and files above 20 MB are refused.
- The picture is almost, not exactly, unchanged after Color RGB LSB or Float coordinate LSB; rendered pixels were not compared.
- A message stored without a password has no integrity check beyond the length frame: a changed byte is not detected. With a password, AES-GCM detects it.
- File names are not stored. The Extractor offers a hidden file for download with an extension taken from its signature, or .bin.
- Key-derivation time on phones was not measured.
Privacy
The SVG is processed in your browser tab (a Web Worker and the Web Crypto API) and is not uploaded. The preview draws the SVG through a blob: image, which does not run scripts inside the file (checked with an SVG that contains an onload handler and a script). Usage statistics may record which options were used, never the SVG, the message or the password. The hosting provider keeps ordinary request logs for page loads.
Which Tool Next?
- SVG Steganography Extractor — read a message back out of an SVG made here.
- PDF Steganography Hider — for documents instead of vector graphics.
- Image Steganography Hider — for PNG, BMP, WebP and JPG pictures, where the bits live in pixels.
- Text Steganography Hider — for plain text, with look-alike characters and whitespace.
- Whitespace Steganography Hider — for text files, using trailing spaces, tabs and line endings.
Frequently Asked Questions
Will the SVG look different after encoding?
Metadata, comment and data-attribute methods add no drawn content. The LSB methods change numbers: Float Coordinate LSB moves a coordinate by at most 0.0009 and Color RGB LSB changes a colour channel by 1 of 255, which is very small but not zero, so the picture is almost, not exactly, identical (not measured pixel by pixel here).
Is my SVG uploaded to a server?
No. Processing happens in your browser tab; the SVG and payload are not sent to a server. Usage statistics may record which options were used, never your file or payload.
Which method should I use?
Metadata works with any SVG, but SVGO's default settings removed it in our test. Data attributes survived SVGO's default settings in both of our test files; Color RGB LSB survived on an illustration with many colours but was lost on a flat icon with a small palette (SVGO shortens colours such as #aabbcc to #abc), so check your own file after optimizing. Float Coordinate LSB is only worth it for path-heavy files that will not be optimized. In Forensic mode you can select 2+ methods for redundant multi-layer embedding.
Can the hidden data survive copy-paste or re-export?
We ran SVGO 3.3.2 with its default settings over the output of each method (one 120-path illustration, `tests/steganography/svg/svgo-survival.mjs`): Data attributes were readable after SVGO on both test files, and Color RGB LSB on the illustration but not on a flat icon with a shortenable palette; XML Comment, Metadata and Float Coordinate LSB were not (SVGO removes comments and metadata and rounds coordinates). Two files, one SVGO version and one configuration: a different configuration, other optimizers and editors were not tested.
What happens to data already hidden in the SVG, and to the rest of my file?
Hiding a new message with a method replaces what this tool stored earlier with that method, so the Extractor returns the newest one. An <svg .../> root is rewritten as <svg ...></svg> so there is a place for the data, and comments, scripts and style text are left untouched: the LSB methods only edit real fill/stroke and path values.
What does the password do?
With a password the payload is encrypted before it is hidden, in your browser, with AES-256-GCM and a key derived from the password with PBKDF2 (100,000 iterations, random salt and IV; 48 bytes added). A wrong password fails authentication. It does not hide that something is there, there is no recovery for a forgotten password, and the encrypted bytes are not protected against someone copying them and guessing passwords offline: use a long passphrase.
How much data can I hide?
XML Comment and Metadata each have a fixed cap of 2,097,152 bytes on the stored data, which includes the 8-byte frame, 48 bytes for a password and Reed-Solomon parity, so the largest message is a little smaller. When you select several methods the message must fit the smallest of them. Data attributes are limited by this tool to 100 bytes of stored data (the framed, encrypted and parity-extended bytes, not only your message) per element that can carry one, written as 136 base64 characters in each data-stg-N attribute; the total capacity is that figure times the number of eligible elements. Color RGB LSB and Float Coordinate LSB hold one bit per eligible colour byte or per coordinate with four or more decimals, so the capacity bar shows the real figure for your file, and a payload at that figure is accepted while one byte more is refused.
Related Tools
SVG Steganography Extractor
Extract data hidden inside SVG vector graphic files by this site's five methods. Auto-detect, optional AES-256-GCM decryption. Processed in your browser, not uploaded.
Image Steganography Hider
Hide secret messages or files inside PNG, BMP, WebP or JPEG images; the result is saved as PNG. Optional AES-256 encryption, processed in your browser.
Steganography Capacity Calculator
Calculate exact hidden-payload capacity for PNG, BMP, WebP, WAV, FLAC, AIFF and more — plus PSNR and detection risk, all client-side. Links to the right specialist hider/extractor for your file type.