Table of contents
- Quick summary
- Why a header, when you already have files
- Method
- The headline: where 690 hosts land
- What the header carries
- Which relations show up
- Platform: who gets to a pass without trying
- The score gap
- What this means if you run a site
- What the header should not become
- Where AIScan fits, and where it stops
- What we are changing in AIScan
- Run it on your own site
Most sites send an HTTP Link header on their homepage. Almost none of them use it to tell an agent anything. On 6 October 2026 we queried AIScan's production database for the D3 check across 690 distinct hosts, one latest scan per host, and sorted every evidence string by what the header was actually spent on. 270 hosts (39.1%) send nothing usable. 361 (52.3%) pass. Among the passes, the number that name an agent discovery relation such as api-catalog, describedby or service-desc in the part of the evidence we can read is 64, or 9.3% of all hosts. The rest pass on something else.
That gap is the post. The Link header is a general-purpose RFC 8288 mechanism, and on the open web it is mostly carrying font preloads, preconnect hints and one WordPress REST API pointer. Our own how-to, Link headers for AI agent discovery, explains how to set the header up. This post is the denominator behind it: how many sites send one, what they put in it, and what that means for anyone reading a D3 result.
Quick summary
| If you want to know... | The measured answer | Where to look |
|---|---|---|
| How many sites pass D3? | 361 of 690 (52.3%); 59 partial (8.6%); 270 fail (39.1%) | Headline table |
How many send an HTTP Link header at all? | 257 of 690 (37.2%) | Headline table |
| How many name an agent discovery relation? | 64 of 690 (9.3%), or 24.9% of the 257 that send a header | What the header carries |
| What do most headers actually contain? | Resource hints: preload, preconnect, modulepreload | What the header carries |
| Which platform passes most? | WordPress, 172 of 184 (93.5%), mostly on a REST API pointer | Platform table |
| Which platform fails most? | Hosts AIScan could not attribute to a platform, 174 of 260 (66.9%) | Platform table |
| Does D3 track the overall score? | Passing hosts average 71.8, failing hosts 34.6 | Score section |
| What should I send? | api-catalog and describedby first, then service-desc if you have a spec | Fix section |
| Can I check it myself? | Yes: npx aiscan-cli yoursite.com, check D3 | Run it on your site |
The short version of the advice is below, and the numbers that support it follow.
- If your homepage has no
Linkheader, add one with two relations. It costs one line at the CDN or web server. - If it already has one, read it. A header made of
rel=preloadandrel=preconnectentries scores partial on D3 and tells an agent nothing about your site. - If you are on WordPress, you probably already pass D3. That pass does not mean agents can find your llms.txt or API catalog.
Why a header, when you already have files
A crawler that wants to know whether you publish an llms.txt, a sitemap or an API description can guess paths, or it can read what you told it. The Link header is the cheapest place to tell it, because the answer arrives with the first response. No second request, no parsing of HTML, no guessing at /.well-known/ conventions.
Three standards make this work. RFC 8288 (Web Linking, October 2017) defines the Link header and the registry of relation types. RFC 9727 (June 2025) registers the api-catalog relation and the /.well-known/api-catalog location, and shows the relation carried in a Link header on an ordinary response. The llms.txt proposal, in the version it shipped on 10 August 2026 per its own page at llmstxt.org, added rel="describedby" and rel="alternate"; type="text/markdown" as discovery relations, deliverable as HTML <link> tags or HTTP headers.
AIScan's D3 check reads the homepage response. According to the discoverability reference, D3 carries a weight of 3 and inspects the Link response header for an api-catalog or describedby entry. The live remediation text in the scan report adds that an HTML <link rel="api-catalog"> or <link rel="describedby"> tag also counts. That detail matters for the numbers below, because the two delivery routes show up differently in the evidence.
This is the next corpus post on discovery signals. The sitemap study measured D2, and the validator study measured whether sites let agents revalidate cheaply. D3 sits between them: it is the pointer that says where the other files live.
Method
Population. Every host in the AIScan scan table on rubric version 2026.08.2, reduced to one row per host by taking the latest scan, with aiscan.site excluded. That leaves 690 hosts. The population is people who chose to scan a site with AIScan, so it is not a random sample of the web. It skews toward owners who already care about agent readiness, which probably flatters every number in this post.
The query. D3 is one check in the unnested checks array of each stored report. We grouped by the check's status and evidence string. We did not read individual rows and we do not name any scanned site. The SQL shape is:
with latest as (
select distinct on (lower(regexp_replace(url,'^https?://(www\.)?([^/]+).*$','\2')))
url, platform, score, result
from scans
where rubric_version = '2026.08.2' and url not ilike '%aiscan.site%'
order by lower(regexp_replace(url,'^https?://(www\.)?([^/]+).*$','\2')), created_at desc
)
select c->>'status' as status, c->>'evidence' as evidence, count(*)
from latest, jsonb_array_elements(result->'checks') c
where c->>'id' = 'D3'
group by 1, 2 order by 3 desc;
The classification. We sorted evidence strings into five groups by pattern. A string starting Link: came from the HTTP header. A string reading <link rel="…"> in HTML head came from the HTML route. Inside header strings, a match on describedby, llms-txt, api-catalog, service-desc, service-doc, sitemap, agent-skills, oauth- or a Markdown alternate counted as an agent discovery relation. A match on api.w.org counted as the WordPress REST pointer. A match on preconnect, dns-prefetch, preload or modulepreload counted as a resource hint.
Limitations, stated before the tables.
- The evidence string is truncated. AIScan stores roughly the first 200 characters of the header. In 200 of the 257 header rows the string hit that cap. Any relation that appears after the cut is invisible to us. Every count of discovery relations in this post is therefore a lower bound, and the true figure for hosts that name one is higher by an amount we cannot measure from this table.
- The HTML route does not name its relation. The evidence for a head
<link>pass says only<link rel="…"> in HTML head. We cannot tell from the stored string which relation matched, so the 163 hosts that pass this way are counted separately and not classified further. - One scanner, one vantage point. AIScan probes from its own infrastructure. A site that varies headers by client would show us one version.
- Association is not cause. Where we compare scores, we are reporting what sits next to what.
The headline: where 690 hosts land
| D3 status | Hosts | Share of 690 | Mean overall score | Median overall score |
|---|---|---|---|---|
| Pass | 361 | 52.3% | 71.8 | 72 |
| Partial | 59 | 8.6% | 48.8 | 46 |
| Fail | 270 | 39.1% | 34.6 | 35 |
Of the 690, 257 hosts (37.2%) send an HTTP Link header, and 163 (23.6%) pass through an HTML head tag instead. The remaining 270 send neither: the evidence reads no Link header or <link> tag.
Among the 257 that send a header, 198 pass (77.0%) and 59 are partial (23.0%). No header-sending host failed outright, because a header either carries something the check accepts or it carries only hints, and hints earn partial credit.
So D3 looks healthy at first glance: more than half of hosts pass. The next table is the reason that reading is incomplete.
What the header carries
We split every one of the 690 hosts by what the visible part of its evidence shows.
| What D3 saw | Status | Hosts | Share of 690 |
|---|---|---|---|
Nothing (no Link header or <link> tag) | Fail | 270 | 39.1% |
HTML head <link>, relation not named | Pass | 163 | 23.6% |
WordPress REST pointer (api.w.org), no agent relation visible | Pass | 115 | 16.7% |
| An agent discovery relation named in the header | Pass | 64 | 9.3% |
| Other header content, no relation we classify | Pass | 13 | 1.9% |
| Resource hints only in the visible text | Pass | 6 | 0.9% |
| Resource hints only in the visible text | Partial | 57 | 8.3% |
| Other or WordPress-only | Partial | 2 | 0.3% |
Four things stand out.
First, the agent discovery pass is small. 64 hosts is 9.3% of the population and 17.7% of the 361 passes. Only about one in eleven of the hosts we scanned tells an agent, in the readable part of its homepage header, where an API catalog, llms.txt, spec or sitemap lives.
Second, the largest pass group we can classify is a WordPress feature. WordPress core adds a header like this to a page response. We confirmed it on a live site on 6 October 2026:
link: <https://wordpress.org/wp-json/>; rel="https://api.w.org/"
link: <https://wordpress.org/wp-json/wp/v2/pages/457>; rel="alternate"; title="JSON"; type="application/json"
link: <https://w.org/>; rel=shortlink
The WordPress REST API handbook documents the api.w.org relation as the way a client discovers the REST root. That is a real, machine-readable pointer. It is also not an api-catalog and not a describedby, so it tells an agent how to talk to WordPress, not what your site offers. The scan report still scores these hosts as a pass, and the evidence shows the REST pointer and nothing else we recognise. 115 hosts (16.7% of the population) sit here. That is nearly twice the size of the group that names an agent relation.
We are not calling this a bug without more evidence. The check's own remediation text allows more than the documentation page describes, and the stored evidence cannot tell us which relation earned the points when a header carries several. What we can say is that a D3 pass and "an agent can find your llms.txt from the header" are two different statements, and the population shows how far apart they are.
Third, resource hints dominate the failures to reach full credit. 57 hosts send a Link header made entirely of preload, preconnect or modulepreload entries in the visible text, and all 57 score partial. The preload headers are not wrong. They are spending a discovery mechanism on performance. A representative evidence shape from the Framer family of sites is a pair of preconnect entries for a CDN host and nothing else. A Wix-hosted site's header is a column of preconnect entries for static asset domains. Next.js sites in the corpus send preload entries for font files and a stylesheet.
Fourth, six hosts pass on hints-only evidence. We read these as a truncation artefact. The visible 200 characters show only fonts, and a later entry in the same header probably carries an accepted relation. The 57 partials and the 6 passes have the same visible shape, which is why we do not trust the visible text alone for any single row. It is another reason the 64 is a floor.
Which relations show up
Across all 690 evidence strings, counting mentions in the visible text of the header (and so a lower bound):
| Relation | Hosts naming it | Share of 690 |
|---|---|---|
api-catalog | 45 | 6.5% |
describedby or llms-txt | 39 | 5.7% |
service-desc | 19 | 2.8% |
sitemap | 7 | 1.0% |
https://api.w.org/ | 121 | 17.5% |
The counts overlap, because a header can name several relations. A typical agent-aware header in the corpus looks like this, and several hosts send close to exactly this:
Link: </.well-known/api-catalog>; rel="api-catalog", </llms.txt>; rel="describedby"; type="text/plain"
Some go further. A handful add service-desc pointing at an OpenAPI file, and one site names an agent-skills index and an oauth-authorization-server document in the same header. One uses the older llms-txt relation name instead of describedby. A few send a Markdown alternate link, which is the other relation llms.txt v2 asks for.
api-catalog leads the discovery relations at 45 hosts, ahead of describedby at 39. That ordering is notable, because AIScan's own documentation puts it first and a lot of the guidance that circulates for agent readiness leads with llms.txt. Sites that have taken the trouble to add a header have more often chosen the API catalog. We cannot tell from this data whether that reflects what owners want or what a particular plugin, template or hosting default sends for them.
Sitemaps are a rounding error. Only 7 hosts advertise a sitemap through the Link header. The sitemap's usual home is a Sitemap: line in robots.txt, which D1 already checks, so a low number here is not a gap.
Platform: who gets to a pass without trying
AIScan labels each scan with a detected platform. The table below covers every platform with at least eight hosts. The six listed account for 663 of the 690 hosts.
| Platform | Hosts | Pass | Partial | Fail | Send a header | Mean score |
|---|---|---|---|---|---|---|
| Not detected | 260 | 70 (26.9%) | 16 | 174 (66.9%) | 39 | 46.0 |
| WordPress | 184 | 172 (93.5%) | 2 | 10 | 125 | 66.2 |
| Next.js | 157 | 66 (42.0%) | 23 | 68 (43.3%) | 61 | 52.1 |
| Astro | 34 | 25 (73.5%) | 0 | 9 | 8 | 67.4 |
| Shopify | 17 | 8 (47.1%) | 8 | 1 | 9 | 66.6 |
| Lovable | 11 | 9 (81.8%) | 0 | 2 | 3 | 77.2 |
WordPress passes almost by default. 172 of 184 hosts pass, and 125 of those 184 send a header, nearly all of it the REST pointer. Add the 163 hosts that pass through a head tag and it becomes clear how much of the population's D3 pass rate is WordPress core doing something for free.
Next.js is the split case. 66 pass, 23 are partial and 68 fail. The 23 partials include font and stylesheet preload headers that the framework or its host sends on its own. A Next.js site sends a Link header by default and spends it on performance, which is the exact pattern the how-to warns about. Fixing it means adding two entries to a header the site already sends, usually in next.config.js headers or at the CDN, not creating a new one. Our Next.js setup guide covers the framework side.
Shopify has the highest partial share. Of 17 hosts, 8 are partial, and the visible evidence is preconnect entries for cdn.shopify.com and similar. Shopify storefronts do not offer, to our knowledge, a merchant-facing setting for response headers, so for a store owner the file route is the practical one: StoreSEO generates llms.txt and schema for Shopify stores, and the <link> tag route is the one a theme can reach. The sample is 17 hosts, so treat the split as direction, not a rate.
The undetected group fails most. 174 of 260 (66.9%) send nothing. These are the static sites, custom builds and hosts where AIScan found no platform fingerprint, and they are also the majority of the failures: 174 of the 270 failing hosts. If you run a hand-built site, you are the likeliest to fail D3 and the likeliest to be able to fix it in one line.
The score gap
Pass, partial and fail sit at mean overall scores of 71.8, 48.8 and 34.6. That is a 37-point gap between pass and fail, and D3 itself is worth only 3 points of weight. The gap is not D3's doing. A host that has bothered to publish discovery pointers has usually done other work too, and hosts that fail D3 may well be hosts that fail other checks too. Treat D3 as a marker of a maintained site, and not as a lever that lifts a score 37 points on its own.
The partial group is informative the other way. A partial host averages 48.8, about 14 points above a failing host and 23 below a passing one. That puts the sites that spend their header on hints in the middle: they send headers, which is deliberate work, but the work went to performance, not discovery.
For a prioritised view of which checks move a score most, see the one agent-readiness fix that moves the score most. D3 carries a weight of 3, so we would not move it ahead of the heavier checks.
What this means if you run a site
The measured pattern suggests three groups of readers.
You send no header (270 of 690). This is the easiest case. Add a Link header with two entries on the homepage response, an api-catalog relation pointing at /.well-known/api-catalog and a describedby relation pointing at /llms.txt. If the files do not exist yet, the header points at nothing, so create them first. The API catalog how-to covers the file, and the llms.txt generator produces one. A minimal header is:
Link: </.well-known/api-catalog>; rel="api-catalog", </llms.txt>; rel="describedby"; type="text/plain"
You send a header of hints (57 of 690). Keep the hints and append the discovery relations. A header can carry any number of comma-separated entries. The partial status in the corpus does not come from sending hints. It comes from sending only hints. Put the two discovery entries first, so that a client or a log line that truncates the value still sees them. Our own truncation problem in this study is a reminder that the front of a header is the part that gets read.
You pass through the WordPress REST pointer (115 of 690). You are not broken, but you are not discoverable either. If you run WordPress, ThinkRank is the plugin we recommend for this job, because it manages llms.txt, robots.txt, robots meta, schema and sitemaps from one plugin instead of three that each try to own the same files, and it migrates settings from Rank Math, Yoast, AIOSEO and SEOPress. ThinkRank gives you the files the header should point at. The header itself is a web server or CDN setting, so add it in your server config or CDN rule as described in the Link header how-to. Rank Math, Yoast and AIOSEO also generate sitemaps and some of these files; if you already use one, what matters is that exactly one plugin writes each file. The WordPress setup guide covers the full path.
You pass through a head <link> tag (163 of 690). This is a legitimate route and the check accepts it. Open your page source and confirm the tag names api-catalog or describedby, because the stored evidence does not say which relation matched. If it names something else, such as canonical or alternate, the pass deserves a second look.
What the header should not become
Two traps showed up in the corpus.
A header that carries only performance hints. This is the 57-host partial group. It is a common pattern because frameworks and CDNs add preload entries automatically, and because the same header field serves two audiences with different needs.
A header that points at files that do not exist. We did not measure this in the 690, because D3 does not follow the targets. It is the natural next step in this series, since a pointer to a 404 is worse than no pointer: the agent trusts the header and gets nothing. The same soft-404 problem is described in the soft-404 discovery post. Until we publish a follow-up, check by hand that each target returns 200 with the right content type.
Where AIScan fits, and where it stops
Run npx aiscan-cli yoursite.com, or paste the URL at aiscan.site, and read the D3 line in the report. Free, no account. The evidence string tells you which route matched. Two related checks complete the picture: D1 (robots.txt, which should reference your sitemap) and D2 (the sitemap itself). If you publish an API catalog, the capabilities checks (P1) look at the catalog file itself, which D3 only points at.
What AIScan cannot see:
- Where a relation sits in the header. The scan stores the first part of the string. We showed above how that limits this very study.
- Whether the pointed-at file is correct. D3 confirms the pointer, not the destination.
- Pages other than the homepage. The check reads one response.
- Whether any agent reads the header. We have not verified that any major AI crawler acts on
describedbyorapi-catalogtoday. These relations are the standards-track way to be found if clients adopt them, and this post measures supply, not demand.
If you would rather check by hand, request your homepage with curl -sI https://yoursite.com/ | grep -i '^link' and read what comes back. Check that discovery entries come before any resource hints, and that each target answers with a 200.
What we are changing in AIScan
This study turned up three issues in our own instrument.
- Store the whole header. Truncating at about 200 characters made 200 of 257 header rows partly unreadable. Evidence for D3 should list every relation type in the header, even if it shortens each URL.
- Name the relation on the HTML route.
<link rel="…"> in HTML headshould say which relation matched, so that a head-tag pass can be audited the way a header pass can. - Say why a pass passed. A WordPress REST pointer and an
api-catalogentry both read as pass. The report should show which entries earned the credit and which were ignored.
We will re-run the same query after the evidence format changes and publish how much the 64-host floor moves.
Run it on your own site
Scan your site and read D3. If it says no Link header or <link> tag, add the two-entry header above. If it reads like a list of fonts, put your discovery entries first. If you are on WordPress and it passes on the REST pointer, confirm that your llms.txt and API catalog exist and add the header at the server. Then scan again, and read D1 and D2 while you are there.
The reference page for these checks is discoverability checks. The how-to guides, including the Link header setup, API catalog and llms.txt guides, are at /guides. For the wider picture of how sites score across all checks, see the state of AI agent readiness in 2026.
Frequently asked questions
What is the Link header check (D3) in AIScan?
D3 inspects the HTTP Link response header on your homepage, and also accepts an HTML link tag, for an api-catalog or describedby relation. It carries a weight of 3. In our 690-host corpus 52.3% passed, 8.6% scored partial and 39.1% failed.
Why does my site pass D3 but agents still cannot find my llms.txt?
Because a pass does not prove the header names llms.txt. In the corpus, 115 hosts (16.7%) passed with only a WordPress REST API pointer visible in the evidence, and 163 passed through an HTML head tag whose relation the evidence does not name. Open your header and check that a describedby entry points at /llms.txt.
Why does D3 say partial when my site sends a Link header?
Your header probably contains only resource hints such as preload, preconnect or modulepreload. In the corpus 57 hosts had that shape and all scored partial. Keep the hints and add an api-catalog entry and a describedby entry, ideally at the front of the header.
Why does D3 say 'no Link header or <link> tag' when I added one?
The header is probably set on a path other than the homepage, set only for some clients, or stripped by a CDN or proxy. D3 reads the homepage response. Run curl -sI https://yoursite.com/ and look for a link line. Also check that your CDN rule applies to the apex and www hosts.
Does a WordPress site need to add a Link header?
WordPress core already sends a REST API pointer with the api.w.org relation, which is why 172 of 184 WordPress hosts passed D3. That pointer is not an api-catalog or describedby entry. To be found by agents, publish llms.txt and add a describedby entry at the server or CDN.
What should I put in the header first?
Put an api-catalog relation and a describedby relation first. A minimal header is Link: </.well-known/api-catalog>; rel="api-catalog", </llms.txt>; rel="describedby"; type="text/plain". Create both target files before you add the header, since D3 does not follow the targets.
Why did my D3 result change between two scans?
The header may differ per request, for example when a CDN adds hints on some responses, or a rate limit answered one request differently. Scan twice and compare the evidence line. Our determinism study found D3 flipped on about 5.3% of repeat scans.
Can I send the Link header on Shopify?
Shopify storefronts do not give merchants a response-header setting that we know of, and 8 of the 17 Shopify hosts in the corpus scored partial on preconnect hints. The practical route is the file and HTML link route, and StoreSEO generates llms.txt and schema for Shopify stores.
Related guides
Rate-limit AI crawlers without blocking them
Most advice on rate limiting AI crawlers stops at "add a limit". The part that costs you is where the limit applies and what it answers. A limit that covers /robots.txt and /llms.txt makes your own…
Which Agent-Readiness Checks Travel Together: 739 Sites, Three Bundles
Fix one agentreadiness check and a second one often moves with it. Fix another and nothing else changes. A scan report lists every check as its own line, so the reader cannot see which lines are…
Platform League Table: WordPress, Next.js, Astro and Shopify Across 728 Sites
Every few weeks someone asks which platform produces the most agentready sites. WordPress, Next.js, Astro and Shopify all have fans, and a ranked table is the answer people expect. We have the data…
10 Best Instagram Profile Analyzers in 2026 (Tested)
Comparison of 10 Instagram profile analyzers with free plans, prices and AIScan AIreadiness scores, October 2026 Updated October 13, 2026. Prices, freetier limits and AIScan scores were all checked…
