Gzip compression reduces the size of HTML, CSS, and JS files by 60–80% before sending them to the browser. It's one of the fastest ways to improve PageSpeed without changing any code.
Enable gzip via .htaccess
<IfModule mod_deflate.c>
# Enable compression for text types
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE application/json
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE application/x-font-ttf
AddOutputFilterByType DEFLATE font/opentype
# Don't compress already-compressed formats
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|webp|zip|gz)$ no-gzip
</IfModule>
Checking compression
After adding the code, check that compression is working:
- Open gzip-test online
- Or in Chrome DevTools: Network → select the document → Headers →
Content-Encoding: gzip
Brotli: even better than gzip
Brotli compresses 15–20% better than gzip. On cPanel, Brotli is enabled in the Software → Optimize Website section.
# If mod_brotli is available:
<IfModule mod_brotli.c>
AddOutputFilterByType BROTLI_COMPRESS text/html text/css application/javascript
</IfModule>
Browser caching
Along with compression, set up caching — it speeds up repeat visits even further:
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 month"
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
</IfModule>
Common mistakes when enabling compression
Most compression problems show up right away in the response headers or the Apache logs.
Invalid command 'SetEnvIfNoCase', perhaps misspelled or defined by a module not included in the server configuration
The mod_setenvif module isn't enabled on the server, even though .htaccess already has a rule using it. Some shared hosting plans restrict which modules are allowed — remove the SetEnvIfNoCase line, or contact support to check which Apache modules are enabled.
ERR_CONTENT_DECODING_FAILED
The browser received a Content-Encoding: gzip header, but the response body wasn't compressed, or was compressed twice — typical when compression is enabled both at the cPanel level (Optimize Website) and manually in .htaccess. Keep only one layer of compression, not both.
PageSpeed Insights: "Enable text compression" — still flagged
Seeing this after editing .htaccess usually means you're testing a cached page version behind a CDN or proxy in front of the hosting (Cloudflare, for instance), which strips the origin server's compression headers and repackages the response its own way. Check headers directly against the origin, bypassing the CDN, or purge the CDN cache.
gzip vs Brotli comparison
| Parameter | gzip | Brotli |
|---|---|---|
| HTML/CSS/JS compression ratio | 60-80% | 65-85% |
| CPU load while compressing | Lower | Higher at maximum level |
| Browser support | All browsers | All modern browsers |
| Availability on shared hosting | Almost everywhere | Not on every plan |
The gap between gzip and Brotli shows up on large text files — on a typical 50-100 KB page, the gain is just a few kilobytes, and it's easy to lose that gain with a poorly configured compression level (Brotli's maximum level creates noticeable CPU load on every first uncached request).
When compression won't help
Images (JPEG, PNG, WebP), video, and already-archived files (ZIP, GZ) shouldn't be compressed — they already use their own compression algorithms, and recompressing them either doesn't shrink the size or grows it because of the added headers. The SetEnvIfNoCase Request_URI ... no-gzip rule in the example above exists exactly for this — don't skip it. If the provider has disabled mod_deflate entirely at the server level (common on some budget plans), edits to .htaccess won't change anything — you need support to confirm the module is available.
How to verify the result
The server's response headers are the most reliable source — more reliable than the visual indicators in online tests:
curl -H "Accept-Encoding: gzip, br" -I https://example.com/ | grep -i "content-encoding\|content-length"
A Content-Encoding: gzip or br header in the response confirms compression is working. Also compare Content-Length with and without compression — a difference of several times for text files confirms the effect. If the header is missing despite explicitly sending Accept-Encoding, compression isn't active, regardless of the config edits.