Your files never leave your device. All processing happens locally in your browser.
How do I hide a secret message inside an image?
Upload a cover image, type your message, and the Image Steganography Tool writes it into the least-significant bits of the picture’s pixels — then downloads a lossless PNG that looks identical to the original. Turn on encryption to seal the message with AES-256-GCM first, so even if someone detects it, the content stays unreadable. To read it back, load the PNG (and the passphrase, if any) and the tool extracts the hidden text. Everything runs in your browser; nothing is uploaded.
LSB embedding in the R/G/B channels — 1 or 2 bits per channel
Optional AES-256-GCM encryption (PBKDF2-SHA-256) so it is hidden AND sealed
Output is always a lossless PNG so the hidden bits survive
Live capacity meter warns if the message will not fit
100% client-side — your image and message never leave the browser
What is
Image steganography (LSB)
Steganography is the practice of concealing a message inside another, ordinary-looking object so that its very existence is hidden. In least-significant-bit (LSB) image steganography, the secret’s bits replace the lowest bit(s) of each pixel’s red, green and blue colour values; because changing the least-significant bit shifts a channel by at most 1/255, the alteration is invisible to the eye. Because it operates at the exact pixel level, the carrier must be stored losslessly (PNG) — any lossy re-compression such as JPEG destroys the hidden data.
No. The cover image is drawn to a canvas and its pixels are read and rewritten in memory; the message and the finished PNG never leave your browser.
The Image Steganography Tool is 100% client-side. Your picture is loaded into a <canvas>, its pixels are read with getImageData, the message bits are written into the least-significant bits locally, and the stego PNG is built and downloaded entirely in-browser. Optional encryption uses the Web Crypto API (AES-256-GCM with a PBKDF2-SHA-256 key and randomness from crypto.getRandomValues). There is no upload, no server, no CDN and no telemetry in the path, and nothing is persisted — close the tab and it is gone.
Hiding is not the same as securing. LSB steganography is concealment; it is detectable by steganalysis and does not encrypt the message unless you turn on encryption.
Steganography hides the existence of a message, but a hidden message is not automatically a secure one. LSB embedding is detectable by well-known statistical steganalysis (RS analysis, chi-square, sample-pair, and tools like StegExpose), and 2 bits/channel is easier to detect than 1. For genuine secrecy, enable encryption so the payload is sealed with AES-256-GCM before it is embedded — then even if someone discovers something is hidden, the content stays unreadable without your passphrase. Treat this as a fun, educational and lightly-protective tool, not a guarantee for high-threat situations.
The message lives in exact pixel bits, so any re-compression, resize, crop, filter or screenshot rewrites the pixels and erases it. PNG is lossless and preserves them.
LSB steganography stores data in the lowest bits of each pixel, so it only survives if the pixels are preserved bit-for-bit. Saving the image as JPEG (or any lossy format), resizing, cropping, applying colour filters, or taking a screenshot re-encodes the pixels and destroys the hidden bits. That is why this tool always exports a lossless PNG — keep and share that exact PNG. Uploading it to platforms that recompress images (many social networks and chat apps do) will usually strip the message.
Roughly (width × height × 3 × bits-per-channel) ÷ 8 bytes, minus a small header. A 1000×1000 image holds about 375 KB at 1 bit/channel; the live meter shows the exact figure.
Capacity depends on the pixel count and the bits-per-channel setting. Each pixel offers three colour channels (red, green, blue), and you store 1 or 2 bits in each, so capacity ≈ (width × height × 3 × bitsPerChannel) ÷ 8 bytes, minus a 10-byte marker/length header (and ~49 extra bytes if you encrypt). For a 1000×1000 image that is about 375 KB at 1 bit/channel or 750 KB at 2. The tool shows a live capacity meter and blocks you if the message will not fit — use a larger image, shorten the message, or raise the bit depth (at the cost of easier detection).
Detailed Explanation
📖How It Works
What the Image Steganography Tool Does
This tool hides a secret text message inside an ordinary image and can reveal it again, entirely in the browser. In HIDE mode the user picks a cover image and types a message; the tool draws the image to a canvas, reads its pixels, and writes the message into the LEAST-SIGNIFICANT BIT(S) of the red, green and blue channels behind a small marker + length header, then exports a LOSSLESS PNG that looks identical to the original. In REVEAL mode it reads a stego PNG’s pixels, auto-detects the bit depth from the marker, and extracts the message. The message can optionally be ENCRYPTED with a passphrase first, so it is both hidden and sealed. Nothing is uploaded.
Hide and reveal secret messages inside images, fully locally
LSB embedding in R/G/B channels at 1 or 2 bits per channel
Optional AES-256-GCM encryption before embedding
Output is always a lossless PNG; reveal auto-detects the bit depth
100% client-side — image and message never leave the browser
⚙️Methodology
How LSB Embedding Works
Each pixel has three 8-bit colour channels (red, green, blue). The lowest bit of a channel changes its value by at most 1 in 255, a shift the eye cannot see, so the secret’s bits are written there. The message is first framed as MAGIC("STEG") + version + a flags byte (recording whether it is encrypted) + a 4-byte big-endian LENGTH + the payload; those bytes are then packed MSB-first, 1 or 2 bits at a time, across the RGB channels (the alpha channel is left untouched so opacity is preserved). On reveal, the tool reads the header at 1 bit/channel and, if the MAGIC marker is not reproduced, retries at 2 bits/channel, so the user never has to remember the setting. When encryption is on, the payload is an AES-256-GCM blob produced by the shared text-crypto engine (PBKDF2-HMAC-SHA-256 key derivation, random salt and IV) rather than raw UTF-8.
Message framed as MAGIC + version + flags + 4-byte length + payload
Bits packed MSB-first into RGB LSBs; alpha channel untouched
Reveal auto-detects 1 vs 2 bits/channel via the marker
Encrypted payloads are AES-256-GCM blobs, not plain text
🔧Technical Details
Local Canvas Pipeline and Capacity
The cover image is loaded into an HTMLImageElement, drawn to an offscreen <canvas>, and its pixels read with getImageData — no worker-to-server, no network. A pure, fully-typed engine (stegoEngine.ts) computes capacity, packs the header, writes and reads the LSBs, and throws a typed StegoCapacityError when a message is too large; the page shows a live meter of used-versus-available bytes and disables hiding when it would overflow. After embedding, putImageData writes the modified pixels back and canvas.toBlob(…, ‘image/png’) produces the lossless download. A side-by-side cover-versus-stego preview demonstrates that the change is visually undetectable. Encryption is delegated to the shared textCryptoEngine so the same audited AES-GCM path is reused rather than reinvented.
getImageData / putImageData on a canvas; no server round-trip
stegoEngine.ts: pure typed capacity, pack, embed and extract
Live capacity meter; over-capacity is blocked with a clear message
Lossless PNG export via canvas.toBlob; side-by-side preview
Encryption reuses the shared textCryptoEngine AES-GCM path
⚠️Limitations
Honest Limitations
Steganography is CONCEALMENT, not encryption. A message that is only hidden is not secure: LSB embedding is DETECTABLE by well-known statistical steganalysis (RS analysis, chi-square, sample-pair, and tools such as StegExpose), and 2 bits/channel is easier to detect than 1. It is also FRAGILE — the payload lives in exact pixel bits, so any re-compression (saving as JPEG), resizing, cropping, colour filtering or screenshotting rewrites the pixels and destroys the hidden data, which is why the carrier must stay a lossless PNG and why many social/chat platforms that recompress uploads will strip it. For real secrecy, turn on encryption so discovery of the hiding still reveals nothing without the passphrase (and a lost passphrase cannot be recovered — there is no backdoor). This is a fun, educational and lightly-protective tool, not a guarantee for high-threat use.
Concealment, not encryption — hidden is not the same as secure
Detectable by RS / chi-square / sample-pair steganalysis (StegExpose)
Destroyed by JPEG re-compression, resize, crop, filter or screenshot
Must stay a lossless PNG; recompressing platforms strip the message
Encrypt for real secrecy; a lost passphrase cannot be recovered
🔒Privacy & Security
Private by Design
Everything happens on your device. The image is a local canvas buffer and the message is React state; the LSB reading and writing, the capacity math, the PNG encoding and any encryption all run in the browser with no upload, no server, no CDN and no telemetry. Because the picture and secret never leave your machine, it is safe to hide genuinely sensitive notes — unlike an online steganography service that would receive your cover image and plaintext. Optional encryption uses the Web Crypto API with randomness from crypto.getRandomValues. Nothing is persisted, so closing the tab erases it; the tool works offline once cached; and the only optional network use anywhere on the site is consent-gated ads, which never see your image or message.
Image and message processed locally; no upload, server, CDN or telemetry
Safe for sensitive notes, unlike online steganography services
Encryption via Web Crypto; randomness from crypto.getRandomValues
Nothing persisted — closing the tab erases everything
Works offline once cached; only optional network use is consent-gated ads
Ways to keep a message private
Approach
What it does
Trade-off
Used here
LSB steganography (this tool)
Hides the message in image pixels
Invisible but detectable; destroyed by recompression
Yes
Encryption alone
Makes content unreadable
Obvious that something is protected; strong secrecy
Optional (combined)
Hide + encrypt (recommended)
Conceals AND seals the message
Best of both; still fragile to recompression
Yes
Online stego service
Hides via a server
Uploads your cover image and plaintext
No — never
Use hiding for plausible deniability and encryption for actual secrecy; combine both for the strongest result, and always keep the carrier a lossless PNG. Everything here runs locally in the browser. As of July 2026.