ROT13 is a Caesar cipher with a fixed shift of 13 positions applied to the 26-letter Latin alphabet, and it is a Caesar shift that is its own inverse — applying ROT13 twice to any text recovers the original letter-for-letter. The transform rotates every ASCII uppercase letter A–Z by exactly 13 slots so A becomes N, B becomes O, M becomes Z, and N cycles back to A; lowercase a–z follows the same pattern independently with a remaining lowercase. Because 26 ÷ 2 = 13, the two halves of the alphabet swap perfectly, which is why the same single operation encodes and decodes. The transform is deliberately narrow: only ASCII A through Z and a through z are touched. Digits, punctuation, spaces, line breaks, accented Latin letters such as é, Greek, Cyrillic, Arabic, CJK ideographs, and emoji surrogate pairs are preserved code-unit for code-unit. A browser-based ROT13 Encoder Decoder applies this substitution in place inside the active tab, reports the number of ASCII letters it changed, and never uploads the input to a remote server.
This plain-English walkthrough unpacks the alphabet math, the preservation rules, the self-inverse property, and the limits you should know before you treat ROT13 as anything more than casual obfuscation.

How the ROT13 Substitution Works Mechanically
The classic ROT13 alphabet mapping defines 26 fixed swaps. The Python standard library publishes this table directly in its rot_13 codec, and a browser-based ROT13 decoder applies it identically for every ASCII letter while preserving the case of each character. Mechanically, each uppercase letter has its code reduced by 65, has 13 added modulo 26, and then has 65 added back; lowercase letters use base 97 instead of 65. That single computation is the entire substitution.
For example, "HELLO" rotates to "URYYB". H is the 8th uppercase letter (0-indexed 7), plus 13 is 20, which is U. E plus 13 is R. The two L letters both become Y, and O becomes B. Nothing else in the string — the quote marks, the spaces, or any other character — would be modified, because ROT13 only acts on ASCII A–Z and a–z.
The official Python codecs documentation confirms this strict behavior, and the CPython rot_13 source supplies the direct alphabet table that any correct implementation cross-checks against.
What Changes and What Stays Unchanged
ROT13 rotates only ASCII letters and preserves every other code unit, which means the transform is safe to run on mixed text without losing structure. Digits 0 through 9 stay exactly as they are. Spaces, tabs, line breaks, NUL, punctuation, and symbols are returned unchanged. Accented Latin letters such as é, ñ, or ü are also preserved because they live outside the A–Z and a–z ranges — for instance, "café" becomes "pnsé", since only the c, a, and f get shifted and the é passes through.
Non-Latin scripts behave the same way. Greek, Cyrillic, Arabic, Hebrew, Devanagari, and CJK ideographs are all preserved as UTF-16 code units. Emoji are kept as their surrogate pairs. A combining sequence such as the letter e followed by U+0301 (combining acute accent) changes only the ASCII e and leaves the combining mark in place, producing the visually correct precomposed-looking output.
This strict preservation matches the Python rot_13 codec and avoids pretending that ROT13 defines rotations for every writing system. Any tool claiming to "rotate accented é" or "shift emoji" is doing more than ROT13 by definition.
Apply and Reverse ROT13 in Three Steps
The whole workflow on a browser-based ROT13 decoder takes three actions: paste, apply, and either copy or reverse.
- Paste text containing any mix of ASCII letters and other characters into the input field. The tool accepts strings up to 1,000,000 UTF-16 code units and rejects empty input before transformation.
- Select Apply ROT13 and review the transformed output together with the count of changed ASCII letters. That count is also the number of code-unit positions whose value changed, since every matched ASCII letter always maps to a different ASCII letter.
- Copy the result if you need the obfuscated text, or apply ROT13 to that result again to recover the exact original string. Re-running clears any previous result, validation error, statistics, copy status, and confirmation timer before publishing the new output.
Why ROT13 Is Its Own Inverse
The self-inverse property is a direct consequence of the alphabet length, not a coincidence. Each ASCII letter has an index between 0 and 25 inside its case. ROT13 computes (index + 13) mod 26. Applying the same transform a second time computes ((index + 13) mod 26 + 13) mod 26, which simplifies to (index + 26) mod 26, which equals index. The letter returns to its starting position, and the case-preserving implementation guarantees the casing matches too.
Because every transformed ASCII code unit is replaced by exactly one ASCII code unit, and every other code unit is preserved, the output length always equals the input length in UTF-16 code units. That 1:1 length rule is what makes "apply twice to recover" work for arbitrary mixed text, including inputs that contain no ASCII letters at all.
For example, the input "ABC123" produces "NOP123". Applying ROT13 to "NOP123" produces "ABC123" again. The digits never moved, and every letter round-tripped through the same single operation.
ROT13 Versus Caesar, ROT47, and ROT18
ROT13 belongs to a family of simple rotations, and it is the most restricted member. The table below compares the four most common variants so you can pick the right one for your text.
| Transform | Alphabet covered | Shift | Self-inverse? | Typical use case |
|---|---|---|---|---|
| ROT13 | ASCII A–Z and a–z only | Fixed 13 | Yes | Casual obfuscation of English text and spoilers |
| Caesar (arbitrary) | ASCII A–Z and a–z | Configurable 1–25 | No | Puzzles and configurable shifting |
| ROT47 | Printable ASCII 33–126 | Fixed 47 | Yes | URLs and code snippets with symbols |
| ROT18 | ROT13 on letters plus ROT5 on digits | 13 + 5 | Yes | Order IDs, sequence numbers, and dates mixed with text |
If you need a configurable ASCII shift rather than a fixed 13, use a dedicated Caesar Cipher Decoder instead. ROT13 does not implement arbitrary Caesar shifts, ROT5, ROT47, or Unicode transliteration; trying to use it for those jobs will silently preserve symbols that the wider transforms would change.
Security Reality: What ROT13 Does and Does Not Do
ROT13 is obfuscation, not encryption. It has no key, the substitution table is public, and anyone who recognizes the rotation can reverse it immediately by applying ROT13 again. There is no confidentiality, no authentication, no integrity protection, no hashing, and no access control. Treat any "ROT13-encrypted password" or "ROT13-secured message" claim as a security failure waiting to happen.
Historically, ROT13 served a narrow social role on early Usenet: obscuring spoilers, punchlines, puzzle answers, or coarse language so a casual reader would not see them by accident. RFC 1855 captures the historical context for that use. The transform is genuinely convenient for hiding spoilers in mixed prose because every letter still looks like a letter, but it never protects anything that needs to stay private.
For real secrets, use an established audited cryptographic system such as AES-GCM, RSA-OAEP, or an HMAC, with a key that an attacker cannot recover. ROT13 has no role in that pipeline. The honest description of the tool is the safest: reversible, self-inverse, public, and not a security boundary.
Related reading: Repeat the Same Result With a ROT47 Encoder Decoder.
Related reading: Vigenere Cipher Decoder Example: A Full Walkthrough.