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.
Try the demo instantly
Loads a 200×200 gradient PNG — no upload needed
Drop image file or click to browse
PNG, BMP, WebP, JPEG — max 50 MB (10 MB on mobile). TIFF opens only in browsers that can decode it (Safari)
Processed in your browser
Your image is decoded in your browser, in a Web Worker, and is not sent to a StegoToolkit server. Basic usage analytics record coarse facts such as file type and size range, never the image or your payload. Output is always a lossless PNG.
How to Hide a Message in an Image (5 steps)
- Upload a PNG, BMP, WebP or JPEG image as your carrier (TIFF only in Safari; up to 50 MB, 10 MB on phones). The result is always saved as a PNG.
- Enter the secret message or attach a file to hide.
- Choose an algorithm — Adaptive LSB is the default; Standard and Forensic modes add Basic LSB, Custom LSB, DCT and Spread Spectrum.
- Optionally set a password for AES-256-GCM encryption.
- Click Encode, then download the stego PNG.
Image Steganography Methods — Algorithm Comparison
| Method | Speed | Capacity | Best For |
|---|---|---|---|
| Basic LSB (1-bit) | ⚡ Fast | Pixels × 3 ÷ 8 bytes (about 180 KB for 800 × 600) | Lossless transfer of PNG/BMP files; the simplest method for CTF-style extraction |
| Adaptive LSB | ⚡ Fast | At least the Basic LSB figure; more when the image has strong edges (2 bits there) | Default. Same lossless-transfer limits as Basic LSB |
| Custom LSB (1–8 bit) | ⚡ Fast | Pixels × 3 × bit depth ÷ 8 bytes (about 720 KB at 4 bits, 800 × 600) | Large payloads, or reading a CTF image that used a known bit depth |
| DCT Domain | 🐢 Slower | Width ÷ 8 × height ÷ 8 × 2 bits (about 1.8 KB for 800 × 600) | Experimental. Recovered only after JPEG quality 100 in our tests |
| Spread Spectrum | ⚡ Fast | At most about 1.2 KB, whatever the image size | Short messages that must survive JPEG conversion (recovered down to quality 60 in our tests); adds visible noise |
What Hiding Data in an Image Actually Changes
A decoded image is a grid of pixels, and each pixel is three numbers (red, green, blue) from 0 to 255. Least-significant-bit (LSB) steganography overwrites the lowest bit of some of those numbers with your message, so a colour value moves by at most 1 out of 255 at one bit per channel. This tool also offers two methods that work on frequency or noise patterns instead (DCT and Spread Spectrum), which behave very differently, as the tables below show.
Your image is decoded in the browser, changed in memory, and saved as a PNG. PNG is lossless, so every changed value stays exactly as written until someone converts the file to a lossy format such as JPEG. The Extractor on this site reads what this Hider writes; other tools use other layouts.
Which Algorithm Should You Choose?
Use Adaptive LSB (the default) or Basic LSB when the PNG will travel as a file: email attachment, USB, a download link, a CTF challenge. They hold the most data and were read back byte for byte in every test. They are also the methods steganalysis tools check first, and neither survives a JPEG conversion: in our tests LSB data was lost at every JPEG quality from 100 down to 75.
Use Custom LSB when the payload is large, or when you need an exact bit depth. A 4-bit change can move a colour value by up to 15 out of 255, and on a smooth carrier the whole-image PSNR falls to about 32 dB when the image is full (see the measured table), which is visible in flat areas.
Use Spread Spectrum (Forensic mode) only for short messages that have to survive a JPEG conversion. It was recovered after JPEG quality 100, 90, 75 and 60 in our tests, but it holds at most about 1.2 KB and it adds visible noise: about 41 dB PSNR for a 29-byte message and about 25 dB when full. DCT is available but experimental: it was recovered only at JPEG quality 100 and lost at 90 and below, so it is not a safe choice for photos that will be re-compressed.
Capacity: What Fits in an Image
Capacity depends on the image's pixel dimensions and the algorithm, not its file size. Basic LSB holds width × height × 3 ÷ 8 bytes, minus a 4-byte length header. The tool then subtracts what it adds to your payload: a 1-byte filename frame (more when you hide a named file), 48 bytes if you set a password (the encryption wrapper's own 4-byte length, 16-byte salt, 12-byte IV and 16-byte authentication tag; this is separate from the image's 4-byte length header), and for Reed-Solomon a 16-byte header plus 10, 20 or 30 parity bytes per 223-byte block.
The capacity bar and the Encode button use the same function as the encoder, and the encoder itself refuses an oversize payload with a "Payload too large" message instead of writing part of it. This is tested at the exact limit and one byte over for every algorithm, with and without a password and Reed-Solomon (npm run test:unit:image). Adaptive LSB's bar shows the Basic LSB figure as a safe floor; an image with strong edges can hold more.
What Gets Written
Every LSB method writes a 4-byte big-endian length, then your payload bits, most significant bit first, into the red, green and blue values in file order (or in a shuffled order when you set a seed). Alpha is never changed. There is no signature or marker, which is why the Extractor has to be told, or has to guess, the bit depth and channels.
DCT and Spread Spectrum work differently; each algorithm is described once, step by step, in the expandable "How Each Algorithm Works" list above, including how DCT forces coefficient signs and how Spread Spectrum adds and correlates a pseudo-random pattern.
Seed, Password and Error Correction
The seed (Forensic mode) is a number from 0 to 999,999,999 that changes the order in which pixels (LSB methods) or noise values (Spread Spectrum) are used, so the same seed is needed to read the data. It is not a secret and does not encrypt anything: a billion values can be tried by a program. DCT ignores the seed. The password is what protects the content.
Reed-Solomon (Forensic mode, RS-10, RS-20, RS-30) is a real Reed-Solomon code over GF(2^8): 10, 20 or 30 parity bytes per 223-byte block repair up to 5, 10 or 15 changed bytes in that block. It repairs a few scattered edits. It does not rescue an image that was converted to JPEG, which changes most pixels, and damage beyond the limit is reported rather than silently accepted, although a very small chance remains that heavy damage decodes to wrong data, so pair it with a password when certainty matters.
How Strong Is the Encryption?
If you set a password, the payload is encrypted before it is hidden, in your browser, with the Web Crypto API. The cipher is AES-256 in GCM mode. The 256-bit key is derived from your password with PBKDF2 using HMAC-SHA-256 and 100,000 iterations. Every encryption generates a fresh random 16-byte salt and a fresh random 12-byte IV with the browser's cryptographically secure random generator (crypto.getRandomValues), so encrypting the same message twice gives different bytes. The stored layout is a 4-byte length, the salt, the IV, then the ciphertext followed by a 16-byte authentication tag — 48 bytes added in total. The tag means a wrong password, or any change to the ciphertext, makes decryption fail instead of returning garbage.
These are standard, widely used primitives, but this implementation has not had an independent audit, and using them does not make the system unbreakable. Their limits matter. Anyone who finds the hidden data can copy the ciphertext and try passwords against it offline, so your password is the real defence: use a long random passphrase, not a word or a date. The key derivation uses 100,000 PBKDF2-HMAC-SHA-256 iterations. This is below OWASP's commonly cited 600,000-iteration recommendation for password storage. That recommendation is not a direct requirement for this file-encryption format, but the lower count makes a strong, unique password especially important. The iteration count is fixed in the code and is not written into the file, so raising it requires a new, versioned format so that files already made can still be opened.
Encryption hides what the data says, not that it exists, and it does not hide the length: AES-GCM ciphertext is the same length as the plaintext, and the encrypted layout adds a fixed 48 bytes of overhead: its own 4-byte length field, the salt, the IV and the authentication tag, separate from any length or framing the tool puts around it. No padding is added. There is no key file and no way to recover a forgotten password. We have not measured key-derivation time on phones or older devices, so very large batches or slow devices may take noticeably longer per file. The tool is intended for educational and personal use; do not rely on it as the only protection for sensitive information, or against a well-resourced adversary.
Formats, Size Limits and Transparency
PNG, BMP, WebP and JPEG carriers are accepted, up to 50 MB (10 MB on phones). TIFF is listed by the file picker but only opens in browsers that can decode it: in our check a TIFF decoded in Safari (WebKit) and failed in Chromium and Firefox. Animated GIF is not accepted. The output is always a PNG, even when the carrier was a JPEG; hiding data in a JPEG carrier therefore gives a PNG (usually much larger than the JPEG) that still loses its data if converted back to JPEG.
The PNG is written through the browser's canvas. Browsers may not keep the colour values of fully transparent pixels exactly, so data written into transparent areas could be damaged. We have not measured this; use an opaque image to be safe. Alpha itself is never used to carry data.
Detectability
Changing the lowest bits leaves statistical traces that tests such as chi-square, RS analysis and sample pairs can detect, especially when the image is nearly full. Writing only a little (the result screen shows the share of capacity used) and using a smooth-to-textured natural photograph both help against a simple test; neither guarantees that a detection tool will miss it. We have not run this tool's output against published steganalysis benchmarks, so the pages do not claim a detection rate. The Steganography Detector on this site runs four of those tests on any image so you can check the result yourself.
Capacity Examples (computed by the tool's own functions)
Raw capacity is what the algorithm can embed after its 4-byte length header. Usable is the largest payload that fits once the filename frame (and, for the last two columns, the 48-byte password overhead or Reed-Solomon RS-10 parity) is added. Sizes are in bytes. The boundary is tested at 160 × 160 pixels; the larger sizes use the same function.
| Image and algorithm | Raw capacity | Usable, no password | With password | With RS-10 |
|---|---|---|---|---|
| 800 × 600, Basic LSB 1-bit | 179,996 B | 179,995 B | 179,947 B | 172,249 B |
| 800 × 600, Custom LSB 2-bit | 359,996 B | 359,995 B | 359,947 B | 344,529 B |
| 800 × 600, Custom LSB 4-bit | 719,996 B | 719,995 B | 719,947 B | 689,069 B |
| 800 × 600, DCT | 1,871 B | 1,870 B | 1,822 B | 1,774 B |
| 800 × 600, Spread Spectrum | 1,246 B | 1,245 B | 1,197 B | 1,169 B |
| 1920 × 1080, Basic LSB 1-bit | 777,596 B | 777,595 B | 777,547 B | 744,199 B |
| 1920 × 1080, DCT | 8,096 B | 8,095 B | 8,047 B | 7,729 B |
| 1920 × 1080, Spread Spectrum | 1,246 B | 1,245 B | 1,197 B | 1,169 B |
Measured Image Quality (PSNR)
PSNR compares the original and the changed pixels; higher means a smaller change. Measured on one 900 × 700 smooth graphic (a desktop wallpaper crop) with printable pseudo-random payloads, so treat it as an example, not a promise for every image. We have not measured a set of real photographs. A rule of thumb is that above about 40 dB differences are hard to see, but it depends on the picture.
| Algorithm | 29-byte message | Half full | Full |
|---|---|---|---|
| Basic LSB 1-bit | 89.5 dB | 54.2 dB | 51.1 dB |
| Adaptive LSB | 86.0 dB | 53.6 dB | 50.5 dB |
| Custom LSB 4-bit | — | 34.4 dB | 31.7 dB |
| DCT | 68.8 dB | 50.3 dB | 46.9 dB |
| Spread Spectrum | 41.0 dB | 27.8 dB | 24.6 dB |
Does It Survive Conversion to JPEG? (our test)
Each algorithm hid a 29-byte message in a synthetic 800 × 600 photo-like image, the PNG was converted to JPEG with the macOS system encoder at the quality shown, converted back, and the Extractor's decoder was run with the right settings. Qualities 100, 90 and 75 gave the same pattern on four different carriers and with a 300-byte message as well; quality 60 was run on one carrier only. Repeat it with npm run test:codec:image. Other encoders (phones, social networks) were not tested, and none of this holds for a different message length or carrier.
| Algorithm | Quality 100 | Quality 90 | Quality 75 | Quality 60 |
|---|---|---|---|---|
| Basic / Adaptive / Custom LSB | lost | lost | lost | lost |
| DCT | recovered | lost | lost | lost |
| Spread Spectrum | recovered | recovered | recovered | recovered |
Examples
Input: A 100 × 100 image and a 40-character text message, Basic LSB, no password
Result: Accepted. Capacity is 100 × 100 × 3 ÷ 8 − 4 = 3,746 bytes; the message plus its 1-byte frame is 41 bytes. The decoder returned all 40 bytes unchanged in the unit test.
Meaning: A short message uses a tiny fraction of the image. The 41 payload bytes and the 4-byte length use the first (41 + 4) × 8 = 360 colour values; some of them already hold the right bit, so fewer actually change.
Input: An 800 × 600 image, Basic LSB, a file of exactly 179,995 bytes, no password
Result: Accepted and read back exactly. 179,996 bytes is refused with "Payload too large for LSB on this image".
Meaning: The limit is the capacity bar's number, not an estimate. The same boundary test passes for every algorithm at 160 × 160.
Input: The same image and a 179,947-byte file with a password
Result: Accepted; one more byte is refused. The password adds 48 bytes: a 4-byte length, a 16-byte salt, a 12-byte IV and a 16-byte authentication tag (measured on the real output: 0, 1, 40 and 500-byte payloads all gain exactly 48).
Meaning: Encryption costs a fixed 48 bytes, not a percentage.
Input: A 29-byte message with Spread Spectrum, seed 42, then the PNG converted to JPEG at quality 75
Result: Recovered exactly with seed 42 in our macOS test. The same PNG hidden with Basic LSB was lost at quality 75.
Meaning: Spread Spectrum can outlive a JPEG conversion; the price is visible noise (PSNR about 41 dB) and a 1.2 KB limit.
How the Hider Works
1. Decode the carrier
The browser decodes your image to raw pixels in a Web Worker. Nothing is uploaded.
2. Prepare the payload
A 1-byte frame (plus the file name when you hide a file) is added, then optionally AES-256-GCM encryption, then optional Reed-Solomon parity.
3. Check it fits
The final byte count plus the 4-byte length is compared with the algorithm's capacity. If it does not fit, encoding stops with a "Payload too large" message.
4. Embed
LSB methods overwrite low bits of R, G and B; DCT changes coefficient signs in the red channel; Spread Spectrum adds a pseudo-random pattern. Alpha is never changed.
5. Measure and save
The tool computes PSNR and histograms against the original and saves the pixels as a PNG for download.
What the results mean
| Result | What it means | What to do |
|---|---|---|
| PSNR above about 50 dB | A very small change (typical of Basic or Adaptive LSB at modest fill) | Fine for most uses; it says nothing about whether a detection tool would find the data |
| PSNR 30–40 dB | A larger change, typical of high bit depths or a full Spread Spectrum payload | Compare the original and encoded images; consider a larger image or a shorter payload |
| Share of capacity used above 40% | The image is close to full | A fuller image is easier to detect statistically; use a larger carrier |
| Refused: Payload too large | The payload plus overhead is larger than the algorithm can embed | Use a larger image, a higher bit depth, a shorter payload, or remove the password or Reed-Solomon |
| Output is a PNG | The tool always writes a lossless PNG | Send it as a file; converting it to JPEG destroys LSB data |
Limitations
- The output is always a PNG. Converting it to JPEG destroyed all LSB data and all DCT data below quality 100 in our tests; only Spread Spectrum was recovered, and only for a short message on the carriers we tried.
- We tested JPEG conversion with one encoder (the macOS system encoder). Social networks and phone apps use other encoders and may resize or strip the image; none was tested.
- Spread Spectrum needs the same seed at the Extractor and a photograph with natural texture; on an image of pure random noise it does not read back reliably (0 of 10 in our unit test).
- TIFF carriers open only in browsers that can decode TIFF (Safari in our check). Animated images are not supported.
- PSNR is a measure of how far the pixels moved, not of detectability. LSB changes can be found by statistical tests even when the picture looks identical.
- Fully transparent pixels may not keep their colour values when the PNG is written through the canvas (not measured); prefer opaque carriers.
- Steganography hides that a message exists; it is not encryption. Without a password the payload is stored as plain bytes.
Privacy
Your image and payload are processed in your browser, in a Web Worker, and are not sent to a StegoToolkit server. The tool saves nothing to disk or to a database: the only things it stores in your browser are your chosen display mode (localStorage) and a flag that you dismissed the mobile tip (sessionStorage). The image, the payload and the password exist only in page and worker memory while you use the tool; starting over or closing the tab discards them. Page views are counted by Vercel Analytics, which is cookieless. Tool events (the options you choose such as the algorithm, bit depth and error-correction level; the file's type and a size range; and how long processing took) are sent to Google Analytics only if the site has it configured and you accepted analytics cookies. The tool does not pass the image, the payload, a password, the seed number or the filename to analytics, and a filter drops fields with names such as password, payload, data or filename before anything is sent. If you accept cookies, the site may also load advertising and other analytics scripts that are outside this tool's code. As on any website, the host keeps ordinary request logs for loading the page (IP address, URL, browser); because the file is never uploaded, the image, payload and password are not part of any request.
Which Tool Next?
- Image Steganography Extractor — Read back what you just hid
- LSB Embedder — LSB hiding with explicit channel and bit-order control
- PNG Steganography Hider — Hide data in PNG's own chunk structure instead of the pixels
- BMP Steganography Hider — Hide data in an uncompressed BMP
- Steganography Detector — Test whether an image shows signs of hidden data
Frequently Asked Questions
Which image formats can I use as carriers?
PNG, BMP, WebP and JPEG, up to 50 MB (10 MB on phones). TIFF opens only in browsers that can decode it; in our check Safari could and Chromium and Firefox could not. The output is always a PNG. A JPEG carrier is decoded to pixels first, so the result is a PNG, and converting it back to JPEG destroys LSB data.
What algorithm should I choose?
Adaptive LSB is the default and holds the most data for a PNG that will travel as a file. If the image may be converted to JPEG, only Spread Spectrum (Forensic mode) was recovered in our tests, for short messages up to about 1.2 KB, at the cost of visible noise. DCT was recovered only at JPEG quality 100.
Does a 40-byte message fit?
Yes in any image large enough for the algorithm. A 100 × 100 image holds 3,746 bytes with Basic LSB, and a 40-byte message was encoded and read back exactly in the unit test. Spread Spectrum holds at most about 1.2 KB whatever the image size, and DCT about 1.8 KB for an 800 × 600 image.
How does the seed work?
The seed changes the order in which pixels (LSB methods) or noise values (Spread Spectrum) are used, so the same seed is needed to read the data. It has about a billion possible values and is not a secret, so it does not replace a password. DCT ignores it.
What is PSNR and what does the score mean?
PSNR (peak signal-to-noise ratio) measures how far the changed pixels are from the originals, in decibels; higher is a smaller change. On the smooth carrier we measured, Basic LSB gave about 51 dB when the image was full and Spread Spectrum about 25 dB. As a rule of thumb, above about 40 dB differences are hard to see, but it depends on the picture. PSNR does not tell you whether a detection tool would find the data.
Will the hidden data survive if I share the image?
It survives anything that keeps the PNG's pixels unchanged: a file copy, email attachment or the original file from cloud storage. It does not survive conversion to JPEG, which is what most social apps do to photos; we have not tested individual apps. LSB data was lost at every JPEG quality we tried.
Is my data encrypted?
Only if you set a password. Then the payload is encrypted with AES-256-GCM (key from PBKDF2-HMAC-SHA-256, 100,000 iterations) before it is embedded, which adds 48 bytes (4-byte length + 16-byte salt + 12-byte IV + 16-byte tag). Without a password the payload is stored as plain bytes. The seed is not encryption.
Is anything stored or sent?
The image and payload are processed in your browser and are not uploaded. The tool stores only your display-mode preference and a dismissed-tip flag in your browser. Usage events (options chosen, file type, size range, timing) may be sent if you accept analytics cookies; the image, payload, password, seed and filename are not part of them.
Related Tools
Image Steganography Extractor
Extract hidden messages from steganographic image files. Auto-detect mode, bit plane analysis.
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.
Text-in-Image Hider
Hide secret text inside an image with Sequential, Seeded Scatter or Adaptive Edge LSB. Shows PSNR and SSIM after encoding, optional AES-256 password, and always saves a PNG.
Text-in-Image Extractor
Extract hidden text from images. Auto-Detect tries 11 common LSB settings; manual mode, bit plane viewer, chi-square pre-scan, CTF flag detection and an optional AES-256 password.