mrkeyoor.com_
Tue 22 Sept 22:36 UTC
PyPIUtilsupdated 21 Sept 2026

emoji review

emoji 2.15.0 is a Python Unicode data and text utility, not an image renderer. It expands official shortcodes or optional aliases, converts characters back to names, finds complete emoji sequences with Python string offsets, replaces matches, and exposes metadata such as the Emoji version. The 2.15.0 release updates its table to Unicode 17.0. English is the default, with 14 documented translated name sets. Its parser understands flags, skin tones, variation selectors, and joined sequences that a one-code-point loop will split incorrectly.

Verdict

emoji 2.15.0 installed in 0.2 seconds, occupied 5 MB, imported in 0.27 seconds, and had 0 audit findings in our sandbox, making it an easy choice for Unicode-aware emoji text work on Python 3.8+. Do not install it for glyph rendering, sentiment analysis, display-width calculation, or immutable multilingual identifiers.

We installed it

Lab card: what happened when we installed emojiScreenshot of emoji documentation
Install✓ · 0.2s1 package on disk · 5 MB
Importimport emoji in 0.27s · pure Python · py.typed · requires Python >=3.8
Known vulns0(pip-audit)

Answers from our run

Does emoji install cleanly?

Yes. In a fresh container with an empty cache, pip install emoji finished in 0.2s, leaving 1 package and 5 MB on disk. pip-audit reported no known vulnerabilities.

What does emoji need to run?

Python >=3.8, and nothing compiled: it is pure Python. In our run import emoji succeeded in 0.27s, and the package ships py.typed for type checkers.

emoji or demoji: which should you use?

demoji: Use it for a smaller find, describe, replace, and remove API when localized shortcode expansion is unnecessary. emoji 2.15.0 installed in 0.2 seconds, occupied 5 MB, imported in 0.27 seconds, and had 0 audit findings in our sandbox, making it an easy choice for Unicode-aware emoji text work on Python 3.8+.

When should you not use emoji?

You need bitmap artwork, a font, or consistent cross-platform rendering; this package only returns and inspects Unicode text

API stability4/5The current 2.x API centers on `emojize`, `demojize`, `analyze`, `replace_emoji`, list and count helpers, validation, version lookup, and `EMOJI_DATA`. Release 2.15.0 changes the data set to Unicode 17.0 without announcing a new calling convention. One point comes off because version 2 removed the former regex API and old dictionaries, while translated output can still change when Unicode CLDR names are refreshed. Module-level parser settings also create shared state.
Docs5/5The linked Sphinx documentation covers every main function, alias mode, 15 language choices including English, variation selectors, replacement callbacks, string offsets, version filtering, joined sequences, and the difference between `is_emoji` and `purely_emoji`. It also keeps a migration page for the 2.0 breaks and a generated table of supported characters. These examples answer the awkward Unicode questions that a short function list would leave open.
Maintenance4/5PyPI published 2.15.0 on September 21, 2025, and its release note says the package moved to Unicode 17.0. GitHub records a push on the same date, does not mark the repository archived, and currently shows 27 open issues and pull requests combined. This project naturally moves with Unicode data releases instead of shipping weekly features. The evidence shows a maintained data package, though there has been no newer code push in almost a year.
Ecosystem5/5emoji records 3,925,987 weekly downloads, and GitHub currently reports 2,039 stars. Version 2.15.0 supports Python 3.8 or newer, ships a `py.typed` marker, and includes English plus 14 translated name sets derived from Unicode data. That makes it a familiar dependency for Python text pipelines. Rendering remains outside the package, so its ecosystem reach does not solve missing glyphs on old phones or servers.

Use it if

  • Your Python service needs shortcode expansion or `demojize` output using Unicode 17.0 data
  • Text scanning must treat skin tones, flags, and zero-width-joiner families as emoji sequences
  • You need names in English or one of the 14 documented translated language sets
  • Older clients require Emoji-version filtering with a replacement for unsupported characters
Skip it if

Setup reality

Our install of emoji 2.15.0 finished in 0.2 seconds in a fresh Python 3.12 container. It left 1 package and 5 MB on disk, and pip-audit found 0 known vulnerabilities. The measured package had 2 direct dependencies, required Python 3.8 or newer, contained only Python code, and imported successfully in 0.27 seconds. It ships py.typed, so type checkers can use the package's annotations.

Official English names work without configuration. Common spellings such as :thumbsup: require language='alias'; the normal English table expects official names such as :thumbs_up:. A translated call selects a documented language code. Code that reads a translated entry directly from EMOJI_DATA must call emoji.config.load_language(code) first, which adds that language to process-wide module data.

Treat demojized names as presentation or interchange text rather than fixed IDs. The 2.0 migration changed translated names when the project adopted newer CLDR data, and some emoji lack a name in some languages. Version 2.15.0 adds Unicode 17.0 data, but client fonts and operating systems still decide whether a new symbol renders as intended.

emoji_list returns Python string indexes. A family, flag, or toned character may occupy several code points, so those offsets are not byte positions or terminal columns. is_emoji requires the entire input to be one recognized entry; purely_emoji accepts a string made only from emoji tokens. Non-RGI joined-sequence behavior also uses module-level configuration, so changing it inside a reusable library affects other callers in the same process.

Patterns

Expand an official shortcode emojize

import emoji

text = emoji.emojize('Deploy complete :check_mark_button:')
print(text)

English official names are the default in 2.15.0. An unknown shortcode stays in the string unchanged.

Allow chat-style aliases alias-names

import emoji

text = emoji.emojize(
    'Nice work :thumbsup: :+1:',
    language='alias',
)

Alias mode adds informal spellings to the official English table. Those aliases are unsuitable as permanent identifiers.

Turn emoji into searchable names demojize

import emoji

stored = emoji.demojize('Ship it 👍')
# 'Ship it :thumbs_up:'

Unicode and CLDR updates can rename serialized output. Pin version 2.15.0 if another system treats these names as a protocol.

Use braces around names custom-delimiters

import emoji

rendered = emoji.emojize(
    'Status {green_circle}',
    delimiters=('{', '}'),
)

Pass the same delimiter pair to `demojize` when a round trip must keep brace-based syntax.

Use the Spanish name table localized-names

import emoji

rendered = emoji.emojize(
    'Todo bien :pulgar_hacia_arriba:',
    language='es',
)
names = emoji.demojize(rendered, language='es')

Some entries have no translation, and CLDR updates can change a localized name between releases.

Get the span of each emoji sequence match-offsets

import emoji

for item in emoji.emoji_list('A 👩‍🚀 aboard a 🚀'):
    print(item['emoji'], item['match_start'], item['match_end'])

The returned positions index the Python string. `👩‍🚀` spans several code points even though the parser returns one match.

Read a match's name and Emoji version inspect-metadata

import emoji

for token in emoji.analyze('Launch 🚀'):
    match = token.value
    print(token.chars, match.start, match.end)
    if match.data is not None:
        print(match.data['en'], match.data['E'])

`analyze` is a generator. A non-RGI joined token may be recognized while carrying no combined metadata dictionary.

Count total and distinct emoji count-matches

import emoji

text = '🌍 😂 😃 😂 🌍 🌦️'
total = emoji.emoji_count(text)
unique = emoji.emoji_count(text, unique=True)
values = sorted(emoji.distinct_emoji_list(text))

Sort the distinct list when output order matters because uniqueness is derived through a set.

Delete recognized emoji remove-matches

import emoji

plain = emoji.replace_emoji('Alert 🚨 resolved ✅', replace='')

This removes emoji entries known to version 2.15.0. It is not a general filter for every Unicode symbol or grapheme.

Replace each match with its English name replacement-callback

import emoji

def english_name(chars, data):
    return f' {data["en"]} '

searchable = emoji.replace_emoji(
    'Weather 🌧️ improving ☀️',
    replace=english_name,
)

The callback receives the matched sequence and its data. Normalize the extra spaces if the result feeds a search index.

Substitute emoji newer than version 3.0 version-limit

import emoji

safe = emoji.emojize(
    'A :T-Rex: eats a :croissant:',
    version=3.0,
    handle_version='[unsupported emoji]',
)

`version=3.0` refers to the Unicode Emoji data value, not Python, Android, iOS, or the package release.

Tell one emoji from an emoji-only string validate-input

import emoji

assert emoji.is_emoji('👍')
assert not emoji.is_emoji('👍👍')
assert emoji.purely_emoji('👍👍')

`is_emoji` expects one complete recognized entry. `purely_emoji` tokenizes the whole input and accepts multiple emoji.

Alternatives

PackageRegistryPick it when
demojiPyPIUse it for a smaller find, describe, replace, and remove API when localized shortcode expansion is unnecessary.
emotPyPIUse it when social-text parsing must include ASCII emoticons alongside Unicode emoji.
pilmojiPyPIUse it when Pillow must draw emoji images instead of merely inspecting Unicode strings.

More utils guides

lru-cache · ajv · type-fest · p-limit · find-up · js-yaml · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.