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⏱️ 8 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.

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: Disable Emojis
 * Description: Stops WordPress printing the emoji detection script and styles.
 */

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

Tech Architect · Software Engineer · AI/DevOps

Tech architect and software engineer with 20+ years building software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Currently Chief Technology Officer at a healthcare tech startup, which is where most of these field notes come from.

Keep reading

Related posts

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.

Bluehost for WordPress: Honest Take for Small Sites

Bluehost has the WordPress.org recommendation and the lowest entry-tier price in mainstream hosting. The honest take on where Bluehost legitimately fits in 2026, the real operational ceiling, and the migration path for sites that outgrow it.

A WordPress Hosting Decision Tree for Agencies

Hosting choices for WordPress agency clients are operational decisions, not pricing decisions. The decision tree by traffic tier and workload type: shared, managed WordPress, managed VPS, self-managed VPS. Plus the agency-side implications of each.