X Xerobit

ROT13 Decoder — How to Decode ROT13 Encoded Text

ROT13 is a simple letter-substitution cipher that shifts each letter 13 positions. Since it's self-inverse, decoding is identical to encoding. Here's exactly how to decode ROT13.

Mian Ali Khalid · · 5 min read
Use the tool
ROT13 / Caesar Cipher
Encode and decode ROT13 and arbitrary Caesar shifts. Letter frequency analysis. 100% client-side.
Open ROT13 / Caesar Cipher →

ROT13 decoding is the same operation as ROT13 encoding. Apply ROT13 to encoded text and you get the original back. This self-inverse property — applying the transformation twice returns to the start — is the defining feature that makes ROT13 unique among Caesar ciphers.

Use the ROT13 Cipher tool to encode or decode any text instantly.

Why ROT13 is self-inverse

The English alphabet has 26 letters. ROT13 shifts each letter by 13 positions. If you shift by 13 and then shift by 13 again, you’ve shifted by 26 — which is the full alphabet, bringing you back to the start.

A → N → A  (A shifted 13 = N, N shifted 13 = A)
B → O → B
M → Z → M
N → A → N
Z → M → Z

This is the only shift value for which encoding and decoding are the same operation. ROT7 encoding requires ROT19 to decode. ROT13 encoding requires ROT13 to decode.

The ROT13 substitution alphabet

Plain:  A B C D E F G H I J K L M
ROT13:  N O P Q R S T U V W X Y Z

Plain:  N O P Q R S T U V W X Y Z
ROT13:  A B C D E F G H I J K L M

Each letter is swapped with its “partner” 13 positions away:

  • A ↔ N
  • B ↔ O
  • C ↔ P
  • D ↔ Q
  • E ↔ R
  • F ↔ S
  • G ↔ T
  • H ↔ U
  • I ↔ V
  • J ↔ W
  • K ↔ X
  • L ↔ Y
  • M ↔ Z

Non-alphabetic characters (digits, spaces, punctuation, emoji) are passed through unchanged.

Decoding ROT13 examples

Example 1:

Encoded: Uryyb, jbeyq!
Decoded: Hello, world!

Letter by letter:

  • U → H (U is the 21st letter, 21-13=8, 8th letter=H)
  • r → e
  • y → l
  • y → l
  • b → o
  • (space unchanged)
  • j → w
  • b → o
  • e → r
  • y → l
  • q → d
  • (! unchanged)

Example 2: Spoiler text

Encoded: Qnegu Inqre vf Yhxr'f sngure.
Decoded: Darth Vader is Luke's father.

Example 3: Puzzle clue

Encoded: Gur nafjre vf gjragl-sbhe.
Decoded: The answer is twenty-four.

Manual decoding without a tool

If you need to decode ROT13 without a tool, you can use the alphabet pairing table. Write out the alphabet twice in a circle — the second starting at position 14 — and look up each letter.

Or memorize the 13 pairs: A-N, B-O, C-P, D-Q, E-R, F-S, G-T, H-U, I-V, J-W, K-X, L-Y, M-Z.

For a single word, working through the pairs manually takes 30–60 seconds. For anything longer, use the ROT13 Cipher tool.

ROT13 in Unix/Linux systems

Unix systems have built-in ROT13 support via the tr command:

# Encode (and decode — same command):
echo "Hello World" | tr 'A-Za-z' 'N-ZA-Mn-za-m'
# Output: Uryyb Jbeyq

echo "Uryyb Jbeyq" | tr 'A-Za-z' 'N-ZA-Mn-za-m'
# Output: Hello World

# Decode a file:
cat encoded.txt | tr 'A-Za-z' 'N-ZA-Mn-za-m'

# Decode in-place (requires a temp file):
tr 'A-Za-z' 'N-ZA-Mn-za-m' < encoded.txt > decoded.txt

The tr command translates characters according to a mapping. 'A-Za-z' is the source set (all alphabet characters), and 'N-ZA-Mn-za-m' is the target set (the ROT13 alphabet). tr processes character by character, applying the mapping.

Some Linux distributions also have a standalone rot13 command (part of the bsdgames package):

# Install on Debian/Ubuntu:
sudo apt install bsdgames

echo "Hello" | rot13
# Output: Uryyb

ROT13 in programming

Python — one line

import codecs
codecs.encode('Hello, world!', 'rot_13')  # 'Uryyb, jbeyq!'
codecs.decode('Uryyb, jbeyq!', 'rot_13') # 'Hello, world!'

# Without codecs:
text = 'Hello, world!'
rot13 = text.translate(
    str.maketrans(
        'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
        'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm'
    )
)
# 'Uryyb, jbeyq!'

JavaScript

function rot13(text) {
  return text.replace(/[A-Za-z]/g, c => {
    const base = c <= 'Z' ? 65 : 97;
    return String.fromCharCode(((c.charCodeAt(0) - base + 13) % 26) + base);
  });
}

rot13('Hello, World!')  // 'Uryyb, Jbeyq!'
rot13('Uryyb, Jbeyq!') // 'Hello, World!'

Python — full implementation

def rot13(text):
    result = []
    for char in text:
        if 'A' <= char <= 'Z':
            # Uppercase: shift within A-Z
            rotated = chr((ord(char) - ord('A') + 13) % 26 + ord('A'))
            result.append(rotated)
        elif 'a' <= char <= 'z':
            # Lowercase: shift within a-z
            rotated = chr((ord(char) - ord('a') + 13) % 26 + ord('a'))
            result.append(rotated)
        else:
            # Non-alphabetic: pass through unchanged
            result.append(char)
    return ''.join(result)

print(rot13("Hello, World!"))       # "Uryyb, Jbeyq!"
print(rot13(rot13("Hello")))        # "Hello" (self-inverse)
print(rot13("Numbers: 123"))        # "Ahzoref: 123" (digits unchanged)

Where you’ll encounter ROT13 encoded text

Reddit and forums

Reddit historically used ROT13 for spoilers before implementing native spoiler tags. Posts about movies, books, and games from the 2010s often contain ROT13 in comments. If you see garbled text like “Gur xvat vf qrnq” in an old Reddit thread, that’s a spoiler.

CTF (Capture the Flag) competitions

ROT13 is one of the first encodings to try when you find a suspicious string in a CTF. It often appears as a first layer that reveals a hint, a flag fragment, or a pointer to the actual challenge.

Standard CTF workflow for a suspicious string:

  1. Try Base64 decode
  2. Try ROT13
  3. Try hex decode
  4. Try from-binary
  5. Try Caesar cipher with other shifts

Source code comments

Some developers use ROT13 to obfuscate TODO comments, profanity filters, or puzzle Easter eggs in source code. Search open-source projects for strings matching the pattern of ROT13 text.

Email obfuscation (historical)

Before GDPR and sophisticated spam filters, some sites encoded email addresses with ROT13 to reduce bot harvesting. Modern spam filters check ROT13 automatically, so this is no longer effective.

ROT13 vs Base64 vs other encodings

ROT13, Base64, and URL encoding are all encoding mechanisms — not encryption. The difference is their purpose:

EncodingReversiblePurposeSecurity
ROT13YesCasual text obfuscationNone
Base64YesBinary-to-text encoding for transportNone
URL encodingYesEncode special characters in URLsNone
Caesar cipherYesWeak encryptionNone (26 possible keys)
AES-256Yes (with key)Strong encryptionStrong
SHA-256No (hash)Data integrity verificationCryptographic

ROT13 should never be used where any security is required. It provides no protection against a determined reader — it’s purely for informal, voluntary obfuscation.

The ROT13 tool

The ROT13 Cipher tool encodes and decodes ROT13 client-side. It also supports ROT47 (shifts all printable ASCII characters) and Caesar cipher with any shift value from 1–25. The source text never leaves your browser.


Related posts

Related tool

ROT13 / Caesar Cipher

Encode and decode ROT13 and arbitrary Caesar shifts. Letter frequency analysis. 100% client-side.

Written by Mian Ali Khalid. Part of the Encoding & Crypto pillar.