TechEarl

Disable WordPress Emojis to Speed Up Your Site

How to disable WordPress emojis: a small functions.php snippet that strips the wp-emoji-release.min.js script, the inline detection JS, and the emoji styles from every page.

Ishan Karunaratne⏱️ 10 min readUpdated
Share thisCopied
How to disable WordPress emoji support: a functions.php snippet that removes wp-emoji-release.min.js, the inline detection script, and emoji CSS to cut an HTTP request from every page load.

To disable WordPress emojis, drop this remove_action() block into your theme's functions.php (or, better, a small site-specific plugin). It stops the emoji script, the inline detection JS, and the emoji CSS from printing on every page:

php
add_action( 'init', function () {
    remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
    remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
    remove_action( 'wp_print_styles', 'print_emoji_styles' );
    remove_action( 'admin_print_styles', 'print_emoji_styles' );
    remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
    remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
    remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
} );

That is the whole fix. WordPress core registers those actions in wp-includes/default-filters.php, and removing them at init stops the emoji machinery before wp_head runs. No plugin required, nothing to configure.

What WordPress actually loads for emojis

Since WordPress 4.2 (April 2015), every front-end page gets an emoji polyfill so that older browsers and operating systems render 🎉 and friends consistently. On a clean install, view-source on the front page shows two things in the <head>:

  • A block of inline JavaScript (the detection script) that checks whether the browser can render the current emoji set natively.
  • A conditional load of wp-emoji-release.min.js from wp-includes/js/wp-emoji-release.min.js, pulled in only when that detection decides the browser needs the polyfill.

Plus a small <style> block (img.wp-smiley) that controls how emoji images sit inline with text.

The inline script is small but it is render-blocking parse work in the <head>, and on modern browsers the polyfill it guards is almost never needed: every current version of Chrome, Firefox, Safari, and Edge renders Unicode emoji natively. So for the overwhelming majority of visitors you are shipping detection code to solve a problem they do not have.

How much speed does this actually save?

Honestly, not much. This is a micro-optimization, and I want to be straight about that before you spend an afternoon on it.

The inline detection script is a few hundred bytes of gzipped HTML. The wp-emoji-release.min.js file is only fetched when detection fails, which on a modern browser is basically never, so on most page loads you are not saving a network request at all. What you reliably save is:

  • The inline script bytes in every HTML response (small, but it is on every page).
  • A little main-thread parse and execution time in the <head> before the browser moves on.
  • One line of noise in the Network tab and in Lighthouse "reduce unused JavaScript" nags.

If you are chasing a perfect PageSpeed score or auditing a site where every request matters, removing emojis is a clean, zero-risk item to tick off. If you are trying to make a genuinely slow site fast, your time is better spent on a caching layer, image sizing, and your slowest plugins. See my notes on tracking down ACF-driven query bloat for the kind of problem that actually moves the needle, and on a WooCommerce store the slow path is almost always the database, not the head scripts.

Put it in a plugin, not the theme

The snippet works in functions.php, but I do not keep it there. Theme code disappears the moment you switch themes, and "why did emojis come back?" is a genuinely annoying thing to debug six months later.

Drop this file into wp-content/mu-plugins/disable-emojis.php instead. Files in mu-plugins (must-use plugins) load automatically, before regular plugins, and survive theme switches:

php
<?php
/**
 * Plugin Name: TE Disable Emojis
 * Plugin URI:  https://techearl.com/disable-wordpress-emojis-speed
 * Description: Stops WordPress printing the emoji detection script and styles.
 * Version:     1.0.0
 * Author:      Ishan Karunaratne
 * Author URI:  https://techearl.com
 * License:     GPL-2.0-or-later
 * Text Domain: te-disable-emojis
 */

add_action( 'init', function () {
    remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
    remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
    remove_action( 'wp_print_styles', 'print_emoji_styles' );
    remove_action( 'admin_print_styles', 'print_emoji_styles' );
    remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
    remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
    remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );

    // Drop the wpemoji TinyMCE plugin from the classic editor.
    add_filter( 'tiny_mce_plugins', function ( $plugins ) {
        return is_array( $plugins ) ? array_diff( $plugins, array( 'wpemoji' ) ) : array();
    } );

    // Stop the emoji JS from getting prefetched via the resource-hints DNS line.
    add_filter( 'wp_resource_hints', function ( $urls, $relation_type ) {
        if ( 'dns-prefetch' === $relation_type ) {
            $emoji_svg = apply_filters( 'emoji_svg_url', 'https://s.w.org/images/core/emoji/' );
            $urls = array_diff( $urls, array( $emoji_svg ) );
        }
        return $urls;
    }, 10, 2 );
} );

The tiny_mce_plugins filter drops the wpemoji plugin from the classic editor's TinyMCE instance, so the editor stops loading the emoji code too. It only matters if you (or your clients) still write in the classic editor; the block editor does not register that plugin, so the filter is a harmless no-op on a Gutenberg-only site.

The extra wp_resource_hints filter removes the s.w.org dns-prefetch line that WordPress adds for the emoji SVG host. It is the one easy-to-miss leftover: strip the script and styles but forget this, and view-source still shows a <link rel="dns-prefetch" href="//s.w.org"> you did not want.

The hook priority detail people get wrong

The one place this snippet goes wrong is the priority argument:

php
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );

remove_action() only matches when the priority you pass is the same priority the action was added with. WordPress hooks print_emoji_detection_script onto wp_head at priority 7, so you have to pass 7 here. Leave it off (which defaults to 10) and the remove_action call silently does nothing: no error, no warning, the emoji script keeps printing, and you waste twenty minutes wondering why.

The same is true for any "remove a core action" snippet. Find the original add_action() in core, copy its priority exactly. This one is documented in wp-includes/default-filters.php.

Comparison: the three common approaches

ApproachSurvives theme switchCode to maintainWhen I use it
functions.php snippetNoOne blockQuick test, or a site I fully control
mu-plugins fileYesOne fileMy default for any real site
Disable-emojis pluginYesZero (someone else's)Client sites where a non-dev edits things

For a developer-controlled site, the mu-plugins file wins: it is the same seven lines, it survives theme changes, and there is no third-party plugin to keep updated or to trust. The standalone plugin is fine when the person maintaining the site will not touch PHP, but it is a lot of overhead for what is ultimately a remove_action() call.

Verify it worked

After adding the snippet, hard-refresh the front page and check the page source. Search the HTML for emoji. A clean result means:

  • No inline _wpemojiSettings / wpemoji detection block in the <head>.
  • No wp-emoji-release.min.js request in the browser Network tab.
  • No img.wp-smiley style block.
  • No //s.w.org dns-prefetch link (if you included the resource-hints filter).

If emoji still shows up, the usual cause is the priority bug above, a page cache serving the old HTML (purge it), or a plugin re-adding emoji support after your init callback runs.

One honest caveat: removing the polyfill does not stop emoji from working. On any current browser, a 🚀 you type into a post still renders fine, because the browser handles Unicode emoji natively now. You are only removing the compatibility shim for browsers almost nobody uses anymore.

See also

Sources

Authoritative references this article was fact-checked against.

TagsWordPressPerformancePHPfunctions.phpPage Speed

Found this useful? Pass it on.

Copied

Ishan Karunaratne

Software Systems Architect · Senior Software Engineer · Engineering Leadership

Software systems architect and senior software engineer with more than two decades designing, building, and running production software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Now a CTO, though what I write here is drawn from the full arc of that work, across architecture, engineering, and operations, not any single job.

Keep reading

Related posts

Managed WordPress vs VPS for agencies. Simplicity vs flexibility, price premium vs lower per-resource cost. The break-even math with real numbers.

Managed WordPress Hosting vs VPS for Agencies

Managed WordPress hosting buys you operational simplicity at a per-site price premium. VPS buys you flexibility and lower per-resource cost at the price of in-house sysadmin time. The honest comparison and the agency-side break-even math.