Direct answer: on 2026-11-07 we made one request to each of the 13 product entry pages from study 104 with Accept-Encoding: gzip, br. All 13 returned 200 and Content-Encoding: gzip. Their cached raw HTML totals 1,184,145 bytes; measured wire bodies total 162,817 bytes (159.0 KB), only 13.7% of the raw files, with a per-page median of 17.2%. Local recompression gives 153,128 bytes at gzip -9 and 113,597 bytes at Brotli-11; the Brotli estimate is 30.2% below the measured gzip transfer, but the servers did not choose Brotli in this test. In a 13:40 br-only recheck, all 13 returned uncompressed and none returned Brotli, so 30.2% remains a local estimate with no evidence of Brotli support on these pages.
Compression is not a yes/no flag but a range: all 13 pages used gzip, yet the per-page wire share runs from 9.4% to 34.5%, a 3.7× spread. Judging a product page only by raw HTML understates the difference, and assuming “gzip is on” means “fully compressed” misses the remaining gap.
Method: one real negotiation plus one local recompression
The sample is the 13 product entry-page caches from study 104 (captured 2026-11-01; P04/P14 have no product link). From 12:41 on 2026-11-07 each page was requested once with Accept-Encoding: gzip, br; we recorded HTTP status, Content-Encoding, Content-Type, wire bytes and the body decoded by that encoding. Requests were sequential with a 1.5-second gap.
The local pass recompresses the cached raw files: gzip at -9, Brotli at quality=11. That is an upper-bound estimate, not what any server sent. Wire bytes are HTTP message-body bytes and exclude TLS/TCP headers; TTFB, cache hits and CDN origin behaviour were not measured.
At 13:40 we rechecked the same pages: first with only Accept-Encoding: br, then with gzip, br. The br-only pass is a capability test, not the normal browser negotiation. The two passes were about 60 minutes apart and sequential.
| Item | Definition | Boundary |
|---|---|---|
| Measured transfer | Message-body bytes of one GET | TLS/TCP headers excluded |
| Decoded bytes | Body decompressed by Content-Encoding | Compared with the cached raw file |
| Local gzip / Brotli | Recompress cached file, gzip -9 / Brotli-11 | Lab estimate, not live output |
| Cache match | Decoded bytes exactly equal the 2026-11-01 cache | Bytes only, not DOM |
Result: 13/13 gzip, wire at 13.7% of raw
| Metric | Total / median | Of cached raw |
|---|---|---|
| HTTP 200 | 13 / 13 | — |
| Content-Encoding: gzip | 13 | 100% |
| Content-Encoding: br | 0 | 0% |
| br-only returned br | 0 | 0% |
| br-only returned uncompressed | 13 | 100% |
| Cached raw bytes | 1,184,145 | 100% |
| Measured wire bytes | 162,817 | 13.7% |
| One-hour gzip recheck wire bytes | 162,819 | 13.7% |
| Recheck vs 12:41 | +2 B | 0.0% |
| Median per-page wire share | 17.2% | — |
| Local gzip -9 | 153,128 | 12.9% |
| Local Brotli-11 | 113,597 | 9.6% |
| Brotli vs measured gzip | 113,597 / 162,817 | 30.2% lower |
| Decoded bytes exactly matching cache | 10 / 13 pages | — |
Mind the denominator: study 106 split 1,179,680 bytes after newline normalisation, while this study uses the 1,184,145-byte cached files; the 4,465-byte (0.4%) difference comes from CRLF versus LF. “Raw bytes” here always means the cached file size, so it can be aligned page by page with the decoded bytes.
Page-by-page (13 pages)
| Page | Cached KB | Wire KB | Wire % | gzip -9 | Brotli -11 | Cache match |
|---|---|---|---|---|---|---|
| P01 | 7.9 | 2.7 | 33.9% | 33.9% | 23.6% | yes |
| P02 | 232.4 | 22.0 | 9.4% | 7.4% | 5.2% | yes |
| P03 | 159.3 | 13.7 | 26.9% | 11.5% | 8.1% | no (-110,967 B) |
| P05 | 158.0 | 18.4 | 11.7% | 9.8% | 7.1% | no (-92 B) |
| P06 | 100.7 | 17.0 | 16.8% | 16.6% | 12.9% | yes |
| P07 | 93.8 | 15.8 | 16.9% | 15.0% | 10.9% | yes |
| P08 | 29.5 | 7.8 | 26.6% | 23.9% | 18.8% | yes |
| P09 | 41.1 | 7.1 | 17.2% | 16.6% | 13.0% | yes |
| P10 | 14.8 | 3.5 | 23.4% | 23.4% | 17.2% | yes |
| P11 | 94.9 | 15.7 | 16.5% | 14.1% | 10.4% | no (-16 B) |
| P12 | 13.4 | 4.6 | 34.5% | 26.3% | 19.9% | yes |
| P13 | 170.4 | 23.2 | 13.6% | 13.6% | 10.4% | yes |
| P15 | 40.2 | 7.6 | 19.0% | 18.8% | 14.5% | yes |
Three tails: P12 is only 13.4 KB raw but 34.5% on the wire, the worst small page; P01 at 7.9 KB is 33.9%. P02 is 232.4 KB raw but 9.4% on the wire, because repeated markup and whitespace compress well. P03 does not match the cache: its decoded body is 52,121 bytes, 110,967 fewer, so its 26.9% reflects changed content and cannot be compared with the cached recompression rate.
“gzip on” is not “fully compressed”
Among the 10 pages whose decoded bytes exactly match the cache, measured gzip totals 113,904 bytes versus 104,780 bytes for local gzip -9, 8.7% higher. Most pages sit near 100% (P01 100.1%, P10 100.0%, P13 100.4%), but P12 is 131.0%, P02 126.8%, P07 112.1% and P08 111.3%. That may reflect the server's compression level or implementation; we did not inspect server configuration, so the cause is not asserted. It does show headroom even after gzip is enabled.
The 30.2% Brotli figure is a local -q 11 estimate on the same cached files. Every server chose gzip when both gzip and br were offered; at 13:40, when only br was offered, all 13 returned uncompressed and none returned br. That number is only an upper bound “if Brotli were enabled”, not an online saving, and there is no evidence of Brotli support on these 13 pages; enabling it would require a server/CDN change followed by a fresh test.
One-hour recheck: gzip stable, br-only all uncompressed
At 13:40 on 2026-11-07 we rechecked the same 13 pages: first with only Accept-Encoding: br, then with gzip, br. 0/13 returned br; all 13 br-only responses had no Content-Encoding and sent uncompressed HTML, while gzip, br still returned gzip on 13/13.
The br-only pass transferred 1,073,070 bytes, 6.6× the 162,819 bytes of the gzip recheck. Normal browsers usually advertise gzip too, so this is not the ordinary user path; it does show that Brotli cannot be assumed as an automatic fallback. The gzip recheck was only 2 bytes above 12:41 and all 13 decoded bodies matched 12:41, so content was stable within the hour.
| Page | br-only encoding | br-only KB | gzip recheck KB | Δ vs 12:41 | Decoded match |
|---|---|---|---|---|---|
| P01 | uncompressed | 7.9 | 2.7 | 0 | yes |
| P02 | uncompressed | 232.4 | 21.9 | -1 | yes |
| P03 | uncompressed | 50.9 | 13.7 | +4 | yes |
| P05 | uncompressed | 157.9 | 18.4 | 0 | yes |
| P06 | uncompressed | 100.7 | 17.0 | 0 | yes |
| P07 | uncompressed | 93.8 | 15.8 | 0 | yes |
| P08 | uncompressed | 29.5 | 7.8 | +1 | yes |
| P09 | uncompressed | 41.1 | 7.1 | +1 | yes |
| P10 | uncompressed | 14.8 | 3.5 | -1 | yes |
| P11 | uncompressed | 94.9 | 15.7 | 0 | yes |
| P12 | uncompressed | 13.4 | 4.6 | -2 | yes |
| P13 | uncompressed | 170.4 | 23.2 | 0 | yes |
| P15 | uncompressed | 40.2 | 7.6 | 0 | yes |
Comparison with homepages and article pages
| Sample | Encoding mix | Median wire share | Frame |
|---|---|---|---|
| 13 product pages | gzip 13; br-only 0 | 17.2% | study-104 product entry pages |
| 14 homepages | gzip 12 / br 1 / none 1 | 21.0% | homepage pilot |
| 10 article pages | gzip 10 | 26.9% | article live subsample |
The three frames and capture times differ, so the median gap is not a page-type effect. What is clear: this product batch has full gzip coverage (13/13), but per-page compression varies widely; a site-wide average would hide the small-page overhead and the large-page gains.
What this means for acceptance
- Check wire/decoded, not only raw HTML. These 1.18 MB of raw files travelled as 159 KB; raw size alone overstates the transfer burden.
- Confirm the encoding negotiation. Send
Accept-Encoding: gzip, brwith a fixed UA and record the actual Content-Encoding; this br-only recheck returned 0/13 br and 13/13 uncompressed, so test both requests. - Inspect compression level or implementation. On the 10 matching pages the live gzip was 8.7% above local -9; P12 and P02 were over 26% above, worth asking the server or CDN about.
- Watch small pages too. P01/P12 are 33.9%/34.5% on the wire; fixed overhead matters more there, so optimising only large pages misses them.
- Exclude content changes. P03 decoded 110,967 bytes fewer than the cache, so its ratio is not comparable; re-cache after a redesign before comparing.
Limits
- 13-page pilot: the same product entry pages as study 104; not all product pages on the sites and not an industry estimate.
- Limited request count: one per page at 12:41 and two per page at 13:40; longer-term variation, CDN hits and regions were not tested.
- br-only was tested but remains narrow: 0/13 returned br and 13/13 were uncompressed; this describes these 13 pages in two passes, not every path or CDN.
- Local recompression is an estimate: gzip -9 / Brotli-11 are lab upper bounds, not live settings; CPU cost was not measured.
- Limited byte scope: HTTP message body only; TLS/TCP headers, request headers, DNS, TTFB and rendering are excluded.
- Content snapshot: the cache is from 2026-11-01; P03/P05/P11 differ, and all 13 decoded bodies matched 12:41 in the one-hour recheck.
Data and reproduction
Anonymised data: first pass equipment-product-entry-html-compression-2026.csv (13 rows × 16 columns); one-hour recheck equipment-product-entry-html-compression-recheck-2026.csv (13 rows × 13 columns: br-only encoding and bytes, gzip recheck bytes, delta from the first pass, decoded match). In-repo copies: docs/research/2026-11-product-entry-html-compression.csv and docs/research/2026-11-product-entry-html-compression-recheck.csv.
Parser: scripts/article_html_compression_probe.py (live records the negotiation and wire/decoded bytes; local recompresses at gzip -9 / Brotli-11); tests: scripts/test_article_html_compression_probe.py (7 tests). Run:
python -m unittest discover -s scripts -p "test_article_html_compression_probe.py"
Related: the product entry HTML composition pilot, the product entry image-delivery pilot, and the homepage HTML compression pilot.
Sources and definitions
- Sample: 13 product entry-page caches from study 104 (captured 2026-11-01; P04/P14 have no product link).
- Live: one GET per page from 12:41 on 2026-11-07 (Asia/Shanghai),
Accept-Encoding: gzip, br, 1.5 s apart. - Local: cached raw files recompressed with gzip -9 / Brotli-11; site and product URLs are not published.
Frequently asked questions
Does 13/13 gzip mean Brotli is unsupported?
No. In normal negotiation all 13 chose gzip; when only br was offered at 13:40 on 2026-11-07, all 13 returned uncompressed and none returned br. These 13 pages show no Brotli support, but that cannot be generalised to every path or CDN.
How do 162,817 bytes relate to 1.18 MB?
1,184,145 is the cached raw HTML; 162,817 is the measured HTTP message body. The ratio is 13.7%; the HTML was not deleted, it was compressed on the wire.
Why is P03's wire share not comparable with the cache?
P03 decoded to 52,121 bytes, 110,967 fewer than the cache, so its content changed. Its 26.9% describes the new page, not the cached file.
Can the local 30.2% Brotli saving be reported as an online saving?
No. Brotli-11 is a lab recompression; the br-only test returned no br on any of the 13 pages. 30.2% is an “if enabled” upper bound, with deployment and CPU cost unverified.
Is there anything left to optimise after gzip?
Check the level. On 10 byte-identical pages, live gzip totalled 8.7% above local -9; P12/P02 were 31.0%/26.8% above, suggesting a level or implementation difference.
Is the one-hour recheck stable?
Yes at the byte level: all 13 still returned gzip at 13:40, and every decoded body matched 12:41. Wire bytes totalled 162,819, 2 bytes more than 12:41; per-page changes were -2 to +4 bytes.
Can the data be reproduced?
Yes. The 13-row × 16-column first-pass CSV, the 13-row × 13-column recheck CSV and seven offline compression/decoding tests are in the repository; site and product URLs are not published.