Direct answer: we took the first img in DOM order on each of 25 equipment-company homepages: two pages had no image and 23 had a URL. Of those 23 URLs, 20 returned 200, two 567 and one 404; of the 20 200s, only 19 had an image/* Content-Type, one was text/html. Among the 19 usable images, 16 were PNG, two JPEG and one SVG; 11 had a positive max-age and eight had no Cache-Control. Expanding to the first four images per page: of 94 slots, 68 returned 200 (64 image/*), 19 returned 567, four 404, one request error and two pages had no image; among the 64 usable images, 32 were cacheable and 32 had no Cache-Control.
The 11 cacheable images used 14 days (4), 30 days (3), one year (3) and 5 minutes (1); the median was 30 days. All 19 usable images had Last-Modified and ETag, but a validator is not an explicit max-age; the eight without Cache-Control depend on heuristic caching.
Method: first image, HEAD first, GET fallback
We reused the 25 cached homepages from study 4 and took the first img src in DOM order that was not data:/blob:/javascript:; whether it is the product hero was not judged. On 2026-11-07 at 23:41 each received one request, HEAD first with Accept-Encoding: gzip, br and Referer; HEAD returning 400/403/405/501 or failing fell back to GET. We recorded status, method, Cache-Control, max-age, ETag, Last-Modified, Vary, Content-Encoding, Content-Type, length, Age, Server and CDN markers.
“Usable image” requires 200 and an image/* Content-Type; a 200 HTML response does not count. Cache policy: max-age > 0 cacheable; no-store/private/no-cache private; max-age=0 separate; no header = missing.
| Item | Count |
|---|---|
| Homepages | 25 |
| With an img URL | 23 |
| No image | 2 (E18, E20) |
| 200 | 20 |
200 with image/* | 19 |
| 200 but HTML | 1 (E17) |
| 567 | 2 (E09, E22) |
| 404 | 1 (E24) |
| Cacheable among usable images | 11 |
| No Cache-Control among usable images | 8 |
Result: 19 usable images, 11 cacheable
| Page | Status / type | Policy / max-age | Source |
|---|---|---|---|
| E01 | 200 image/png | missing / — | same-origin |
| E02 | 200 image/png | missing / — | same-origin |
| E03 | 200 image/png | cacheable / 14d | same-origin |
| E04 | 200 image/png | cacheable / 1y | same-origin |
| E06 | 200 image/png | cacheable / 14d | same-origin |
| E08 | 200 image/png | missing / — | same-origin |
| E09 | 567 text/markdown | missing / — | external |
| E11 | 200 image/png | cacheable / 30d | same-origin |
| E12 | 200 image/png | cacheable / 30d | same-origin |
| E13 | 200 image/png | missing / — | same-origin |
| E14 | 200 image/png | cacheable / 14d | same-origin |
| E16 | 200 image/png | cacheable / 1y | external |
| E17 | 200 text/html | missing / — | same-origin |
| E18 | no image | — | — |
| E19 | 200 image/png | missing / — | same-origin |
| E20 | no image | — | — |
| E22 | 567 text/markdown | missing / — | external |
| E23 | 200 image/png | cacheable / 14d | same-origin |
| E24 | 404 text/html | private / — | same-origin |
| E25 | 200 image/png | cacheable / 1y | same-origin |
| E26 | 200 image/png | missing / — | same-origin |
| E27 | 200 image/png | missing / — | same-origin |
| E28 | 200 image/png | cacheable / 30d | same-origin |
| E29 | 200 image/png | cacheable / 5m | same-origin |
| E30 | 200 image/png | missing / — | same-origin |
Among the 19 usable images, 16 were PNG, two JPEG and one SVG; 11 were cacheable and eight had no Cache-Control. Three first images were external: E09 and E22 returned 567, while E16 returned 200 with a one-year max-age. E17's first URL returned 200 with a text/html Content-Type, not an image; E24's 404 carried private/no-cache.
Expanded to four images: 64/94 usable, 19 567s
To see whether later images are worse, we took the first four unique img src in DOM order on the same 25 pages, 94 slots in total (E18/E20 have no image, so two empty slots; the other 23 pages have four each). Each was requested once on 2026-11-08 at 00:42 with the same method as the first-image pass.
Result: 68 200, 19 567, four 404 and one request error. Of the 68 200s, 64 were image/* (PNG 41, JPEG 19, SVG 4) and four were 200 HTML (E17's four). All 19 567s were external H1 images: E03/E06/E09/E14/E23 have three each and E22 four; E24's four are all 404; E04's fourth failed request-header encoding because the URL contains non-ASCII characters and is recorded as an error.
Among the 64 usable images, 32 had a positive max-age and 32 had no Cache-Control; cacheable max-age was 30 days (12), one year (11), 14 days (5) and 5 minutes (4), median 30 days. Of the 68 200s, 64 had ETag/Last-Modified, but validators still do not replace explicit max-age.
| Page | Usable | 567 | 404 / error | Cacheable | No CC |
|---|---|---|---|---|---|
| E01 | 4 | 0 | 0 | 0 | 4 |
| E02 | 4 | 0 | 0 | 0 | 4 |
| E03 | 1 | 3 | 0 | 1 | 0 |
| E04 | 3 | 0 | 1 error | 3 | 0 |
| E06 | 1 | 3 | 0 | 1 | 0 |
| E08 | 4 | 0 | 0 | 0 | 4 |
| E09 | 1 | 3 | 0 | 1 | 0 |
| E11 | 4 | 0 | 0 | 4 | 0 |
| E12 | 4 | 0 | 0 | 4 | 0 |
| E13 | 4 | 0 | 0 | 0 | 4 |
| E14 | 1 | 3 | 0 | 1 | 0 |
| E16 | 4 | 0 | 0 | 4 | 0 |
| E17 | 0 | 0 | 0 (4× 200 HTML) | 0 | 0 |
| E18 | 0 | 0 | 0 | 0 | 0 |
| E19 | 4 | 0 | 0 | 0 | 4 |
| E20 | 0 | 0 | 0 | 0 | 0 |
| E22 | 0 | 4 | 0 | 0 | 0 |
| E23 | 1 | 3 | 0 | 1 | 0 |
| E24 | 0 | 0 | 4 | 0 | 0 |
| E25 | 4 | 0 | 0 | 4 | 0 |
| E26 | 4 | 0 | 0 | 0 | 4 |
| E27 | 4 | 0 | 0 | 0 | 4 |
| E28 | 4 | 0 | 0 | 4 | 0 |
| E29 | 4 | 0 | 0 | 4 | 0 |
| E30 | 4 | 0 | 0 | 0 | 4 |
Key change: the first image had only two 567s, while the first four have 19; E03/E06/E14/E23 are “one same-origin + three H1 567s”, and E22 is four 567s. A usable first image does not mean images 2–4 are usable; checking only the first image underestimates external-image risk.
Three ways to misread it
- 200 is not an image. E17 returned 200 with HTML; counting status alone raises the usable count from 19 to 20. Check Content-Type and magic bytes.
- 567 is not a cache-policy problem. E09 and E22 returned 29–30 bytes of
text/markdown, with no image bytes and no Cache-Control; do not call them “uncacheable images”. - ETag is not max-age. All 19 usable images had Last-Modified and ETag, but eight still had no Cache-Control; a validator only answers whether the resource changed.
What this means for acceptance
- Validate Content-Type and bytes before calling an image usable. 200 +
image/*; record 200 HTML, 567 and 404 separately. - Give images explicit Cache-Control. Eight of 19 usable images had none; at least separate fingerprinted assets from replaceable campaign images.
- Version URLs before long caching. Three of the 11 cacheable images use one year and three use 30 days; without a fingerprint, long caching makes replacement harder.
- Watch external first images. Two of the three external images returned 567; a CDN change directly hits the first screen.
- The first image is not all images, nor the first four. 567s rise from two to 19 across the first four slots; all 958 still need their own check.
Limits
- 25-site pilot: the same homepage cache; not the industry and not all 958 images.
- First four only: 25 pages × 4 slots = 94; not the product hero or all 958 images; one URL request error.
- HEAD first: E19 and E29 used GET fallback; methods are recorded, and tool failures are not treated as policy.
- One snapshot: 2026-11-07 23:41; no redesign, CDN edge or regional recheck.
- Headers only: TTFB, rendering, LCP and real browser cache hits were not measured.
Data and reproduction
Anonymised data: equipment-homepage-first-image-cache-2026.csv (25 rows × 19 columns: found, external, status, method, Cache-Control, policy, max-age, ETag, Last-Modified, Vary, encoding, Content-Type, length, Age, Server, CDN, error, time). In-repo copy: docs/research/2026-11-homepage-first-image-cache.csv. First-four expansion: equipment-homepage-first-four-images-2026.csv (94 rows × 19 columns: image index, external, status, method, Cache-Control, policy, max-age, ETag, Last-Modified, Vary, encoding, Content-Type, length, Age, Server, CDN, error, time). In-repo copy: docs/research/2026-11-homepage-first-four-images.csv.
Collection: Python urllib, HEAD first and GET fallback, with Accept-Encoding: gzip, br and Referer; the policy classifier is evaluate() from scripts/cache_compression_probe.py. Site names and full URLs are not published.
Related: the homepage resource inventory pilot, the homepage CSS/JS cache-header pilot, and the homepage image-delivery pilot.
Sources and definitions
- Sample: 25 homepage caches from study 4 (2026-10-31); the first img in DOM order on each page.
- Requests: 2026-11-07 23:41, HEAD first with GET fallback, 25 requests.
- Usable image: 200 with an
image/*Content-Type; 200 HTML, 567 and 404 are separate.
Frequently asked questions
Does 200 mean an image is usable?
No. All four E17 images returned 200 with a text/html Content-Type; check image/* and the bytes.
Why are there 19 567s?
The 19 external images on six sites all come from host H1: E03/E06/E09/E14/E23 have three each and E22 has four; a usable first image does not mean the 2nd–4th are usable.
What is the cache policy across the 64 usable images?
32 had a positive max-age and 32 had no Cache-Control; the cacheable median was 30 days (30 days 12, one year 11, 14 days 5, 5 minutes 4).
Can ETag / Last-Modified replace Cache-Control?
No. Of 68 200s, 64 had ETag/Last-Modified, but 32 usable images still had no explicit max-age; a validator only answers whether the resource changed.
What is the one error?
E04's fourth image URL contains non-ASCII characters and the request-header encoding failed; it is recorded as error, not 404 or 567, and no server cause is inferred.
Why only the first four images?
25 pages × 4 slots = 94; it shows a first-screen group, not all 958 images, and does not judge hero-image semantics.
Why keep the first-image section?
It is retained as a baseline while the four-image pass checks whether later images are worse; neither is a whole-site total.
Can the data be reproduced?
Yes. The 25-row first-image CSV and the 94-row first-four CSV are in the repository and record status, method, Cache-Control, max-age, ETag, Last-Modified, Vary, encoding, Content-Type and error; site names and full URLs are not published.
Related: the homepage canonical and og:url pilot.