How to strip emoji and pictograph glyphs from any font
- Step 1Drop your font onto the tool — Any TTF, OTF, WOFF, or WOFF2 is accepted (`.ttf,.otf,.woff,.woff2`). WOFF is zlib-inflated and WOFF2 is Brotli-decompressed to an sfnt buffer first, so format does not matter. Free tier caps the file at 5 MB; Pro at 50 MB; Developer at 1 GB.
- Step 2Let the tool walk the cmap — The tool iterates every glyph in the font, reads its primary Unicode value, and adds it to the keep-set only if it falls outside the four emoji/dingbat/PUA ranges. There is nothing to configure — the range set is fixed in code.
- Step 3Download the rebuilt TTF — The result is a fresh `*.no-emoji.ttf` built from the kept glyphs (plus `.notdef`). The metrics panel reports glyphs in source, glyphs kept, source size, and subset size so you can confirm the emoji block was actually present and removed.
- Step 4Re-compress for the web — The output is an uncompressed TTF. For production, run it through [TTF→WOFF2](/font-tools/ttf-to-woff2) (or [TTF→WOFF](/font-tools/ttf-to-woff) for legacy support). WOFF2's Brotli typically beats the raw TTF by 40–60%, which dwarfs the emoji-glyph saving on its own.
- Step 5Verify rendering against the OS fallback — Open a page with emoji content. macOS uses Apple Color Emoji, Windows 10+ uses Segoe UI Emoji, Android 9+ uses Noto Color Emoji. Because your font now carries no emoji glyphs, the browser cleanly falls through to the OS font — no double-rendering, no tofu, identical visual result.
- Step 6Re-add layout features if you need them — The rebuild drops kerning and `GPOS`/`GSUB`. If your text font relied on kerning pairs or ligatures, do the emoji strip in a layout-preserving pipeline instead — see [the build-pipeline guide](/font-tools/guides/emoji-removal-build-pipeline-script), which uses an hb-subset path that keeps those tables.
What the Emoji Remover keeps vs. drops
The four ranges are hard-coded; everything else is kept. Note that U+1F000–U+1FFFF already covers U+1F300–U+1FAFF, so the two entries overlap — both are listed because both are in the source.
| Codepoint range | Block(s) | Action | Why |
|---|---|---|---|
U+0000–U+25FF | Basic Latin, Latin-1, punctuation, currency, arrows, math, box-drawing | Kept | Outside all emoji ranges — your text glyphs survive untouched |
U+2600–U+27BF | Miscellaneous Symbols + Dingbats (☀ ☂ ☺ ✂ ✈ ✓ ✔ ❤ ➤) | Removed | Includes both emoji and text-mode symbol variants |
U+2800–U+DFFF | Braille, CJK, Hangul, surrogates, etc. | Kept | Outside the ranges |
U+E000–U+F8FF | Private Use Area | Removed | Treated as the typical custom-emoji range — also catches icon-font glyphs (see edge cases) |
U+1F000–U+1FFFF | Mahjong/Domino/Cards, Emoticons, Transport, Supplemental Symbols & Pictographs, Symbols Extended-A | Removed | The main emoji supplementary plane |
U+1F300–U+1FAFF | Misc Symbols & Pictographs through Symbols & Pictographs Extended-A | Removed | Subset of the above; listed explicitly in the code |
Input formats, output, and tier limits
All inputs are normalised to an sfnt buffer before processing; the output is always TTF regardless of input.
| Property | Value | Notes |
|---|---|---|
| Accepted inputs | TTF, OTF, WOFF, WOFF2 | WOFF inflated via zlib, WOFF2 decompressed via wawoff2 before processing |
| Output format | TTF (font/ttf) | Filename <stem>.no-emoji.ttf; re-compress with TTF→WOFF2 |
| Layout tables | Dropped | Kerning + GPOS/GSUB not carried by opentype.js's writer; outlines preserved |
| Free file limit | 5 MB | Per-job; covers essentially every text font with an emoji block |
| Pro file limit | 50 MB | Developer tier: 1 GB |
| Options / UI controls | None | No range picker, no presets — the keep/drop logic is fixed |
Cookbook
Real before/after runs. The metrics shown match the fields the tool reports (glyphs in source, glyphs kept, source/subset size).
Text font that shipped monochrome emoji
ExampleA self-hosted display font carried a small set of black-and-white emoji nobody could see (the browser always preferred the OS colour set). Stripping them is pure savings.
Input: Brand-Display.ttf (412 KB, 1,184 glyphs) Run: Emoji Remover (drop, download) Metrics panel: Charset: non-emoji glyphs Glyphs in source: 1184 Glyphs kept: 1109 (75 emoji/dingbat glyphs removed) Source: 412.0 KB Subset: 331.5 KB Next step: TTF -> WOFF2 -> ~140 KB shipped
WOFF2 in, TTF out
ExampleYou only have the production WOFF2 and no original. The tool decompresses it to sfnt, strips emoji, and hands back a TTF you re-compress.
Input: Inter.woff2 (96 KB)
Pipeline:
emoji-remover (WOFF2 -> sfnt -> strip -> TTF)
-> Inter.no-emoji.ttf (243 KB, uncompressed)
ttf-to-woff2
-> Inter.no-emoji.woff2 (89 KB)
The TTF is larger than the WOFF2 you started with -- that is
expected. The output is always uncompressed sfnt; re-compress it.Dingbats and symbols go too
ExampleU+2600–U+27BF is in the removal set, so check-marks (✓ ✔), scissors (✂), and the heart (❤) are stripped alongside true emoji. If your UI used a ✓ from this font, it will fall back to the OS or vanish.
Before (font cmap, partial): U+2713 CHECK MARK present U+2764 HEAVY BLACK HEART present U+2709 ENVELOPE present After Emoji Remover: U+2713 removed U+2764 removed U+2709 removed If you depend on these as TEXT glyphs, do not use this tool -- use the Character Whitelist Builder to keep them explicitly.
Font with no emoji at all
ExampleRun it on a plain Latin font and nothing in the ranges matches. The keep-set is the whole font, so you get a rebuilt TTF that is the same coverage (minus kerning/layout).
Input: SourceText.ttf (no emoji block) Metrics: Glyphs in source: 642 Glyphs kept: 642 Note: Kerning + OT layout features dropped; outlines preserved Size may even GROW slightly because the rebuild does not carry GPOS/GSUB but re-emits glyf/loca cleanly. If the font had no emoji, you gained nothing -- skip the tool.
Emoji-only font triggers colour-table strip
ExampleIf the font is entirely emoji (every cmap codepoint is in the ranges), the keep-set is empty. Rather than error, the tool falls back to removing the colour tables only.
Input: AppleColorEmoji-clone.ttf (emoji-only) Keep-set size: 0 -> fallback path Action: strip COLR, CPAL, sbix, SVG, CBDT, CBLC Metrics: Mode: Colour-table strip (emoji-only font) Output: 11240.3 KB This does NOT remove the emoji glyphs -- it only removes their colour layers. For full colour stripping use Colour Table Remover.
Edge cases and what actually happens
Every row below was probed against the live API. Some documented requirements (alphabetical axis order, numerical tuple order) are not actually enforced in practice — useful to know if you've been blaming the wrong thing for a 400.
Kerning and ligatures are dropped
By designThe rebuild goes through opentype.js's font writer, which emits glyph outlines but not GPOS/GSUB. So kerning pairs, ligatures, and stylistic sets are gone from the output. The metrics panel says so: Kerning + OT layout features dropped; outlines preserved. For a text font that relies on kerning, strip emoji in a layout-preserving pipeline instead — see the build-pipeline guide.
Icon-font glyphs in the PUA get removed
RemovedU+E000–U+F8FF (Private Use Area) is in the removal set because that is where custom emoji often live — but it is also where Font Awesome, Material Icons, and most icon fonts park their glyphs. Run this on an icon font and you delete the icons. Use the Character Whitelist Builder to keep specific PUA codepoints, or run Character Coverage Map first to see what is in your PUA.
Output is always TTF, never WOFF2
ExpectedWhatever you feed in — including a WOFF2 — the output is an uncompressed *.no-emoji.ttf. That TTF is usually bigger than the WOFF2 you started with. This is not a bug: the tool's job is glyph removal, not compression. Re-compress with TTF→WOFF2 before shipping.
Text-mode symbol variants disappear
RemovedSome characters have both a text and an emoji presentation (☺ U+263A vs 😊, ✉ U+2709). The text-mode codepoints sit in U+2600–U+27BF (Misc Symbols + Dingbats), which is in the removal set, so they go too. If you need the text-mode symbol preserved, use the Character Whitelist Builder with those exact codepoints.
CFF / PostScript-outline OTFs may fail to rebuild
Erroropentype.js's writer is strongest with TrueType (glyf) outlines. Fonts with CFF (PostScript) outlines or non-standard tables can throw inside toArrayBuffer(). The tool surfaces a clear message: convert to TTF first with a desktop tool, or use the Character Whitelist Builder with a smaller charset. The error is from the writer, not from the emoji logic.
ZWJ sequences and flags vanish together
RemovedFamily emoji (👨👩👧) are Zero-Width-Joiner sequences and flags are regional-indicator pairs (U+1F1E6–U+1F1FF); the indicators live inside U+1F000–U+1FFFF, so they are removed. The ZWJ itself (U+200D, in General Punctuation) is outside the ranges and kept, but with no component glyphs there is nothing left to join. See the edge-cases reference for the full sequence breakdown.
Multi-codepoint glyphs are kept if any codepoint is non-emoji
PreservedThe subsetter keeps a glyph if its primary unicode is in the keep-set, OR if any of its unicodes aliases is. So a glyph mapped to both an emoji codepoint and a non-emoji one survives because of the non-emoji mapping. In practice this is rare for emoji but it means removal is keyed on cmap codepoints, not glyph identity.
File over the tier limit is rejected before processing
RejectedThe client checks file size before doing any work. Free tier rejects anything over 5 MB with a per-job-limit error; Pro allows 50 MB; Developer 1 GB. A 60 MB colour-emoji font on the free tier never reaches the strip step — upgrade or run it on a paid tier.
No emoji present means no benefit
No-op-ishIf the font has no codepoints in any of the four ranges, every glyph is kept and you get a rebuilt TTF with the same coverage — but minus kerning/layout, so it can even be slightly larger. Confirm an emoji block exists first with Character Coverage Map or Glyph Count Analyzer before bothering.
Frequently asked questions
Won't my emoji disappear from the page?
No. Modern OSes (iOS, macOS, Windows 10+, Android 9+) provide colour emoji via a system font — Apple Color Emoji, Segoe UI Emoji, Noto Color Emoji. When your web font lacks emoji glyphs, the browser walks the font-fallback chain and uses the OS emoji font. Same rendering, smaller payload. The only emoji that vanish are ones that depended on your font and had no OS equivalent — which is essentially never for standard Unicode emoji.
Which exact ranges does it remove?
Four hard-coded ranges: U+1F000–U+1FFFF, U+2600–U+27BF (Misc Symbols + Dingbats), U+E000–U+F8FF (Private Use Area), and U+1F300–U+1FAFF. The last is a subset of the first; both are in the code. Everything outside these is kept. There is no UI to change the ranges.
What format is the output?
Always TTF, named <stem>.no-emoji.ttf, regardless of whether you fed in a TTF, OTF, WOFF, or WOFF2. It is uncompressed sfnt. For the web, re-compress with TTF→WOFF2.
Does it strip dingbats and check-marks too?
Yes. U+2600–U+27BF covers Miscellaneous Symbols and Dingbats — so ☀ ☂ ☺ ✂ ✈ ✓ ✔ ❤ ➤ all go. If you use any of these as text glyphs from this font, do not use the Emoji Remover; use the Character Whitelist Builder to keep them explicitly.
Will it break my icon font?
Probably, if the icons live in the Private Use Area. U+E000–U+F8FF is in the removal set, and that is exactly where Font Awesome, Material Icons, and similar fonts store their glyphs. Run Character Coverage Map to confirm, then use the Character Whitelist Builder to keep your icon codepoints instead.
Does it keep kerning and ligatures?
No. The rebuild uses opentype.js's writer, which does not carry GPOS/GSUB, so kerning pairs and ligatures are dropped. Outlines are preserved. The metrics panel states this explicitly. For a kerning-sensitive text font, strip emoji in a layout-preserving (hb-subset) pipeline — see the build-pipeline guide.
What if my font is branded-emoji only?
Don't run the Emoji Remover on it — every codepoint is in the emoji ranges, the keep-set is empty, and the tool falls back to stripping only the colour tables (COLR/CPAL/sbix/SVG/CBDT/CBLC). To keep just your brand emoji, use the Character Whitelist Builder with the codepoints you want to retain.
Why did my output file get bigger?
Two reasons. First, output is always uncompressed TTF — if you fed in a WOFF2, the TTF will naturally be larger. Second, the rebuild re-emits a clean glyf/loca but drops compact layout tables, so a font with little emoji can grow. Re-compress with TTF→WOFF2 and compare against your original deliverable, not against the intermediate TTF.
Can it handle OTF (PostScript) fonts?
It accepts OTF as input, but the rebuild can fail for CFF outlines because opentype.js's writer is happiest with TrueType outlines. If you hit a writer error, convert the OTF to TTF first with a desktop tool, then run the Emoji Remover.
How big a font can I process?
Free tier: 5 MB per file. Pro: 50 MB. Developer: 1 GB. A colour-emoji font like Apple Color Emoji (60+ MB) won't fit on the free tier — but you usually don't want to strip emoji from an emoji font anyway; you want it off a text font, which is well under 5 MB.
Is anything uploaded to a server?
No. The whole pipeline — decompress, walk the cmap, rebuild — runs in your browser tab via opentype.js (and wawoff2/pako for WOFF decompression). The font file never leaves your machine. Only an anonymous run counter is recorded for signed-in dashboard stats.
How do I verify the emoji were actually removed?
Check the metrics panel: it reports glyphs in source and glyphs kept. The difference is the number of emoji/dingbat/PUA glyphs removed. If the difference is zero, your font had nothing in the ranges. You can also re-run Character Coverage Map or Glyph Inspector on the output to confirm the ranges are empty.
Privacy first
Every JAD Font tool runs entirely in your browser using opentype.js and the wawoff2 WASM Brotli encoder. Your fonts never leave your device — verified by zero outbound network requests during processing.