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.
Drop image or click to browse
PNG, BMP, WebP recommended — max 50 MB (10 MB mobile)
Processed in your browser — your image and text are read and encoded in this browser tab and are not sent to a StegoToolkit server. Page views are counted without cookies; coarse tool-usage facts (such as file size range and the options chosen) are sent to Google Analytics only if it is configured and you accepted analytics cookies. The image, text and password are never included. The result is always saved as a PNG.
How to Hide Text in an Image (4 steps)
- Upload an image (PNG, BMP, WebP or JPEG). A JPEG is read as pixels and the result is always saved as a PNG
- Type your secret message; the capacity bar updates as you type
- Pick a method in Standard mode (Adaptive, Sequential or Scatter) or leave Quick mode on its default; Forensic mode adds channel, bit depth, Reed-Solomon and seed
- Optionally add a password, then click Hide Text in Image and download the PNG
Text-in-Image Encoding Methods — What This Tool Handles
| Method | Technique | Quality | Best For |
|---|---|---|---|
| Sequential LSB | Overwrites the lowest bits of the selected channels, pixel after pixel from the top left | PSNR about 51 dB when the image is full, about 64 dB at 5% full | The simplest layout; full capacity |
| Seeded Scatter | Same bits, but the pixels are visited in a pseudo-random order set by a 32-bit seed | Same PSNR as Sequential at the same fill | Spreading the changes over the image; the Extractor needs the same seed |
| Adaptive Edge | Writes 2 bits in pixels with a strong edge and 1 bit in the others | PSNR about 50 dB when full, about 63 dB at 5% full (slightly below Sequential in our tests) | Putting more of the changes at edges; at least the 1-bit capacity |
| Channel choice | Red, green, blue or all three channels | One channel holds a third of the data of all three | Fewer changed values, or the full capacity |
| Reed-Solomon (optional) | Wraps the data in parity: a 16-byte header plus 10, 20 or 30 parity bytes per 223-byte block | Adds about 4.5%, 9% or 13.5% plus 16 bytes | Repairing a few changed bytes; it does not survive re-saving |
What Hiding Text in an Image Actually Does
Every pixel is stored as three numbers (red, green and blue) from 0 to 255. Changing the lowest bit of one of them moves a colour by 1 out of 255, which is usually hard to see. This tool turns your message into bits and writes them into those lowest bits. In front of the message it writes a 4-byte length, so the Extractor knows how many bytes to read. There is no signature, so the Extractor finds the message by trying settings, checking that the length fits the image, and looking at how the bytes read. A length that fits is not proof that a message exists; unrelated data could in principle pass the length check, which is why the bytes are also judged as text, encrypted data or noise.
The output is always a PNG, because PNG keeps every pixel value exactly. A JPEG you upload is read as pixels and written back as a PNG; saving the result as a JPEG again would destroy the hidden bits.
Which Method Should You Choose?
Quick mode uses Adaptive Edge on all three channels at 1 bit with no error correction. Standard mode lets you choose between Adaptive, Sequential and Scatter. Forensic mode adds the channel, the bit depth (1 to 3), Reed-Solomon and the Scatter seed, plus a separate "Plausible Deniability: Decoy + Real Payload" option: a plain-text decoy message goes in the lowest bit of the red channel and your real message, encrypted with a password, in the blue channel, with no signature in either; without the password only the decoy can be read. It is not undetectable: statistical tools can still flag the changes.
Sequential is the simplest layout. Scatter spreads the same changes over the whole image in an order that depends on a seed. Adaptive writes 2 bits at edge pixels, where small changes are harder to see, and 1 bit elsewhere. Which of these is hardest to detect, or least visible, is not something we have shown: in our measurements Adaptive had a slightly lower PSNR than Sequential at the same fill. Look at the before-and-after view and the figures for your own image.
Capacity: How Much Text Fits
Every capacity figure on this page is the longest message you can type, in bytes of plain text, after the other overhead is taken off. Raw capacity is floor(width × height × channels × bits ÷ 8) bytes. The image stores its own 4-byte length header first, so the room for what is stored is that minus 4. Adaptive is counted at 1 bit per value, the guaranteed minimum; its real capacity is higher because edge pixels carry 2 bits (about 16% higher on average over our seven photo crops). A password then takes 48 more bytes: the encrypted layout is its own 4-byte length field, a 16-byte salt, a 12-byte IV and a 16-byte authentication tag around the ciphertext, which is a separate field from the image's header. For 200 × 150 at 1 bit on all channels that is 11,250 − 4 = 11,246 bytes for a plain message and 11,246 − 48 = 11,198 with a password. Reed-Solomon takes a 16-byte header plus 10, 20 or 30 parity bytes per 223 bytes. The capacity bar and the Hide button use these same numbers, so a message that fits the bar is written in full. The Extractor reads at most 5,000,000 stored bytes (the message plus password and parity overhead), and the Hider applies the same limit to the stored bytes, so with a password the longest message at that limit is 48 bytes shorter.
The table below uses exact byte counts (1 KB = 1,024 bytes would give about 759 KB for 1920 × 1080 at 1 bit). The figures are for the largest message, after the length header, with and without a password.
How Much Does the Image Change?
It depends on how full the image is. We measured PSNR (a standard distortion figure; higher means closer to the original) on seven 800 × 600 crops of two real landscape photographs and averaged them. With the image full, Sequential on all channels at 1 bit scored 51.1 dB and Adaptive 50.1 dB; at 5% full they scored 64.1 dB and 62.8 dB. Two photographs are a small sample, so treat the numbers as a guide. A high PSNR means the numbers moved little. It does not guarantee that nobody can see a difference, and it says nothing about whether a program can detect the change.
After encoding, the tool shows the PSNR and SSIM measured on your own file next to the original, computed over the red, green and blue values. The SSIM is calculated on 8 × 8 blocks of luminance.
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.
The Scatter Seed Is Not a Key
The seed sets the order in which pixels are visited. It is a 32-bit number fed to a simple linear congruential generator, so there are only 2^32 (about four billion) possible seed values and a program can try them all. The seed is not encryption and not a second password: the password is what protects the text. Without the right seed the Extractor reads the wrong pixels, which is a nuisance for someone who does not know it, not a defence.
What the Chi-Square P-Value Means
The number shown is a p-value from a classic chi-square test on pairs of pixel values (2k and 2k+1), calculated per channel from the counts of each pair. Replacing lowest bits with random-looking bits makes the two counts in each pair nearly equal, and then the p-value is close to 1; in the images we tested, unequal pair counts gave low p-values, but this varies with the image. So here a high p-value means that the pair counts look equalised, which is what full replacement by random-looking bits produces. It reacts when the hidden bits look random and fill most of the image. Plain text is not random, and in our test the p-value stayed at 0.000 for a text payload at every fill level, so a low p-value does not mean an image is safe. For random-looking data, such as an encrypted message, at 100% fill the p-value was between 0.861 and 1.000 for Sequential and between 0.946 and 1.000 for Scatter across all channels of the seven photos. Adaptive reached 1.000 on some but stayed at 0.000 on at least one, so it did not reliably trigger the test.
At 60% fill Sequential stayed at or below 0.002 and Adaptive at 0.000, while Scatter reached 0.964 on one photo. That is one test on seven crops of two photographs, so it says nothing general about detection performance. Do not read it as a ranking of how hard each method is to detect by other tools. Treat the number as one diagnostic signal.
Transparent Images
Transparent and semi-transparent pixels can have their colour values altered when a browser reads or saves an image (canvas processing premultiplies colour by alpha), which loses hidden bits placed there. If a cover has any transparent pixel, the Hider fills the transparent areas with white, says so, and saves an opaque PNG. Check the extracted result before relying on it; an opaque image is the safer choice.
Largest Message by Image Size (computed from the tool's own functions)
All channels, no Reed-Solomon. Adaptive is shown at its guaranteed 1-bit minimum.
| Image | 1-bit, no password | 1-bit, with password | 2-bit, no password | One channel, 1-bit |
|---|---|---|---|---|
| 640 × 480 | 115,196 B | 115,148 B | 230,396 B | 38,396 B |
| 1280 × 720 | 345,596 B | 345,548 B | 691,196 B | 115,196 B |
| 1920 × 1080 | 777,596 B | 777,548 B | 1,555,196 B | 259,196 B |
| 4000 × 3000 | 4,499,996 B | 4,499,948 B | 5,000,000 B (limit) | 1,499,996 B |
Measured PSNR by Fill (mean of seven 800 × 600 real-photo crops, all channels, 1-bit)
Random payload bits. Fill is how much of the capacity is used. Sequential and Scatter write the same number of bits, and 1-bit replacement changes a value only about half the time, so their PSNR depends almost entirely on the fill and is nearly the same on any image (our synthetic test cover gave the same 64.1/57.2/53.4/51.1 dB). Adaptive differs a little because it also writes 2 bits at edge pixels.
| Method | 5% full | 25% full | 60% full | 100% full |
|---|---|---|---|---|
| Sequential | 64.1 dB | 57.2 dB | 53.4 dB | 51.1 dB |
| Scatter | 64.1 dB | 57.2 dB | 53.4 dB | 51.1 dB |
| Adaptive | 62.8 dB | 56.1 dB | 52.3 dB | 50.1 dB |
What Common Conversions Do to the Hidden Text (macOS sips, seven real-photo crops)
A 600-byte text hidden at 1 bit on all channels, then the PNG was converted and read back. This tests file conversions, not websites or apps.
| Conversion | Sequential | Adaptive |
|---|---|---|
| PNG re-saved as PNG | 7 of 7 exact | 7 of 7 exact |
| PNG → BMP → PNG | 7 of 7 exact | 7 of 7 exact |
| PNG → TIFF → PNG | 7 of 7 exact | 7 of 7 exact |
| JPEG quality 100 → PNG | 0 of 7 | 0 of 7 |
| JPEG quality 95 → PNG | 0 of 7 | 0 of 7 |
| JPEG quality 75 → PNG | 0 of 7 | 0 of 7 |
| Resized to 90% and back | 0 of 7 | 0 of 7 |
Examples
Input: A 200 × 150 image, Sequential, all channels, 1 bit, a 40-character message, no password
Result: 44 bytes are written (4-byte length + 40) of a capacity of 11,246 bytes
Meaning: It fits easily. The Extractor returns the same 40 characters.
Input: The same image with a password
Result: The capacity for the message falls from 11,246 to 11,198 bytes
Meaning: A password adds 48 bytes to what is stored.
Input: The same image with Reed-Solomon RS-30 and a password
Result: The largest message is 9,832 bytes
Meaning: Reed-Solomon adds a 16-byte header and 30 parity bytes per 223 bytes.
Input: A 4000 × 3000 image at 2 bits on all channels
Result: The largest message is 5,000,000 bytes, not the 8,999,996 the pixels could hold
Meaning: The Extractor reads at most 5,000,000 bytes, so the Hider stops there.
How the Hider Works
1. Read the image
The image is drawn onto a canvas and read as red, green, blue and alpha values. A JPEG is read as ordinary pixels.
2. Prepare the message
Your text is optionally encrypted with AES-256-GCM, then optionally wrapped in Reed-Solomon parity, and given a 4-byte length in front.
3. Choose the pixels
Sequential visits pixels in file order. Scatter shuffles the order with your seed. Adaptive visits them in file order and decides per pixel, from the edge strength of its top six bits, whether to write 1 or 2 bits.
4. Embed
The bits are written most significant first into the lowest bits of the chosen channels, in a Web Worker.
5. Measure and save
PSNR, SSIM and the chi-square p-value are computed against your original and the result is saved as a PNG.
What the results mean
| Result | What it means | What to do |
|---|---|---|
| PSNR | How close the stego image is to your original (red, green, blue values); higher is closer | Below about 40 dB, shorten the message or use a larger image |
| SSIM | A structural similarity score on 8 × 8 luminance blocks; 1 means no structural change | Values very close to 1 are normal |
| Chi-square p-value | From a chi-square test on pairs of pixel values: near 1 when the pair counts look equalised, near 0 when they differ (as in the images we tested); it mostly reacts to random-looking data that fills the image | A low p-value does not mean the image is safe; treat it as one signal |
| Payload density | The share of the capacity your message uses | A fuller image changes more pixels |
| Refused: too large | The message plus password and parity overhead is bigger than the image can hold | Use a larger image, more channels or a shorter message |
Limitations
- Re-saving, resizing or converting the PNG (for example to JPEG) destroys the hidden text. Some messaging and social services do that to photos; we have not tested individual services, so send the PNG as a file and check the received copy with the Extractor.
- Reed-Solomon repairs a few scattered changed bytes. It does not make the text survive re-saving or JPEG conversion.
- LSB steganography can be flagged by steganalysis tools, more easily as the image fills up. The chi-square p-value shown here is one test and stays low for plain text, so it does not prove that an image is safe.
- The Extractor can read at most 5,000,000 bytes, and its Auto-Detect tries 11 fixed settings. A message hidden with Scatter needs the seed; one hidden with other settings needs those settings.
- A cover with transparent pixels is flattened onto white, so the result looks different there; use an opaque cover to avoid that.
- PSNR, chi-square and conversion figures on this page come from seven crops of two real landscape photographs; a larger set of images may give different numbers.
Privacy
Your image, message and password are processed in your browser, in a Web Worker, and are not sent to a StegoToolkit upload server. The image-processing code does not transmit your image or message, and the PNG is created on your device and downloaded from it. Separate site analytics may send limited usage events (the options you choose such as the method, the file's type and a size range, and how long processing took): page views are counted by Vercel Analytics, which is cookieless, and tool events go to Google Analytics only if the site has it configured and you accepted analytics cookies. Those events do not include your image, message, password or filename. If you accept cookies, the site may also load advertising and other analytics scripts that are not part of this tool. Your display mode preference is kept in this browser's localStorage.
Which Tool Next?
- Text-in-Image Extractor — Read back what you just hid
- Image Steganography Hider — Hide text or a file with more algorithm choices
- LSB Embedder — Plain LSB with settings you choose
- Image-in-Image Hider — Hide a picture inside a picture
- Steganography Detector — Test whether an image shows signs of hidden data
Frequently Asked Questions
Will the image look different after encoding?
Often it is hard to notice at 1 bit, but that is not guaranteed. In our tests on seven real-photo crops, Sequential scored 51.1 dB PSNR when full and 64.1 dB at 5% full, and Adaptive 50.1 dB and 62.8 dB. Results depend on the image, the message length and the settings. The result view shows the measured PSNR and SSIM and a before-and-after view for your file.
Why is the output always a PNG?
JPEG compression changes pixel values and would wipe the hidden bits. PNG keeps every value exactly. If you upload a JPEG it is read as pixels and written back as a PNG.
What do Quick, Standard and Forensic mode change?
Quick uses Adaptive Edge on all channels at 1 bit with no error correction. Standard lets you choose Adaptive, Sequential or Scatter. Forensic adds the channel, bit depth (1 to 3), Reed-Solomon, the Scatter seed and the Decoy + Real Payload option.
Is my image uploaded anywhere?
No. The image and message are processed in your browser and are not sent to a StegoToolkit server. Coarse usage facts may be counted if you accept analytics; the image, message and password are never included. See the privacy section above.
What is the scatter seed?
A 32-bit number that sets the pseudo-random order in which pixels are visited. The Extractor must use the same seed. It is not encryption and not a second password, and a program can try all possible seeds, so use a password if the text matters.
Will the hidden text survive sharing?
Only if the receiver gets the exact same PNG file. Resizing, re-saving or converting it to JPEG destroys the text, and some messaging and social services re-compress photos. On real photographs, lossless conversions (PNG, BMP, TIFF) kept the text and JPEG at any quality tested (even 100) destroyed it, as did resizing; see the conversions table above. We could not test what individual websites and apps do to a photo you send them, so send the PNG as a file and check the received copy with the Extractor.
How much text can I hide?
It depends on the image and settings. A 1920 × 1080 image holds 777,596 bytes at 1 bit on all channels and 1,555,196 bytes at 2 bits (the capacity table above has more sizes). A password takes 48 bytes and Reed-Solomon adds a header and parity. Adaptive is counted at its 1-bit minimum and holds a little more. The capacity bar shows the exact limit for your settings.
What does the chi-square p-value mean?
It is the p-value of one statistical test on pairs of pixel values. It rises towards 1 when the hidden bits look random and fill most of the image, and it stays near 0 for plain text, so a low p-value does not mean the image is safe. See the chi-square section above for the figures we measured.
Related Tools
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.
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.
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.
Image Steganography Extractor
Extract hidden messages from steganographic image files. Auto-detect mode, bit plane analysis.