🌐

CDN Coverage

Performance Auditor

Checks if your website content is served through a CDN

PerformanceDeliveryResilience
30 credits
Per check
~30 seconds
Average runtime
Active
Status

Run this auditor

3 of 3 free audits left today

See what CDN Coverage finds on your site. No sign-up needed.

How it works

  1. Fetch β€” downloads the audited URL once as 37AuditsBot. A blocked request ends the audit with 590; an IOException or an HTTP status of 400 or higher ends it with 500.

  2. Discover β€” parses the HTML and collects every first-load asset: link[rel=stylesheet], script[src], img[src], every candidate of img[srcset], font preloads (link[rel=preload][as=font] and link[type*=font]), video[src] and source[src]. URLs are normalized the way browsers accept them (spaces, | and non-ASCII characters are percent-encoded). Inlined data: URIs never leave the HTML, so they are listed but not judged.

  3. Classify β€” a resource is on a CDN when, in this order, its hostname ends with a known CDN suffix (.cloudfront.net, .cloudflare.net, .fastly.net, .akamaihd.net, .azureedge.net, .b-cdn.net and others), its response carries a CDN fingerprint header (cf-cache-status, x-amz-cf-id, server: cloudflare, server: AkamaiGHost, via: … cloudfront, x-served-by: cache-… and others), or its CNAME chain ends on a known CDN hostname. The HTML is classified from the response already fetched; each asset on an unknown hostname is probed with a HEAD request (GET when HEAD is refused). An asset whose probe throws counts as on a CDN when its CNAME points to one, otherwise it is reported with 501 and left out of the decision.

  4. Rules β€” when no resource at all is on a CDN, every backend resource fails (400). When at least one resource is on a CDN, every backend resource warns (300).

  5. Aggregate β€” FAIL wins over WARNING; when every probed resource is on a CDN the audit is SUCCESS (200), with the counts, the detection method of each resource and the inlined data URIs in the check data. A page whose HTML is on a CDN and whose assets all failed to probe is SUCCESS with the 501 checks attached.

Preferences

KeyTypeDefaultDescription
evaluateExternalResourcesbooleantrueWhen false, resources served from a host other than the audited site or one of its subdomains (www. ignored) are not probed or counted; the HTML and the site's own assets decide the result. Each one left out is listed as an INFORMATION check, 37A-CDNCoverageAuditor-100. Set it per monitored URL on the Configuration tab.

An invalid value (anything but a boolean or "true"/"false") makes the auditor fall back to the default and log a warning.

What this auditor validates

Every row maps to one checkRule* method and one CheckCode, in the order the auditor runs them. CheckCode suffixes use status ranges: 200 success, 300–399 warning, 400–499 fail, 500–599 error.

CheckCodeStatusWhen it firesRecommendationWhy it matters
37A-CDNCoverageAuditor-400FAILOne check per resource served directly from the backend when no resource of the page at all is on a CDN.Put {host} behind a CDN such as Cloudflare, CloudFront, Fastly or Akamai so {resource} is delivered from an edge close to the visitor.Without a CDN every visitor downloads the page and its assets from the origin server, so pages load slower for people far from it, traffic spikes hit the origin directly and the site is easier to take down.
37A-CDNCoverageAuditor-300WARNINGOne check per resource served directly from the backend when at least one other resource of the page is on a CDN.Serve {resource} through the CDN that already delivers the rest of {url}, for example by routing {host} through it.Assets that bypass the CDN load slower than the rest of the page and keep the origin exposed to traffic spikes, so the CDN cannot deliver its full performance and resilience benefit.
37A-CDNCoverageAuditor-501ERROROne check per asset whose probe threw (timeout, DNS, TLS, refused connection) while its CNAME chain does not point to a CDN. The asset is left out of the 300 / 400 decision.Make sure {resource} answers HTTP requests from 37AuditsBot, then run the audit again. Last error: {error}.β€”
37A-CDNCoverageAuditor-200SUCCESSEvery probed resource (the HTML and each discovered asset) is served through a CDN. Message gives the resource count, the number of assets that could not be probed and the number of inlined data URIs; data lists the detection method (hostname, headers or cname) of each resource.β€”β€”
37A-CDNCoverageAuditor-500ERRORThe audited page could not be fetched (timeout, DNS, TLS, or an HTTP status of 400 or higher other than a block).Make sure {url} answers with HTTP 2xx, then run the audit again. Last error: {error}.β€”
37A-CDNCoverageAuditor-590ERRORThe audited page answered HTTP 403, HTTP 429 or a Cloudflare challenge, so 37AuditsBot was blocked before it could read the page.Allow 37AuditsBot in your firewall or bot protection: allowlist its user agent, or verify its Web Bot Auth signature. See https://www.37audits.com/bot.While 37AuditsBot is blocked this audit cannot look at the site, so problems on it go unreported.
37A-CDNCoverageAuditor-100INFORMATIONevaluateExternalResources is false: one check per asset that was not probed, served from a host other than the audited site or one of its subdomains. The check's resource is that URL; data carries host, siteHost and evaluateExternalResources: false. Message: Not evaluated: the resource {resource} is served from {host}, outside {siteHost}, and Evaluate external resources is off. Never changes the result's status.Turn on Evaluate external resources for this monitored URL to assess third-party resources too.β€”

Every per-resource check carries resource, kind (html, stylesheet, script, image, font or media), cdnDetection (hostname, headers, cname or none) and httpStatus (null when the resource was not requested) in its data. The 200 check adds resourceCount, cdnCount, inlinedCount, inlinedResources and the per-resource list.

Output Documentation

StatusDescriptionTest logic
SUCCESSThe page and every asset it loads are on a CDNNo probed resource is served from the backend (200). Assets whose probe failed (501) do not count against the page.
WARNINGSome resources bypass the CDNAt least one resource is on a CDN and at least one is served from the backend; one 300 check per backend resource.
FAILNothing is on a CDNNo resource is on a CDN; one 400 check per backend resource (the HTML included).
ERRORThe auditor could not read the pageFetch failure or HTTP 400+ on the audited page (500); site blocked 37AuditsBot (590). A failed asset probe (501) is attached to the result but does not make it ERROR.

Risks and Considerations

Why CDN coverage matters

  • Visitors far from the origin server wait for every byte to cross the distance; a CDN edge answers from nearby and cuts load time, which drives conversions and search rankings.

  • The origin only sees cache misses, so a traffic spike, a viral post or a volumetric attack is absorbed at the edge instead of taking the site down.

  • One asset that bypasses the CDN is enough to keep the page waiting and the origin exposed, which is why the audit looks at every first-load asset and not only at the HTML.

How CDNs are recognised

  • A known hostname suffix is trusted without a request, so assets on *.cloudfront.net, *.fastly.net or *.b-cdn.net are never fetched.

  • Header fingerprints cover the major providers (Cloudflare, CloudFront, Akamai, Fastly, Imperva, Google). A CDN configured to strip its headers on a custom domain is only found through its CNAME chain.

  • The CNAME chain is followed through DNS for up to ten hops. A CDN reached through an A record on the customer's own domain (for example an anycast setup with no CNAME) is not recognised, and that resource is reported as served from the backend.

Behavior changes in this version

  • A page that cannot be fetched (timeout, DNS, TLS, HTTP 400 or higher) is now ERROR with 500; it used to be reported as FAIL.

  • Mixed coverage now emits one WARNING check with 300 per backend resource; the result stays WARNING as before.

  • An asset whose probe fails is now a 501 ERROR check that is left out of the decision; it used to push the result to WARNING on its own.

  • The page is fetched once and ensureNotBlocked runs before any asset is probed; the old auditor probed the page before the block check and then fetched it a second time.

  • Assets on a CDN no longer get one SUCCESS check each; the 200 check lists them in its data instead.

  • srcset candidates are now read the way the HTML Standard does (a URL runs to the first whitespace), so an inlined data: URI with commas stays whole instead of producing a bogus backend resource from its second half.

What this auditor does not check

  • Only the first-load assets written in the HTML are discovered; resources requested by scripts, CSS url() references and lazy-loaded images are not followed.

  • Whether the CDN actually caches the resource (hit ratio, Cache-Control) is left to the Cache auditor.

  • Third-party assets (analytics, tag managers, embeds) are probed like any other asset; moving them is often not in the site owner's hands.

This documentation is built and hosted on Mintlify, a developer documentation platform.

Source: docs.37audits.com

Ready to start auditing?

Add this auditor to your monitoring setup and start identifying issues on your websites today.

Β© 2026 37 Audits. All rights reserved. Audit your websites with confidence.

Supported by

Made with ❀️ in Floripa