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
brstill 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-staticThen 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 nginxOption 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 apache2On RHEL, CentOS, Rocky Linux and AlmaLinux load it explicitly in /etc/httpd/conf.modules.d/00-brotli.conf:
LoadModule brotli_module modules/mod_brotli.soConfigure 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 apache2BrotliCompressionQuality 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
| Host | Brotli status | How to enable |
|---|---|---|
| Cloudflare (any plan) | Enabled by default since 2017 | Already on, no action needed |
| Kinsta | Enabled by default | Already on |
| WP Engine | Enabled on Global Edge Security and CDN | Already on |
| SiteGround | Enabled by default in SiteGround Optimizer | Already on |
| Cloudways | Disabled by default | Application Settings » Settings & Packages » toggle Brotli |
| Hetzner managed | nginx with mod_brotli available | Add directives in domain config |
| OVH Web Hosting | Apache mod_brotli available | Add lines in .htaccess |
| Bluehost, HostGator (cPanel) | Often not available | Use Cloudflare in front |
How do I verify Brotli is working?
- Open Chrome DevTools, Network tab, click any text resource (HTML, CSS, JS). Under Response Headers look for
content-encoding: br. - From a terminal:
curl -I -H "Accept-Encoding: br" https://example.com/style.css | grep -i content-encoding # Expected: content-encoding: br - Use
https://tools.keycdn.com/brotli-testorhttps://www.giftofspeed.com/gzip-test/for a one click web check. - 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
| Algorithm | Year | Typical HTML savings vs uncompressed | Browser support |
|---|---|---|---|
| gzip | 1992, RFC 1952 | 70 to 75 percent | Universal |
| Brotli | 2015, RFC 7932 | 75 to 80 percent | All modern browsers |
| zstd | 2016, Facebook | Comparable to Brotli, faster | Chrome 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.