Cursive text generator turning plain text into Unicode script letters

Youโ€™ve seen names like ๐“ข๐“ช๐“ป๐“ช๐“ฑ in Instagram bios and Discord profiles, even though neither app lets you pick a font. That text comes from a cursive text generator, and no font is involved at all. Every letter is a separate Unicode character that happens to look like handwriting.

This article explains where those characters live in Unicode, why a naive converter produces broken output, how to write a correct one in a few lines of JavaScript, and the trade-offs (search, accessibility, string length) you should know before using script text in a product.

Cursive text is characters, not a font

A normal font changes how the same characters are drawn. Cursive Unicode text does the opposite: it swaps each letter for a different character whose standard shape is script-like. Because the styling lives in the characters themselves, it survives copy and paste into places that only accept plain text: bios, usernames, chat messages, commit messages.

Most of these characters come from the Mathematical Alphanumeric Symbols block (U+1D400โ€“U+1D7FF). Mathematicians need distinct symbols for, say, a script ๐’œ and a bold ๐€, so Unicode encoded whole alphabets in different styles:

Style Example First code point
Script ๐’œ๐’ท๐’ธ U+1D49C
Bold script ๐“๐“ซ๐“ฌ U+1D4D0
Fraktur ๐”„๐”Ÿ๐”  U+1D504
Double-struck ๐”ธ๐•“๐•” U+1D538

A cursive text generator is essentially a lookup table from Aโ€“Z and aโ€“z into one of these alphabets.

The gotcha: holes in the script alphabet

If you write the obvious converter, โ€œoffset every letter from U+1D49Cโ€, you get gaps. Eleven positions in the Mathematical Script range are reserved and empty:

B E F H I L M R   (capitals)
e g o             (lowercase)

Those letters already existed in Unicode before the math block was added, in the older Letterlike Symbols block, so Unicode didnโ€™t encode them twice. The correct characters are:

Letter Character Code point
B โ„ฌ U+212C
E โ„ฐ U+2130
F โ„ฑ U+2131
H โ„‹ U+210B
I โ„ U+2110
L โ„’ U+2112
M โ„ณ U+2133
R โ„› U+211B
e โ„ฏ U+212F
g โ„Š U+210A
o โ„ด U+2134

The bold script alphabet (U+1D4D0 onward) has no such holes, which is one reason many generators default to bold script. Fraktur and double-struck have their own gaps too (Fraktur is missing C, H, I, R and Z; double-struck is missing C, H, N, P, Q, R and Z), so check every alphabet you add.

A minimal cursive converter in JavaScript

Here is a small converter that handles the holes correctly. It maps letters and leaves digits, spaces and punctuation alone:

const SCRIPT_START = 0x1d49c; // MATHEMATICAL SCRIPT CAPITAL A
const HOLES = {
  B: "โ„ฌ", E: "โ„ฐ", F: "โ„ฑ", H: "โ„‹", I: "โ„", L: "โ„’", M: "โ„ณ", R: "โ„›",
  e: "โ„ฏ", g: "โ„Š", o: "โ„ด",
};

function toScript(text) {
  return [...text].map((ch) => {
    if (HOLES[ch]) return HOLES[ch];
    if (ch >= "A" && ch <= "Z") return String.fromCodePoint(SCRIPT_START + ch.charCodeAt(0) - 65);
    if (ch >= "a" && ch <= "z") return String.fromCodePoint(SCRIPT_START + 26 + ch.charCodeAt(0) - 97);
    return ch;
  }).join("");
}

console.log(toScript("Hello World")); // โ„‹โ„ฏ๐“๐“โ„ด ๐’ฒโ„ด๐“‡๐“๐’น

Two details matter. String.fromCodePoint is needed because these characters sit above U+FFFF, outside the Basic Multilingual Plane. And spreading the string with [...text] iterates by code point, so the function also works if the input already contains astral characters.

If youโ€™d rather not maintain tables for every style, a tool such as Cursive Text Generator previews dozens of script, bold and calligraphy styles side by side so you can compare them before deciding which alphabet to support.

Script characters behave differently from ASCII in code, and that leaks into product behavior.

Length. Characters above U+FFFF take two UTF-16 code units. In JavaScript, "๐“’๐“พ๐“ป๐“ผ๐“ฒ๐“ฟ๐“ฎ".length is 14, while [..."๐“’๐“พ๐“ป๐“ผ๐“ฒ๐“ฟ๐“ฎ"].length is 7. If you enforce a username limit with .length, cursive names will hit it at half the expected size. Many platforms count by code point instead, but test the specific field.

Normalization. Unicode compatibility normalization folds these characters back to plain letters:

"๐“’๐“พ๐“ป๐“ผ๐“ฒ๐“ฟ๐“ฎ".normalize("NFKC"); // "Cursive"

That is useful on the receiving side. If your app lets users pick styled display names, normalizing with NFKC before indexing or checking for duplicates prevents โ€œSarahโ€ and โ€œ๐“ข๐“ช๐“ป๐“ช๐“ฑโ€ from being treated as unrelated strings.

Search. Without that normalization step, search engines and in-app search usually treat script characters as distinct symbols. Someone searching for โ€œSarahโ€ may never find โ€œ๐“ข๐“ช๐“ป๐“ช๐“ฑโ€. Keep handles and anything that must be discoverable in plain text.

Where cursive Unicode text renders, and where it breaks

Rendering depends on whether the device has a font covering the Mathematical Alphanumeric Symbols block. Modern iOS, macOS and recent Android versions generally do. Older systems may show empty boxes (โ€œtofuโ€) instead.

Platforms also restrict fields differently. A bio or display name may accept script characters while the @username field strips them or only allows ASCII. The site behind the generator above maintains a cursive Unicode compatibility test that maps which fields on Instagram, TikTok, Discord and WhatsApp keep the styling, and which devices show boxes. That kind of field-by-field check saves a lot of trial and error.

Accessibility: use script text sparingly

Screen readers donโ€™t always read these characters as letters. Depending on the reader and platform, a styled name may be announced character by character with long symbol names, or skipped. For decorative use in a short display name that is usually tolerable. For whole sentences, instructions or anything a user must understand, it isnโ€™t.

A sensible rule: keep script text to a few words, never use it for essential information, and keep a plain-text version wherever meaning matters.

FAQ

Is cursive text from a generator a real font?

No. It is a sequence of Unicode characters that look like script letters. That is why it can be pasted into apps that donโ€™t let you change fonts, and also why its appearance depends on the system fonts on the readerโ€™s device.

Why do some cursive letters look different from the rest?

Eleven script letters (B, E, F, H, I, L, M, R, e, g, o) come from the Letterlike Symbols block rather than the math block. Fonts often draw that block slightly differently, so those letters can look a little out of place next to the others.

Why does my cursive text show up as boxes?

The device or app doesnโ€™t have a font covering those characters. Updating the OS usually fixes it. For text that must display everywhere, use plain letters.

Conclusion

A cursive text generator is a lookup table into Unicodeโ€™s math alphabets, plus a patch for the eleven letters that live elsewhere. Once you know that, the side effects make sense: doubled string lengths in JavaScript, invisible-to-search names, screen-reader noise and the occasional box. Use script text for short decorative touches, normalize it on the way in, and when you want to compare styles quickly, try the free cursive text generator.