Skip to main content

How to generate a subset of an emoji font using Python

If you want to use an emoji font (like Noto Emoji or Noto Color Emoji) on your website but you only need a few of the characters, you’ll save a lot of bandwidth by generating a new font using only your chosen subset of characters. Here’s how to do that in Python 3.

  1. Install the Python modules fonttools and brotli. e.g.:

    python3 -m pip install fonttools brotli
    
  2. Download the font. e.g. on the Noto Emoji page at Google Fonts, click the “Download family” button, and unzip the downloaded file. Inside is a static directory. We’re going to make a subset of a single one of the .ttf fonts inside it: NotoEmoji-Regular.ttf

  3. You could either run the code below in the shell (type python on the command line) or put it in a file like create_font.py and run it from the command line with python create_font.py

  4. You’ll need to change three things in the code:

    1. The path to the downloaded .ttf file to use as the source.
    2. The path to where you want the .woff2 file the code creates to be saved.
    3. The list of emojis you want in the created font. Note that you need quote marks around each one. You could generate this list programmatically if, for example, they’re stored in a database.
from fontTools import subset

# One of the files downloaded from Google Fonts:
source_font_path = "path/to/NotoEmoji-Regular.ttf"

# Where we want to write our new file to. Note, it's woff2:
detination_font_path = "path/to/NotoEmoji-Regular-Custom.woff2"

# The only emojis that we want in our new font:
emojis = ["😀", "🧑‍🤝‍🧑", "👩‍👩‍👧‍👦", "🇬🇧", "⤴️", "🎂"]

# Create a list of unicode codes representing the characters in our emojis:
codes = []
for emoji in all_emojis:
    for e in emoji:
        codes.append(f"U+{:X}".format(ord(e)))

unicodes = ",".join(codes)

args = [
    source_font_path,
    f"--output-file={destination_font_path}",
    f"--unicodes={unicodes}",
    "--flavor=woff2",
]

subset.main(args)

The original .ttf files are 877 KB in size.

I generated a .woff2 file for ooh.directory that contained 155 emojis and it was only 59 KB.

You could drag your generated file onto Wakamaifondue to check which emoji are in it, and other details.

This was mostly pieced together from Stack Overflow answers. The one wrinkle doing this with emoji, compared to standard characters, is that each emoji could be made up of between 1 and 10 separate characters. So we need to cycle through each character within each emoji and ensure we have them all in our new font.

Now what?

Once you’ve put the new font on your server (e.g. in a /fonts/ directory) you can use it in your website’s CSS something like this:

@font-face {
  font-family: "Noto Emoji";
  src: url("/fonts/NotoEmoji-Regular-Custom.woff2") format("woff2");
}

.emoji {
  font-family: "Noto Emoji", sans-serif;
}

And then in your HTML if you do this:

<span class="emoji">😀</span>

Your emoji will be a Noto Emoji emoji instead of your OS’s standard style.

If you use an emoji that you haven’t built into your custom font file then it will appear as standard.

Thanks etc.

Thanks to Richard Rutter whose post “How to subset a variable font” was what first made me realise this kind of thing is even possible.

I’m definitely not an expert on either fonts or emojis so if you notice something that could be better please do comment (while they’re open) or email me.