Character Reverser
Reverse a string one character at a time, with the Unicode handling most reversers get wrong. Emoji and other astral characters move as single units instead of being torn into unpaired surrogates.
If you are testing a reverse function, debugging mojibake, or just need a reference implementation you can paste into, this page shows exactly what correct code-point reversal produces β including the cases where correct still is not perfect.
Working with words rather than characters? Reverse letters per word
Character Reversal Test Cases
These double as a test suite. If your own reverse function disagrees with any row here, it is almost certainly splitting UTF-16 units instead of code points.
| Input | Output | What it shows |
|---|---|---|
| abcdef | fedcba | Baseline: pure ASCII reverses trivially. |
| abπcd | dcπba | The emoji stays whole. A naive split("") produces two broken glyphs here. |
| πππππ ππ | πππ ππππ | Astral mathematical characters are each one code point and survive. |
| cafΓ© | Γ©fac | A precomposed Γ© reverses cleanly as a single character. |
| a b c | c b a | Tabs and newlines are ordinary characters and reverse in place. |
| padded | deddap | Leading and trailing spaces swap ends rather than being trimmed. |
| 1234567890 | 0987654321 | Digit strings reverse without any numeric interpretation. |
| <div class="x"> | >"x"=ssalc vid< | Angle brackets and quotes are not escaped or altered. |
| ABCdef123!@# | #@!321fedCBA | Mixed classes confirm nothing is reordered by type. |
Code Points, Units and Graphemes
There are three plausible answers to "what is a character", and picking the wrong one is why so many reverse functions corrupt text.
UTF-16 code units: the wrong choice
JavaScript strings are sequences of 16-bit units. text.split("").reverse().join("") reverses those units, which swaps the halves of any character outside the Basic Multilingual Plane. Every emoji in the string becomes two replacement glyphs.
Code points: what this tool uses
Array.from(text) iterates code points, so a surrogate pair is yielded as one two-unit string and moves as a unit. This is the correct default and fixes the entire emoji class of bugs.
Grapheme clusters: the perfect but heavier option
A user-perceived character can span several code points β a base letter plus combining marks, or emoji joined by zero-width joiners. Reversing grapheme clusters requires Intl.Segmenter and a much larger implementation; this tool works at code-point level and documents the difference rather than pretending it does not exist.
Why the distinction shows up in counts
The character counts on this page use code points too, so "ππ" counts as 2 rather than the 4 that String.length reports. If your own counter disagrees with the tool, that is usually why.
Reversal Granularity Compared
Four levels at which a string can be reversed, applied to the same input. Choosing the granularity is the whole decision.
Shared input: abc def ghi jkl
| Transformation | Result | Reach for it when |
|---|---|---|
| Characters | lkj ihg fed cba | You want a true end-to-start string reversal. |
| Characters within words | cba fed ihg lkj | You want per-token reversal with layout preserved. |
| Words | jkl ghi def abc | You want token order flipped, tokens intact. |
| Lines | ghi jkl abc def | You want record order flipped in a list or log. |
Documented Reversal Behaviour
Each of these is covered by a unit test in the repository, so the behaviour is deliberate and will not drift.
Surrogate pairs stay intact
Reversing "abπcd" produces "dcπba". The emoji is a single code point stored as two UTF-16 units, and it is never split. This is asserted directly in the test suite.
ZWJ sequences are separated
The family emoji π¨βπ©βπ§ is three emoji plus two zero-width joiners. Code-point reversal yields the components in reverse order rather than the combined glyph. Documented limitation, not silent corruption.
Combining marks detach from their base
The decomposed form of Γ© is "e" followed by U+0301. After reversal the combining acute precedes the e and attaches to whatever now sits before it. The precomposed U+00E9 form has no such problem.
CRLF becomes LFCR
A Windows line ending is two characters. Reversing a document with CRLF endings puts the line feed before the carriage return. If you are reversing files rather than prose, normalise line endings first.
Notes for Developers
The behaviour above maps onto the equivalent operations in the languages people most often ask about.
JavaScript and TypeScript
Use Array.from(str).reverse().join(""), or [...str] which iterates the same way. Avoid str.split("") entirely. For grapheme-accurate reversal, segment with Intl.Segmenter("grapheme") first.
Python
str[::-1] reverses by code point already, because Python 3 strings are sequences of code points rather than UTF-16 units. Combining marks still detach, so the grapheme caveat applies there too.
Java and C#
Both use UTF-16 internally, so StringBuilder.reverse() and a naive char[] reversal have the same surrogate problem as JavaScript. Java's StringBuilder.reverse() does special-case surrogate pairs; a hand-rolled loop usually does not.
Go and Rust
Strings are UTF-8 byte sequences. Reversing bytes corrupts any multi-byte character, so iterate runes in Go or chars in Rust and reverse that sequence instead.
When You Need Character-Level Reversal
Testing your own implementation
Paste the emoji and accent rows from the table above into your function. Any difference from the outputs here points straight at a UTF-16 assumption in your code.
Building test fixtures
Reversed strings with mixed scripts make good fixtures for text pipelines, because they exercise encoding paths that plain ASCII never touches.
Interview practice
"Reverse a string" is a classic interview question, and the Unicode follow-up is the part that separates answers. The cases here are the ones worth being able to discuss.
Debugging mojibake
If reversed text renders as replacement characters somewhere in your stack, comparing against this output isolates whether the corruption happened at reversal or later.
Frequently Asked Questions
Related Text Tools
Text Reverser
Compare six backwards-text results side by side from one input.
Backwards Text Generator
Turn any sentence into backwards text, character by character.
Text Inverter
Invert text three ways β backwards, upside down or mirrored β and compare.
Write Backwards Tool
Type forwards and read backwards, plus how to write in reverse by hand.
Sentence Reverser
Reverse a whole sentence or message, by word order or letter by letter.
Letter Reverser
Reverse the letters inside every word while the words stay in place.
Backwards Text Translator
Translate text to backwards and decode backwards text in one pass.
Reverse Words Tool
Reverse word order while every word stays readable.