str_rot13
Applies the ROT13 substitution cipher to a string, rotating each letter 13 places in the alphabet.
str_rot13(string $string): string- Added in PHP 4.2.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$string | string | The string to encode or decode. |
Return value
stringThe ROT13 version of the given string.
str_rot13 replaces every ASCII letter with the letter 13 positions later in the alphabet, wrapping from z back to a. Digits, punctuation, whitespace and any byte outside A-Z/a-z pass through untouched, and case is preserved.
When to reach for it
Because the alphabet has 26 letters, applying ROT13 twice returns the original string. That makes it a one-function way to make text non-obvious without needing a key or a second decode function: spoiler blocks, joke answers hidden in page source, competition solutions, or masking a mailto address from the crudest scrapers.
What trips people up
ROT13 is not encryption. There is no key, the transformation is fixed and public, and anyone can reverse it instantly. Never use it for passwords, tokens, API keys or anything that has to stay secret — reach for sodium_crypto_secretbox() or openssl_encrypt() instead.
It is also ASCII-only. Accented letters such as é, and every non-Latin script, are left as-is, so a ROT13'd Cyrillic or Greek string looks unchanged. There is no mb_str_rot13; if you need to obscure non-ASCII text, encode it first (for example with base64_encode) or use strtr with your own character map.
Example
When to use it
- Hide spoiler text or puzzle answers in HTML source so they are not readable at a glance
- Obscure a mailto address in generated markup against naive email harvesters
- Store joke or quiz answers in a config file that a casual reader will not accidentally spot
Frequently asked questions
Is str_rot13 secure enough to hide passwords?
No. ROT13 has no key and is trivially reversed by calling str_rot13 again, so it offers zero security. Use password_hash() for passwords and sodium_crypto_secretbox() or openssl_encrypt() for data that must stay secret.
How do I decode a str_rot13 string?
Call str_rot13 on it again. Rotating 13 places twice moves each letter a full 26 positions, returning the original string, so there is no separate decode function.
Does str_rot13 work with UTF-8 or accented characters?
Only for plain ASCII A-Z and a-z. Accented letters, Cyrillic, Greek and emoji are left untouched, and there is no multibyte equivalent in PHP.
More examples
Round-tripping spoiler text
Each line prints the scrambled form ("Fabj zrygf", "Gur ohgyre qvq vg") followed by the original. The same function both encodes and decodes, so you never need to store a matching decoder.
<?php
$spoilers = ['Snow melts', 'The butler did it'];
foreach ($spoilers as $s) {
$hidden = str_rot13($s);
echo $hidden, ' -> ', str_rot13($hidden), "\n";
}Only ASCII letters move
Digits, spaces and punctuation survive unchanged, and the multi-byte <code>é</code> is passed through as raw bytes. The last line proves a string with no ASCII letters comes back identical, which is why ROT13 is useless for non-Latin text.
<?php
echo str_rot13('ABC xyz 123 !?'), "\n"; // NOP klm 123 !?
echo str_rot13('café'), "\n"; // pnsé (é untouched)
var_dump(str_rot13('12:30') === '12:30');Building your own rotation with strtr
Both lines print <code>uryyb</code>, showing str_rot13 is just a fixed <code>strtr</code> map. Use this pattern when you want a different rotation amount or want to include digits in the mapping.
<?php
$from = 'abcdefghijklmnopqrstuvwxyz';
$to = 'nopqrstuvwxyzabcdefghijklm';
echo strtr('hello', $from, $to), "\n"; // uryyb
echo str_rot13('hello'), "\n"; // uryyb
var_dump(strtr('hello', $from, $to) === str_rot13('hello'));
Discussion