Text steganography is the practice of concealing a secret message inside an ordinary-looking piece of text so that anyone glancing at the cover sentence cannot tell that anything extra is hidden in the document. The trick used by Text Steganography is to insert zero-width Unicode characters into an otherwise normal sentence; those characters have no width in typical fonts, so the sentence still reads the same on screen. Behind the scenes, each UTF-8 byte of the hidden message is expanded into exactly eight invisible bits, an explicit start and end marker frames the payload, and the framed sequence is tucked after the first visible code point of the cover. Reveal mode locates those markers, checks that the bit count is a multiple of eight, validates that the resulting bytes are well-formed UTF-8, and returns both the recovered secret and the restored visible cover. All of the encoding and decoding happens locally in the browser, so neither the cover nor the secret ever leaves your machine, and the tool uses a transparent, reversible convention rather than claiming compatibility with every other steganography website.

text steganography explained
Text Steganography Explained: Zero-Width Unicode Basics

What "text steganography" actually means

Steganography is the broader art of hiding one message inside another carrier so that the existence of the hidden channel is not obvious. A historical example is writing in lemon juice and revealing the words with heat; the paper still looks blank. In computing, the carrier is usually a digital object such as an image, an audio file, a video, or, in the case of text steganography, the characters of a normal-looking sentence. The goal is concealment, not confidentiality: a casual reader should not suspect that anything unusual is present at all, which is why steganography is often described as "hiding in plain sight."

Text steganography is the hardest variant because text has so little visual slack. You cannot subtly tweak pixel values the way you can in a JPEG, and there is no obvious frequency band to bury a signal in. Instead, you have to hide bits in code points that the rendering engine already ignores by default. Modern Unicode reserves a handful of "default-ignorable" code points for exactly this kind of purpose: they participate in the character stream but contribute no glyph and no measurable width in normal layouts. That property makes them the natural place to carry a covert bitstream without changing what a reader sees.

How zero-width Unicode carries a hidden message

Text Steganography uses an explicit, documented convention so that any reader can audit the transformation. The mapping has only four code points, each with a precise role:

RoleCode pointMeaning
Start markerU+2063Invisible separator that opens the framed payload
End markerU+2064Invisible plus that closes the framed payload
Bit value 0U+200BZero-width space
Bit value 1U+200CZero-width non-joiner

Each hidden UTF-8 byte is written as eight bits, most-significant-bit first, so the on-the-wire order matches the byte order readers expect. A small hidden message is therefore a long string of alternating zero-width spaces and zero-width non-joiners sandwiched between two invisible markers. The whole framed sequence is inserted after the first visible code point of the cover, so the structure of the sentence is preserved even though the underlying code-point count has ballooned. According to the Unicode Consortium's Unicode Security Considerations report, default-ignorable code points can be silently dropped during processing, which is exactly the failure mode this tool warns about.

Hide a message inside a cover sentence

The hide flow turns a normal sentence and a separate secret into a single steganographic string that you can paste wherever Unicode round-trips faithfully.

  1. Open the Text Steganography tool and switch to hide mode.
  2. Enter an ordinary cover sentence such as "The meeting is on Thursday." in the visible-text field.
  3. Type a short hidden message in the secret field.
  4. Click generate to embed the eight-bit-per-byte stream inside the cover, framed by U+2063 and U+2064.
  5. Copy the resulting string through a channel that preserves default-ignorable code points.
  6. Reveal the copied string in a second window before sending it anywhere else, to confirm that both the hidden message and the visible cover survive the round trip.

A concrete worked example: the hidden message "Hi" in UTF-8 is the bytes 0x48 and 0x69. 0x48 in binary, most-significant-bit first, is 01001000; 0x69 is 01101001. Each 0 becomes a U+200B and each 1 becomes a U+200C, so the payload inside the markers is sixteen invisible code points in the order 0-1-0-0-1-0-0-0-0-1-1-0-1-0-0-1, framed by U+2063 and U+2064, and inserted after the first character of the cover sentence. The visible sentence stays unchanged; the underlying sequence becomes much longer.

Reveal a message and confirm the cover round-trips

Reveal mode is the verification half of the workflow and it is just as important as hide mode, because transport is where steganography usually breaks.

  1. Paste the exact steganographic string into the reveal field without retyping it, so no characters are dropped or re-encoded along the way.
  2. Run reveal; the tool locates the U+2063/U+2064 frame, validates that every payload character is one of the two bit symbols, checks that the bit count is a multiple of eight, and decodes the resulting bytes as strict UTF-8.
  3. Read the recovered hidden message and the recovered visible cover; both should match the originals byte for byte.
  4. If decoding fails, the most likely cause is that your transport stripped default-ignorable code points; copy the raw code points through a developer-view source viewer and compare them against the original to find which platform mangled the string.

The tool extracts only the first valid framed segment and treats malformed framing as an error rather than guessing, so a corrupted payload will fail loudly instead of decoding to a misleading message. This is exactly the kind of behavior you want from a tool that prefers an honest "could not decode" over a plausible but wrong answer.

Why hidden messages can disappear in transit

Text steganography depends on every invisible code point surviving the journey from sender to receiver. Many everyday platforms do not preserve that. Email gateways may normalize line endings; chat clients and content-management systems often sanitize pasted content and remove default-ignorable characters; social networks are especially aggressive about stripping non-printing code points. Clipboard re-encoders, autocorrect, search indexers, and security scanners can each chew a few characters off the invisible stream. If even a single bit disappears, the payload can become malformed or decode to a completely different byte sequence, and the reader will either see an error or, worse, see a wrong message that looks plausible.

The practical rule is that screenshots and printed copies cannot carry the hidden data at all, because the carrier is the Unicode character itself, not the rendered pixels. You should only send the steganographic string through a channel you have tested end to end. Plain-text editors that preserve Unicode exactly are more likely to retain the payload than rich-text editors that treat pasted input as HTML, strip control characters, or insert invisible formatting of their own. When in doubt, paste the output into reveal mode on the receiving side before relying on the delivery.

Limits, capacity, and what the tool will not do

The hidden message is limited to 10,000 UTF-8 bytes and the cover to 100,000 code points. Those caps exist because every hidden byte becomes eight additional code points plus framing, and unbounded growth would make the DOM unresponsive. Because emoji and non-Latin scripts can occupy several UTF-8 bytes each, the visible character count of the secret can be smaller than the byte limit. The cover cannot already contain this convention's start or end marker, because accepting one would make payload boundaries ambiguous; ordinary zero-width characters outside the framed region remain part of the visible cover and are not interpreted as bits.

Text steganography does not provide confidentiality, authenticity, or integrity. The mapping is documented and easy to detect, and anyone who finds the framed segment can read the message. A character counter, a diff tool, a source viewer, or a Unicode-aware security scanner can expose the hidden code points immediately, which is why this tool is suitable for demonstrations, learning how Unicode can carry non-rendering data, and harmless puzzles, but not for hiding credentials, harmful instructions, personal data, or anything that would violate a platform's rules. For durable data exchange, prefer a visible encoding or an authenticated file format, and treat steganography as one trick in a wider toolkit rather than a security boundary on its own.

Steganography versus cryptography

Cryptography makes a message unreadable to outsiders; steganography makes the existence of the message invisible. The two ideas solve different problems, and the usual advice is to combine them when confidentiality actually matters: encrypt the secret with a reviewed cipher and then optionally steganographically hide the ciphertext. For example, you can encrypt sensitive text with AES Encryption Online and then embed the resulting package inside an innocent cover sentence with Text Steganography. A reader who only sees the cover learns nothing about the secret; a reader who notices the hidden stream still has to break the cipher to read the message. For readers who want to compare this convention against other approaches or experiment with command-line workflows, the zero-width Unicode method guide walks through the same idea in a different format.

Related reading: Convert Text to Hex Code: Pick a UTF-8 Output Format.