Fix Guide

How to enable Brotli compression on nginx and Apache

May 20, 2026

Brotli is a lossless compression algorithm developed by Google engineers Jyrki Alakuijala and Zoltan Szabadka, open sourced in September 2015 and standardized as RFC 7932 (July 2016). Compared to gzip (the long standing default), Brotli produces 15 to 25 percent smaller files for HTML, CSS and JavaScript at comparable CPU cost, thanks to a 120 KB static dictionary of common web tokens. Brotli is supported by all modern browsers since 2017 (Chrome 50 in April 2016, Firefox 44 in January 2016, Safari 11 in September 2017, Edge 15 in April 2017) and by every major CDN (Cloudflare since 2017, Fastly, Akamai, CloudFront since September 2020). The HTTP content encoding identifier is br, requested by browsers via the Accept-Encoding: gzip, deflate, br header and acknowledged by servers with Content-Encoding: br. Enabling Brotli typically reduces total page weight by 15 to 30 KB on a 200 KB page and improves Largest Contentful Paint (LCP) by 50 to 150 ms on slow mobile connections. This guide walks through enabling Brotli on nginx with the ngx_brotli module, on Apache 2.4 with mod_brotli, and on managed WordPress hosts where it is already available.

Before you start: when should I use Brotli?

  • Always for static text assets: HTML, CSS, JavaScript, JSON, XML, SVG, web fonts (woff2 already includes Brotli internally, do not re compress).
  • Never for already compressed binary formats: JPEG, PNG, WebP, AVIF, MP4, WebM, ZIP, GZ, PDF. Re compressing wastes CPU and produces larger output.
  • Always combined with gzip as fallback so very old clients that do not understand br still get compressed responses.
  • Static (pre compressed) uses Brotli quality 11 (slowest, smallest output) generated at build time. Dynamic uses quality 4 to 6 at request time to balance CPU and size.

How to enable Brotli on nginx

nginx does not ship Brotli support in mainline. You need the third party module ngx_brotli by Google (latest tag in 2024) or use nginx Plus which includes it commercially.

Option A: Install pre packaged ngx_brotli (Ubuntu, Debian)

Modern Ubuntu (22.04+) and Debian (Bookworm) ship libnginx-mod-brotli as a package:

sudo apt update
sudo apt install libnginx-mod-http-brotli-filter libnginx-mod-http-brotli-static

Then edit /etc/nginx/nginx.conf inside the http block:

# Pre compressed files (.br files generated at build time)
brotli_static on;

# On the fly compression
brotli on;
brotli_comp_level 6;
brotli_min_length 256;
brotli_types
    application/atom+xml
    application/javascript
    application/json
    application/ld+json
    application/manifest+json
    application/rss+xml
    application/vnd.geo+json
    application/vnd.ms-fontobject
    application/x-font-ttf
    application/x-web-app-manifest+json
    application/xhtml+xml
    application/xml
    font/opentype
    image/bmp
    image/svg+xml
    image/x-icon
    text/cache-manifest
    text/css
    text/plain
    text/vcard
    text/vnd.rim.location.xloc
    text/vtt
    text/x-component
    text/x-cross-domain-policy;

Test and reload:

sudo nginx -t
sudo systemctl reload nginx

Option B: Compile ngx_brotli from source

If your distro does not have a package or you build a custom nginx, compile the module:

# Install build tools
sudo apt install build-essential libpcre3-dev libssl-dev zlib1g-dev libbrotli-dev git

# Get nginx source (match your installed version)
NGINX_VERSION=$(nginx -v 2>&1 | grep -oP '\d+\.\d+\.\d+')
wget https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz
tar xf nginx-$NGINX_VERSION.tar.gz
cd nginx-$NGINX_VERSION

# Get ngx_brotli
git clone --recursive https://github.com/google/ngx_brotli.git

# Build as dynamic module
./configure --with-compat --add-dynamic-module=./ngx_brotli
make modules
sudo cp objs/ngx_http_brotli_filter_module.so /etc/nginx/modules/
sudo cp objs/ngx_http_brotli_static_module.so /etc/nginx/modules/

Add load_module lines at the top of /etc/nginx/nginx.conf:

load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;

Then the same brotli directives as above.

How to enable Brotli on Apache

Apache 2.4.26 (released June 2017) and later ship with mod_brotli built in. Enable it:

sudo a2enmod brotli
sudo systemctl restart apache2

On RHEL, CentOS, Rocky Linux and AlmaLinux load it explicitly in /etc/httpd/conf.modules.d/00-brotli.conf:

LoadModule brotli_module modules/mod_brotli.so

Configure compression in /etc/apache2/conf-available/brotli.conf (or directly in a vhost):

<IfModule mod_brotli.c>
    AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/xml text/css text/javascript
    AddOutputFilterByType BROTLI_COMPRESS application/javascript application/json application/xml application/xhtml+xml application/rss+xml
    AddOutputFilterByType BROTLI_COMPRESS application/ld+json application/manifest+json
    AddOutputFilterByType BROTLI_COMPRESS image/svg+xml image/x-icon
    AddOutputFilterByType BROTLI_COMPRESS font/ttf font/otf

    BrotliCompressionQuality 5
    BrotliCompressionWindow 18
    BrotliCompressionMaxInputBlock 24

    <IfModule mod_headers.c>
        Header append Vary Accept-Encoding
    </IfModule>
</IfModule>

Enable and reload:

sudo a2enconf brotli
sudo apachectl configtest
sudo systemctl reload apache2

BrotliCompressionQuality ranges from 0 (fastest, weakest compression) to 11 (slowest, strongest). 5 is the recommended default for dynamic content. 4 is a good choice on busy shared servers.

Brotli on managed WordPress hosts

HostBrotli statusHow to enable
Cloudflare (any plan)Enabled by default since 2017Already on, no action needed
KinstaEnabled by defaultAlready on
WP EngineEnabled on Global Edge Security and CDNAlready on
SiteGroundEnabled by default in SiteGround OptimizerAlready on
CloudwaysDisabled by defaultApplication Settings » Settings & Packages » toggle Brotli
Hetzner managednginx with mod_brotli availableAdd directives in domain config
OVH Web HostingApache mod_brotli availableAdd lines in .htaccess
Bluehost, HostGator (cPanel)Often not availableUse Cloudflare in front

How do I verify Brotli is working?

  1. Open Chrome DevTools, Network tab, click any text resource (HTML, CSS, JS). Under Response Headers look for content-encoding: br.
  2. From a terminal:
    curl -I -H "Accept-Encoding: br" https://example.com/style.css | grep -i content-encoding
    # Expected: content-encoding: br
  3. Use https://tools.keycdn.com/brotli-test or https://www.giftofspeed.com/gzip-test/ for a one click web check.
  4. Lighthouse and PageSpeed Insights show "Enable text compression" under the diagnostics if Brotli is missing.

Static pre compression for maximum savings

For sites with mostly static assets (CSS bundles, JS bundles built at deploy time), pre compress the files once at build time with quality 11 and serve them with brotli_static on (nginx) or by serving .br files via Apache rewrite. Build pipeline example:

# In your build (CI/CD)
find ./dist -type f \( -name "*.html" -o -name "*.css" -o -name "*.js" -o -name "*.svg" \) \
  -exec brotli -q 11 -f {} \;

nginx then picks style.css.br automatically when the client sends Accept-Encoding: br. This shaves a further 5 to 10 percent off file size because quality 11 is impractical at request time.

Common pitfalls

  • Forgetting Vary: Accept-Encoding: CDN and proxy caches must vary on encoding, otherwise users without Brotli support get Brotli content and break.
  • Compressing images: only compress text formats. Double compression of JPEG/PNG wastes CPU and bandwidth.
  • Quality 11 at request time: only quality 4 to 6 makes sense dynamically. 11 is for build time.
  • Brotli without TLS: most browsers only request Brotli over HTTPS. Without TLS, you get gzip.
  • BREACH attack concerns: BREACH (2013) exploits compression of secrets like CSRF tokens in HTML. Mitigations: never put secrets in HTML responses, use SameSite cookies and randomize response length. The same applies to gzip, so Brotli does not make it worse.
  • Old shared hosting: some old hosts run Apache without mod_brotli. Put Cloudflare in front and let the edge handle Brotli.

Brotli vs gzip vs zstd

AlgorithmYearTypical HTML savings vs uncompressedBrowser support
gzip1992, RFC 195270 to 75 percentUniversal
Brotli2015, RFC 793275 to 80 percentAll modern browsers
zstd2016, FacebookComparable to Brotli, fasterChrome 123 (March 2024), Firefox 126 (May 2024). Encoding identifier zstd.

zstd is emerging but adoption is still limited in 2025. For now Brotli plus gzip fallback covers all browsers.

How does InspectWP help with Brotli?

InspectWP analyzes the Content-Encoding header of every requested asset and reports whether Brotli, gzip or no compression is used. The report flags large uncompressed text assets that would save bandwidth if Brotli were enabled.

Check your WordPress site now

InspectWP analyzes your WordPress site for security issues, SEO problems, GDPR compliance, and performance — for free.

Analyze your site free