JavaScript example

How to capitalize the first letter of a string in JavaScript

6 min read Updated Sep 2026 Runs in an isolated runtime
Quick answer

Uppercase the first character and glue the rest back on: str.charAt(0).toUpperCase() + str.slice(1). It returns a new string, leaves the rest of the text as it was, and turns an empty string into "" instead of throwing.

JavaScript has no built-in capitalize() or ucfirst(), and strings are immutable, so every approach builds a new string from two pieces: the first character, uppercased, and everything after it. The one-liner is easy. The details are where the bugs are: an empty string, capitalizing every word, emoji and other characters that take up two UTF-16 code units, and languages such as Turkish whose capital letters differ from the English ones. If the text is only for display on a web page, CSS text-transform: capitalize can do it without touching the string; this page is about changing the string itself. Every example runs on this page: hit Run, then edit the code and run it again.

1charAt(0).toUpperCase() + slice(1)Recommended

charAt(0) returns the first character, toUpperCase() uppercases it, and slice(1) returns everything from index 1 onward. Wrap it in a small function and you have capitalize(). Characters with no uppercase form, such as digits and punctuation, come back unchanged, so you don't need to check the first character first.

capitalize.js

Output

Output: Hello world, JavaScript, 42 apples, "", Hello world. Only the first character changes, so the capital S in javaScript survives. The empty string works because "".charAt(0) and "".slice(1) both return "". If you also want the rest lowercased, add .toLowerCase() to the slice, as capitalizeOnly does, but that also turns acronyms like NASA into Nasa. str.substring(1) works the same as str.slice(1) here. Avoid substr(): it is a legacy method that the spec only keeps for old code.

2str[0], a regex, or destructuring

You will also see three other versions. Bracket indexing str[0] is the most common one, and it gives the same result on any non-empty string. replace(/^./, …) uppercases whatever the regex matched at the start. Destructuring pulls the first character off the front. They differ on the empty string, which shows up whenever the input comes from a form field, a CSV cell or a split().

alternatives.js

Output

The first three lines print Compile. The fourth prints "" undefined undefined: on an empty string charAt(0) returns "", but str[0] and str.at(0) return undefined, so calling .toUpperCase() on them fails with TypeError: Cannot read properties of undefined (reading 'toUpperCase'). The regex version prints "" because ^. has nothing to match, and the destructuring version is safe only because of the = "" default. If you prefer str[0], guard it: str && str[0].toUpperCase() + str.slice(1).

3Letters outside the BMP, emoji and surrogate pairs

A JavaScript string is a sequence of UTF-16 code units. Characters above U+FFFF, which include emoji and the letters of scripts such as Deseret, Osage and Adlam, take two code units each (a surrogate pair). charAt(), str[0], slice() and length all count code units, so charAt(0) returns half a character. Spreading the string ([...str]), codePointAt() and a regex with the u flag all work in whole code points instead.

codepoints.js

Output

The first line prints 𐐨ello 6 5: five characters, six code units. charAt(0) is "\ud801", a lone high surrogate with no uppercase form, so the charAt version prints 𐐨ello unchanged. It doesn't corrupt anything, because the two halves are joined again, but it silently skips the capital. All three fixes print 𐐀ello. Emoji have no case, so 🚀 launch comes back intact from every version. The real risk with emoji is using the first character on its own, for an avatar initial say: charAt(0) gives you "\ud83d", half a rocket.

4Locale-aware: toLocaleUpperCase()

toUpperCase() applies Unicode's default case mapping, which is the same in every language. A few languages disagree with it. Turkish and Azerbaijani have a dotted i / İ pair and a dotless ı / I pair, so the capital of i is İ, not I. toLocaleUpperCase(locale) applies those rules when you pass it the language tag.

locale.js

Output

Output: Istanbul, then İstanbul with the Turkish rules, then İzmir Izmir for the same word in Turkish and English. Lowercasing has the mirror problem: IRMAK becomes irmak by default but ırmak in Turkish. Always pass the locale explicitly. With no argument, toLocaleUpperCase() uses the runtime's default locale, which differs between machines, servers and browsers. The last line, SS 1 2, is a reminder that uppercasing can change a string's length: German ß has no single-character capital in the default mapping, so it becomes SS.

5Which should you use?

MethodEmpty stringOutside the BMPBest for
str.charAt(0).toUpperCase() + str.slice(1)Returns ""Skips the capitalAlmost everything
str[0].toUpperCase() + str.slice(1)TypeErrorSkips the capitalInput known to be non-empty
str.replace(/^./u, (c) => c.toUpperCase())Returns ""Correct with the u flagOne expression, code-point safe
[first = "", ...rest] destructuringReturns "" (needs the default)CorrectA reusable, Unicode-safe helper
str.charAt(0).toLocaleUpperCase(locale) + str.slice(1)Returns ""Skips the capitalTurkish, Azerbaijani and other locale rules

6Common variation: capitalize every word

To capitalize each word, apply the same function to every word. split(" ") plus map() plus join(" ") is the clearest version. A regex that uppercases the first non-space character after the start or after any whitespace handles tabs and newlines as well. The regex you will find most often, /\b\w/g, looks similar but breaks on real text.

title-case.js

Output

Output: The Quick Brown Fox, then Keep The Spacing with the extra spaces kept. split(" ") produces empty strings between repeated spaces, and charAt(0) handles them where str[0] would throw. The regex version prints "Tabs\tAnd\nNewlines Too". The \b\w version prints Don'T Lose Your éLan: \w only matches ASCII letters, digits and underscores, so there is a word boundary after the apostrophe and another between é and l. The whitespace regex gets it right: Don't Lose Your Élan. Lowercase the input first if it might arrive in capitals. Headline-style title case, which leaves words like "the" and "of" in lowercase, needs a list of those words on top of this.

Frequently asked questions

Does JavaScript have a built-in capitalize or ucfirst function?

No. There is no String.prototype.capitalize() and no equivalent of PHP’s ucfirst(), so you write the one-liner str.charAt(0).toUpperCase() + str.slice(1), usually in a small helper function. You can add a method to String.prototype, but it is discouraged: it can clash with another library or with a method a future version of JavaScript adds.

How do I capitalize the first letter and make the rest lowercase?

Lowercase the slice as well: str.charAt(0).toUpperCase() + str.slice(1).toLowerCase() turns "hELLO wORLD" into "Hello world". Only do this when you really want it, because it also turns acronyms and names like "NASA" or "McDonald" into "Nasa" and "Mcdonald".

Why does str[0].toUpperCase() throw on an empty string?

Because ""[0] is undefined, and undefined has no methods, so you get TypeError: Cannot read properties of undefined (reading 'toUpperCase'). "".at(0) is also undefined. "".charAt(0) returns an empty string instead, which is why the charAt version works on empty input without a check.

Why is the first letter not capitalized for some characters?

If the first character is above U+FFFF, it is stored as two UTF-16 code units, and charAt(0) or str[0] returns only the first half, which has no uppercase form. Work in code points instead: const [first = "", ...rest] = str; first.toUpperCase() + rest.join(""), or str.replace(/^./u, (c) => c.toUpperCase()). The u flag is what makes the dot match a whole code point.

Should I use toUpperCase() or toLocaleUpperCase()?

Use toUpperCase() for identifiers, keys and anything that must behave the same everywhere. Use toLocaleUpperCase(locale) with an explicit language tag when you capitalize text shown to people in a language with its own rules: in Turkish, "istanbul" capitalizes to "İstanbul", not "Istanbul". Without an argument it uses the runtime’s default locale, which varies between machines.

Can I use CSS text-transform: capitalize instead?

For display on a web page, yes: text-transform: capitalize uppercases the first letter of each word when the text is rendered. It does not change the string, so the value you store, compare or send to a server is still lowercase. It capitalizes every word, not just the first, so for a sentence-style capital use JavaScript or the ::first-letter pseudo-element.

Run it yourself

Open any of these in the full JavaScript editor: tweak, run, and share.

JavaScript playground