DNS-Prefetch Hints for Non-Critical Third-Party Domains
Issue No: 114
Category: Resource Hints & Performance Issue Type: Suggestion Priority: Standard
Description
Pages that load resources from third-party domains should declare <link rel="dns-prefetch"> hints so the browser can resolve DNS for those domains early, reducing lookup latency. Unlike preconnect, dns-prefetch only resolves DNS without opening a TCP or TLS connection, making it suitable for origins where a full preconnect would be excessive.
The XeoPix crawler identifies external domains by scanning resource URL attributes across <script>, <link>, <img>, and <source> tags in the raw HTML, comparing each hostname against the page's own crawled origin. It then checks whether each external hostname is covered by either a preconnect hint (which implies dns-prefetch) or an explicit dns-prefetch hint. The trigger only fires when uncovered external domains are actually found in the HTML.
How Do We Capture It
Where to Find
Inside HTML <head>:
<link rel="dns-prefetch" href="//analytics.example.com">
<link rel="dns-prefetch" href="https://ads.partner.com">
HTML Extraction Flow
The XeoPix crawler downloads the raw HTML response and parses the <head> block:
- Issues an HTTP GET to the target URL.
- Reads raw response bytes without JavaScript execution.
- Scans the
<head>block for all<link>tags. - Filters for tags where
relequalsdns-prefetch. - Extracts the
hrefattribute from each matched tag. - Normalizes each href to extract the hostname (strips path and query if present).
- Collects all dns-prefetch hostnames into an array and records the total count.
- Scans all
<script src>,<link href>,<img src>, and<source src>attributes across the full HTML document. - Extracts the hostname from each resource URL.
- Compares each hostname against the page's own crawled origin to identify external domains.
- Builds a covered-hostnames set from both
<link rel="preconnect">and<link rel="dns-prefetch">hrefs (preconnect already implies DNS resolution). - For each distinct external hostname, checks whether it exists in the covered-hostnames set.
- Stores the list of external hostnames that are not covered by any hint.
Validation Logic
The crawler validates:
- Whether any
<link rel="dns-prefetch">tag exists in the head. - Whether each
hrefis a valid hostname or URL (protocol-relative or absolute). - Whether each distinct external domain found in resource tags has a corresponding dns-prefetch or preconnect hint.
How to Get It
Crawler should:
- Parse raw HTML
<head>. - Find all
link[rel="dns-prefetch"]andlink[rel="preconnect"]tags. - Extract
hreffrom each; build a covered-hostnames set from both hint types. - Count matched dns-prefetch tags and store hostname list.
- Scan all
<script src>,<link href>,<img src>,<source src>tags in the full document. - Extract hostname from each resource URL.
- Compare against the page's own crawled origin; collect distinct external hostnames.
- Produce the list of external hostnames not present in the covered-hostnames set.
What to Store
| Field | Type | Comment |
|---|---|---|
has_dns_prefetch_hints | BOOLEAN | Whether any dns-prefetch link tag is declared in the page head |
dns_prefetch_hrefs | TEXT[] | Array of href values declared in dns-prefetch tags |
dns_prefetch_count | INT | Number of dns-prefetch link tags found on the page |
has_external_domains | BOOLEAN | Whether the page HTML references any resource on a different hostname than the crawled page |
external_domains | TEXT[] | Distinct external hostnames found in script/link/img/source resource attributes |
external_domain_count | INT | Number of distinct external hostnames referenced in the page HTML |
has_external_domains_without_hint | BOOLEAN | Whether any external domain found in the HTML has no matching dns-prefetch or preconnect hint |
external_domains_without_hint | TEXT[] | List of external hostnames with no corresponding dns-prefetch or preconnect hint |
Condition for Trigger
The following trigger rule fires only when the HTML references external domains that have no dns-prefetch or preconnect hint.
- Trigger Rule 1: External Domains Referenced Without DNS Hint
- Target Field:
has_external_domains_without_hint - Evaluation Logic:
= TRUE - Severity: SUGGESTION
- Diagnostic Message: "One or more third-party domains are referenced in the page HTML but have no dns-prefetch or preconnect hint. Each uncovered external domain incurs a DNS lookup delay before its resources can begin downloading. Add a dns-prefetch hint for external domains not already covered by a preconnect hint."
- Target Field:
Sources
- MDN — link rel=dns-prefetch
- web.dev — Preconnect and DNS-prefetch
- W3C Resource Hints — dns-prefetch
- Google Chrome Developers — Resource Hints
Long Description
DNS prefetching is a lightweight browser optimization that resolves the IP address for a third-party hostname in advance of any actual resource request. Unlike preconnect (which opens a full TCP/TLS connection), dns-prefetch only performs the DNS lookup — making it inexpensive to use for many origins where a full preconnect would be wasteful.
Standard dns-prefetch declaration:
<link rel="dns-prefetch" href="//analytics.example.com">
<link rel="dns-prefetch" href="https://ads.partner.com">
Protocol-relative URLs (//hostname) are also valid since DNS prefetch applies at the hostname level.
DNS lookup timeline without prefetch:
- Browser parses HTML and encounters a
<script src="https://analytics.example.com/tracker.js">. - Browser initiates DNS lookup for
analytics.example.com. - DNS query propagates, resolves, and returns — typically 20–120ms.
- Browser now initiates TCP + TLS handshake.
- Script download begins.
DNS lookup timeline with prefetch:
- Browser parses
<link rel="dns-prefetch" href="//analytics.example.com">early in<head>. - DNS resolution runs in the background immediately.
- By the time the browser encounters the
<script>tag, DNS is already resolved. - TCP + TLS handshake begins immediately — one full round trip saved.
dns-prefetch vs preconnect:
| Hint | DNS | TCP | TLS | When to use |
|---|---|---|---|---|
dns-prefetch | ✅ | ❌ | ❌ | Non-critical or many origins |
preconnect | ✅ | ✅ | ✅ | Critical origins (LCP impact) |
Common failure scenarios:
1. Third-Party Domains Referenced Without Any Hints
A page loads analytics, chat widgets, and ad scripts from 5 different origins with no dns-prefetch or preconnect. Each incurs a serial DNS lookup.
2. Using dns-prefetch for Critical LCP Origins
If an image or font served from a third-party CDN is part of the LCP element, dns-prefetch alone is insufficient. Use preconnect instead (Issue 113).
3. Duplicate or Redundant Hints
<!-- Redundant: preconnect already implies dns-prefetch -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="dns-prefetch" href="//fonts.googleapis.com">
When preconnect is declared for an origin, dns-prefetch for the same origin is redundant. Some browsers handle this gracefully; others may issue duplicate lookups.
How to Fix
Add <link rel="dns-prefetch"> tags for non-critical third-party domains in the page <head>:
<link rel="dns-prefetch" href="//analytics.example.com">
<link rel="dns-prefetch" href="//ads.partner.com">
<link rel="dns-prefetch" href="//cdn.social-widget.com">
Guidelines:
- Use
dns-prefetchfor origins that are used on the page but are not on the critical rendering path. - For origins that serve LCP-blocking resources, use
preconnectinstead (Issue 113). - Do not declare
dns-prefetchfor an origin already covered by apreconnecthint — it is redundant. - There is no meaningful limit on the number of
dns-prefetchhints since each is very low cost. - Place hints early in
<head>for maximum benefit.