How to use this Case Converter
Paste or type your text into the input box, then choose the output style you want.
The converted result appears instantly in the output box, where you can copy it for use in
content, code, filenames, URLs, documentation, or other workflows.
- Enter your text into the input area.
- Select the case style you want.
- Review the converted text in the output box.
- Copy the result or continue converting into other styles.
Example input
sample text for conversion
Example outputs
Title Case
camelCase
snake_case
kebab-case
What "change the case" really means once text leaves ASCII
For plain English the job is trivial: each letter has one uppercase form and one
lowercase form, so A↔a is a simple lookup and title case is just
"capitalize the first letter of each word." That mental model is where almost every
casing bug starts, because it silently assumes three things that Unicode does not
guarantee: that every character has exactly one case mapping, that the mapping is the
same everywhere in the world, and that changing case never changes the length of the
string. All three are false for real text.
This tool covers the everyday styles — UPPERCASE,
lowercase, Title Case, Sentence case,
camelCase, PascalCase, snake_case, and
kebab-case. The sections below are about the edge cases that turn a
one-line toUpperCase() into a production incident: a Turkish login that
won't match, a German word that grows a character, and a "case-insensitive" comparison
that isn't.
The Turkish dotless-i bug that breaks case-insensitive checks
In almost every language, "I".toLowerCase() is "i" and
"i".toUpperCase() is "I". Turkish and Azeri break that rule
because they have two separate letters: a dotless ı/I and a dotted
i/İ. Under Turkish rules the correct lowercase of I is the
dotless ı, and the correct uppercase of i is the dotted
İ (capital I with a dot).
The trap in JavaScript is that String.prototype.toLowerCase() and
toUpperCase() are locale-independent — they always apply
the default Unicode mapping and ignore the user's system locale entirely. Only
toLocaleLowerCase('tr') / toLocaleUpperCase('tr') follow
Turkish rules. The classic failure runs the other way: code that does honor the
user's Turkish locale lowercases "ISTANBUL" to "ıstanbul"
(dotless), so a case-insensitive lookup, a hostname comparison, or a security check
silently fails to match "istanbul". The rule that avoids this both ways: for
identifiers, protocol keywords, hostnames, and any machine token, use
invariant (culture-independent) casing — never the user's locale.
Why uppercasing "ß" makes the string one character longer
The German sharp S is the textbook example that casing is not length-preserving:
"ß".toUpperCase() returns "SS" — two characters. Uppercase a
word containing it and the string physically grows. A capital sharp S
(ẞ, U+1E9E) does exist, but JavaScript's default mapping still expands
ß to SS.
Two consequences bite in practice. First, any "uppercase then slice to N characters"
logic — a fixed-width column, a truncated display name, a buffer sized from the input
length — can overflow or cut in the wrong place, because the output is longer than the
input. Second, casing is not reversible:
"STRASSE".toLowerCase() gives "strasse", and there is no way to
recover the original "straße", because the round trip has lost information.
The same holds for ligatures and titlecase digraphs. Never assume text length or the
original spelling survives a case change.
Case-insensitive comparison is more than toLowerCase()
Comparing two strings by lowercasing both — a.toLowerCase() === b.toLowerCase()
— is fine for pure ASCII, but it is the wrong primitive for real text. It inherits the
Turkish problem above, and it misses the distinction between lowercasing and
case folding, the operation Unicode actually defines for caseless matching
(folding, for instance, maps ß to ss so that
"straße" and "STRASSE" compare equal).
For anything user-facing, prefer a collator: Intl.Collator, or
a.localeCompare(b, locale, { sensitivity: 'accent' }) to ignore case, or
sensitivity: 'base' to ignore both case and accents. These compare text the
way the language's own rules define equality, instead of hoping a naive lowercase happens
to line up.
There is no single correct "title case"
Title case feels well-defined until you try to automate it. Which words get capitalized
depends entirely on the style guide: AP and Chicago disagree about
short words, and both lowercase most prepositions and articles unless they start or end
the title — so "The Man in the Arena" is correct in one system and wrong in
another. A tool can pick a reasonable default, but "capitalize every word" and any single
algorithm will disagree with some house style.
There is a lower-level trap too. Capitalizing "the first letter" by taking the first
code unit — str.charAt(0).toUpperCase() — breaks on characters
outside the Basic Multilingual Plane, because an astral character (an emoji, some CJK
extensions) is stored as a surrogate pair of two code units, and grabbing one
half yields a broken character. A handful of digraph letters such as
dz even have a dedicated titlecase form (Dz) that is
distinct from their uppercase form (DZ), so "uppercase the first letter" is
not the same as "titlecase the first letter."
Frequently Asked Questions
Why does uppercasing "ß" give two letters?
Because the German sharp S has no single-character uppercase form in the default
Unicode mapping — "ß".toUpperCase() expands to "SS", so the
string gets one character longer. Watch out for any code that uppercases and then
truncates to a fixed length, since the output can be longer than the input.
Why is toLowerCase("I") "wrong" in Turkish?
Turkish has two distinct i letters, dotted and dotless. Under Turkish rules
the lowercase of I is the dotless ı, not i. So
lowercasing "ISTANBUL" with the Turkish locale yields
"ıstanbul", which no longer matches "istanbul" in a
case-insensitive check. For identifiers and protocol tokens, always use
locale-independent casing.
Should I use toLowerCase() for case-insensitive comparison?
For ASCII it is fine; for real text it is the wrong tool. It inherits the Turkish
dotless-i problem and isn't true Unicode case folding. Prefer
Intl.Collator or localeCompare(b, locale, { sensitivity: 'accent'
}), which compare while ignoring case (or case and accents) by the language's
own rules.
Why does JavaScript's toLowerCase() ignore my system locale?
By design. toLowerCase() and toUpperCase() apply the
invariant, locale-independent Unicode mapping so results are stable across machines.
If you need language-specific casing — Turkish, Azeri, Lithuanian — call
toLocaleLowerCase(locale) / toLocaleUpperCase(locale)
explicitly.
Is uppercasing then lowercasing reversible?
No. Case changes can lose information: "straße" uppercases to
"STRASSE", which lowercases back to "strasse" — the
original ß is gone. Ligatures and some digraphs behave the same way, so
never treat a round trip through upper- and lower-case as lossless.
Why isn't there one correct "title case"?
Because capitalization of short words, articles, and prepositions is a style-guide
decision, and AP and Chicago disagree. "Capitalize every word" is only one convention
among several, so an automated result will always conflict with some house style.
Treat title-case output as a fast starting point, not an authority.