ROT13 in Python — Encode, Decode, and Extend to ROT47
Implement ROT13 encoding in Python using codecs, str.translate, or a manual lookup table. Extends to ROT47 (all printable ASCII), ROT5 (digits), and ROT18 (combined). Includes...
Use the tool
ROT13 / Caesar Cipher
Encode and decode ROT13 and arbitrary Caesar shifts. Letter frequency analysis. 100% client-side.
Python has built-in ROT13 support via the codecs module. For ROT47 or custom rotations, use str.maketrans() to create fast lookup tables.
Encode and decode ROT13 online with the ROT13 Cipher.
Built-in ROT13 with codecs
import codecs
# Encode:
encoded = codecs.encode('Hello, World!', 'rot_13')
print(encoded) # "Uryyb, Jbeyq!"
# Decode (same operation — ROT13 is its own inverse):
decoded = codecs.decode('Uryyb, Jbeyq!', 'rot_13')
print(decoded) # "Hello, World!"
# Or using the 'rot13' alias:
encoded = 'Hello, World!'.encode('rot_13')
decoded = encoded.decode('rot_13')
Manual ROT13 with str.maketrans
ROT13_TABLE = str.maketrans(
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm'
)
def rot13(text: str) -> str:
return text.translate(ROT13_TABLE)
print(rot13('Hello, World!')) # "Uryyb, Jbeyq!"
print(rot13('Uryyb, Jbeyq!')) # "Hello, World!"
Generic Caesar cipher
def caesar(text: str, shift: int) -> str:
"""Apply a Caesar cipher with given shift to letters only."""
result = []
for char in text:
if char.isalpha():
base = ord('A') if char.isupper() else ord('a')
shifted = (ord(char) - base + shift) % 26 + base
result.append(chr(shifted))
else:
result.append(char)
return ''.join(result)
# ROT13 is shift=13:
rot13 = lambda text: caesar(text, 13)
# Brute-force all 25 shifts:
for shift in range(1, 26):
print(f"ROT{shift:2d}: {caesar('Uryyb', shift)}")
ROT47 — all printable ASCII
ROT47 rotates the full range of printable ASCII characters (33–126, 94 total characters):
def rot47(text: str) -> str:
"""ROT47: rotate all printable ASCII characters."""
result = []
for char in text:
code = ord(char)
if 33 <= code <= 126: # Printable ASCII range
rotated = 33 + (code - 33 + 47) % 94
result.append(chr(rotated))
else:
result.append(char)
return ''.join(result)
print(rot47('Hello, World!')) # "w6==@[ (@C=5P"
print(rot47('w6==@[ (@C=5P')) # "Hello, World!"
# Faster with maketrans:
ROT47_TABLE = str.maketrans(
''.join(chr(i) for i in range(33, 127)),
''.join(chr(33 + (i - 33 + 47) % 94) for i in range(33, 127))
)
def rot47_fast(text: str) -> str:
return text.translate(ROT47_TABLE)
ROT5 (digits only) and ROT18 (combined)
def rot5(text: str) -> str:
"""Rotate digits 0-9 by 5."""
table = str.maketrans('0123456789', '5678901234')
return text.translate(table)
def rot18(text: str) -> str:
"""ROT18 = ROT13 for letters + ROT5 for digits."""
table = str.maketrans(
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm5678901234'
)
return text.translate(table)
print(rot18('Hello World 2026!')) # "Uryyb Jbeyq 7571!"
Command-line ROT13 tool
#!/usr/bin/env python3
"""rot13.py — encode/decode ROT13 from command line or file."""
import sys
import codecs
import argparse
def main():
parser = argparse.ArgumentParser(description='ROT13 encoder/decoder')
parser.add_argument('text', nargs='?', help='Text to encode (or read from stdin)')
parser.add_argument('-f', '--file', help='Input file path')
parser.add_argument('--rot47', action='store_true', help='Use ROT47 instead of ROT13')
args = parser.parse_args()
if args.file:
with open(args.file, 'r', encoding='utf-8') as f:
text = f.read()
elif args.text:
text = args.text
else:
text = sys.stdin.read()
if args.rot47:
table = str.maketrans(
''.join(chr(i) for i in range(33, 127)),
''.join(chr(33 + (i - 33 + 47) % 94) for i in range(33, 127))
)
result = text.translate(table)
else:
result = codecs.encode(text, 'rot_13')
print(result, end='')
if __name__ == '__main__':
main()
# Usage:
python rot13.py "Hello, World!" # Uryyb, Jbeyq!
python rot13.py "Uryyb, Jbeyq!" # Hello, World!
python rot13.py --rot47 "Hello, World!" # w6==@[ (@C=5P
echo "Hello" | python rot13.py # Uryyb
python rot13.py -f spoiler.txt # Decode a file
Related tools
- ROT13 Cipher — encode/decode ROT13 online
- Caesar Cipher — general letter shift cipher
- Base64 — encode/decode Base64
Related posts
- Caesar Cipher and ROT13 — How Shift Ciphers Work — The Caesar cipher shifts each letter by a fixed number. ROT13 shifts by 13. Neit…
- Caesar Cipher Explained — ROT13, ROT47, and Shift Ciphers — The Caesar cipher shifts letters by a fixed number of positions. ROT13 is a Caes…
- ROT13 Uses — When and Why ROT13 Encoding Is Used — ROT13 rotates each letter by 13 positions in the alphabet. It's not encryption b…
- ROT13 Decoder — How to Decode ROT13 Encoded Text — ROT13 is a simple letter-substitution cipher that shifts each letter 13 position…
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.