Caesar cipher & ROT13
With ROT13, Hello, World! becomes Uryyb, Jbeyq!: each letter moves 13 places, capitals stay capitals, and the comma, space and exclamation mark stay put. Choose any shift, positive or negative, and decode with the same number to get your text back. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Input text
- Hello, World!
- Result
- Uryyb, Jbeyq!
- Requested shift
- 13
- Effective shift
- 13
- Operation
- Encode
A Caesar cipher shifts letters by a fixed amount; ROT13 is the special case of shift 13.
How a Caesar shift moves each letter
A Caesar cipher moves every letter a fixed number of places along the alphabet, wrapping from Z back to A. ROT13 is the best-known case, a shift of 13, and it is the default here. Only the letters A to Z move: uppercase letters rotate among the capitals and lowercase letters among the small letters, so Hello, World! becomes Uryyb, Jbeyq! with its comma, space and exclamation mark exactly where they were. Digits and all other punctuation also pass through unchanged, which keeps numbers readable and the layout of the message intact.
Shifts, decoding and the round trip
Any whole number works as a shift, including negative values and values above 25. Because the alphabet has 26 letters, a shift of 26 changes nothing and a shift of −1 is the same as 25; the result always shows the effective rotation that was applied. Decoding simply turns the letters the other way by the same amount, so encoding and then decoding with the same shift always restores the original text. That makes the tool handy for classroom demonstrations, for trying shifts quickly on a puzzle, and for lightly hiding spoilers or answers.
Letters rotate, everything else stays
Only ASCII letters move around the alphabet. Spaces, digits and punctuation pass through unchanged so messages like Hello, World! keep their commas and spaces after encoding.
Uppercase and lowercase are preserved independently: A shifts within A–Z and a within a–z.
Any whole-number shift, with the real rotation shown
Shift defaults to 13 for classic ROT13. Shift 26 is identity; shift −1 is the same as 25.
Decode is the inverse rotation
Decode applies the opposite rotation (−shift) while still reporting the original shift and its effective modulus. That makes round-trips deterministic: encode then decode with the same shift restores the plaintext for any integer shift in a wide range.
What you can do with it
ROT13 and classroom demos
Show classical substitution with a single shift and instant reverse decode.
CTF and puzzle warm-ups
Quickly try shifts on ciphertexts without floating-point surprises.
Message masking
Lightly obscure spoilers or answers that only letters need to hide.
FAQ
What is the default shift?
13 — classic ROT13 — unless you pass another integer.
Do digits rotate?
No. Only A–Z and a–z move; digits and punctuation stay.
How does decode work?
It rotates by −shift while still reporting the original shift fields.
What does a shift of 26 or −1 do?
A shift of 26 brings every letter back to itself, so the text is unchanged. A shift of −1 is the same as 25. Any whole number is accepted, and the result shows the effective shift between 0 and 25 that was actually applied.
Is ROT13 a safe way to hide a message?
Only lightly. ROT13 hides a spoiler or a puzzle answer from a quick glance, but anyone can undo it by applying the same shift again. It is meant for masking and teaching, not for protecting private information.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/text/caesar-cipher \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"Hello, World!"}'const res = await fetch("https://api.kit.forhosting.com/text/caesar-cipher", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"text": "Hello, World!"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/text/caesar-cipher",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"text": "Hello, World!"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/text/caesar-cipher", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"text":"Hello, World!"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"text":"Hello, World!"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/text/caesar-cipher", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"text": "Hello, World!"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "text.caesar_cipher",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_text_chars | 100000 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
This tool rotates only A–Z and a–z, leaves digits and punctuation untouched, reports the effective shift modulo 26, and matches the free browser tool with the API on every character.
Any integer shift, reported as shift_effective
Negative values and values above 25 are allowed; the effective rotation is always ((shift % 26) + 26) % 26 and is returned as shift_effective from the input shift, even in decode mode.
Typed errors and size limits
Text is required and capped at 100000 characters.
Integration use cases
Automated checks
Assert encode and decode round-trips in CI fixtures.
Technical questions
What does shift_effective mean?
The input shift reduced to 0…25 via modulo 26, always from the input shift.
Can shift be negative?
Yes. −1 is equivalent to effective 25.
Is it free in the browser?
Yes on desktop and mobile. The native app uses the API at $0.002.