# Verifying AI crawler user agents: 0% for 48 days, then 73% once we kept the IP

A Machine Relations audit of 59,166 requests claiming an AI crawler user agent across six properties over 24 days, none of them carrying a verified identity because the collector never kept a client IP. Re-run with the IP for 2026-09-17: 2,584 of 3,540 requests verified against the ranges their vendors publish, 932 did not, and 24 were impossible by Google's own contract. 12.77% of the window asked for paths the sites have never served.

Canonical URL: https://machinerelations.ai/research/ai-crawler-user-agent-verification-gap-2026
Published: 2026-09-18
Research type: Study

## Source Body

Over 24 days, six web properties logged 59,166 requests carrying the user agent of an AI crawler. Not one of them carried a verified identity — and that turns out to be a fact about our own query rather than about the traffic. The collector never asked Cloudflare for the client IP, so no identity check was possible on any row, on any day. When we added the dimension and re-ran a single day, 2,584 of 3,540 requests verified against the IP ranges their vendors publish. This study is both the audit and the correction, in that order.

Nine hundred and fourteen of those 59,166 requests could not have been genuine whatever address they came from, because the user agent they claimed does not exist.

That figure is the one to start with, because it needs no statistical judgment. Google's crawler documentation states plainly that [Google-Extended](https://developers.google.com/crawling/docs/crawlers-fetchers/google-common-crawlers) "doesn't have a separate HTTP request user agent string. Crawling is done with existing Google user agent strings; the robots.txt user-agent token is used in a control capacity." Google-Extended is a preference token you put in robots.txt. It never appears in an HTTP request, because nothing sends it.

Our logs contain 914 requests that sent it, across 16 separate days. Every one is forged, by the publisher's own published contract. A further six requests claimed `Applebot-Extended`, which [Apple documents](https://support.apple.com/en-us/119829) the same way — an opt-out token for robots.txt, not a crawler.

This is the retrieval leg of machine relations, and it is the leg nobody outside a site can inspect. The [Machine Relations Index](https://machinerelations.ai/index) measures which domains answer engines cite. Search Console measures what happened on a results page. Neither can see what actually arrived at your server and asked for a file. Only the site owner holds that, which is why this audit turns the instrument on our own logs — and finds the instrument wanting.

## What was measured

The dataset is 24 daily Cloudflare snapshots of AI-bot traffic across six properties: authoritytech.io, machinerelations.ai, jaxonparrott.com, paralabs.ai, paralax.ai and christianlehman.com. The window runs 2026-08-23 to 2026-09-17. That is 24 of 26 calendar days; 2026-09-03 and 2026-09-04 were never collected and are absent rather than empty.

The snapshots hold 25,730 grouped rows, each a combination of request path, HTTP status, claimed user agent and host, with a request count. They sum to 59,166 requests. Every figure below is computed from those rows.

Eight distinct bot labels appear:

| Claimed bot | Requests | Days present |
| --- | ---: | ---: |
| ChatGPT-User | 21,137 | 24 |
| ClaudeBot | 11,123 | 24 |
| Applebot | 9,208 | 24 |
| OAI-SearchBot | 6,686 | 24 |
| PerplexityBot | 5,498 | 24 |
| GPTBot | 4,201 | 24 |
| Google-Extended | 914 | 16 |
| cohere-ai | 399 | 10 |

A crawl-analytics dashboard would render that table as a picture of AI interest in these properties. It is not that. It is a table of what arriving software said about itself.

## Every request is unverified, and the field that says so is a constant

Each stored row carries three identity fields. Across all 59,166 requests, `identityVerified` is `false` without exception. Where any evidence is recorded at all, the value is the string `user_agent_pattern_only`.

Reading the collector explains why, and the explanation is worse than a low verification rate. `identityVerified: false` is written as a literal when the row is constructed. It is not the outcome of a check that failed. It is a constant, and no request in this dataset or any future one could ever be marked otherwise.

The cause is upstream of that line. The collector queries Cloudflare's [GraphQL analytics API](https://developers.cloudflare.com/analytics/graphql-api/) for four dimensions: request path, response status, user agent and host. It never requests a client IP. Identity verification for every AI crawler in existence is a reverse-DNS lookup or an IP-range match. A pipeline that does not retain the source address is not failing to verify; it is structurally incapable of verifying, and the `identityVerified` field is decoration on a measurement that was never attempted.

The filter that decides what counts as an AI bot is a single substring match — `userAgent_like "%GPTBot%"` and eight siblings. Anything that puts that substring in its user-agent header enters the dataset as an AI crawler. There is no second condition.

## What is actually in the traffic

If a meaningful share of this traffic is not crawlers, it should be doing something crawlers do not do. It is.

The cleanest test needs no keyword list and no judgment about what a path means. Across all 48 days of collection, 4,283 distinct host-and-path combinations returned a successful status at least once. Any request in the window for a combination outside that set asked for something these sites have never served to anyone.

**7,553 requests — 12.77% of the total — asked for paths that have never once been served,** across 2,180 distinct host-and-path pairs.

That could in principle be honest crawling of dead links. It is not. 69.2% of those requests match a credential or configuration artifact. Applying such a classifier directly, 5,803 requests (9.81%) over 515 distinct paths asked for files in these families:

| What was requested | Requests |
| --- | ---: |
| Environment files (`.env` and 40+ spellings, `proc/self/environ`) | 2,374 |
| Cloud credentials (`.aws/credentials`, service-account JSON, `rclone.conf`) | 933 |
| Application config (`settings.json`, `docker-compose.yml`, `.npmrc`) | 700 |
| Private keys (`id_rsa`, `.ssh/`, `authorized_keys`, `*.pem`) | 534 |
| Debug endpoints (`actuator`, `telescope/requests`, `server-status`) | 388 |
| Path traversal (`/@fs/`, `%2e%2e`, `%252f`) | 220 |
| Secret stores (`secrets.json`, `.netrc`, Kubernetes service-account tokens) | 213 |
| WordPress and PHP (`wp-json`, `xmlrpc.php`, `phpinfo`) | 195 |
| Version-control artifacts (`.git/`, `.git-credentials`, workflow files) | 145 |
| Shell profiles (`.bashrc`, `.bash_history`) | 55 |
| Backups and dumps (`dump.sql`, `*.bak`) | 46 |

None of these sites runs WordPress, PHP, Laravel, or a Vite dev server. This is credential enumeration, and it is inside an AI-crawler dataset for one reason: it put the right substring in its user-agent header.

The two measures disagree on the exact figure — 9.81% against 12.77% — because one depends on a keyword list and the other does not. That gap is the honest width of the answer, and every ranking below is identical under both.

## Contamination runs inversely to real footprint

Per claimed bot, the share of traffic asking for never-served paths:

| Claimed bot | Total requests | Never-served | Share | Real retrieval |
| --- | ---: | ---: | ---: | ---: |
| cohere-ai | 399 | 376 | 94.2% | 23 |
| Google-Extended | 914 | 729 | 79.8% | 185 |
| GPTBot | 4,201 | 1,416 | 33.7% | 2,785 |
| OAI-SearchBot | 6,686 | 1,473 | 22.0% | 5,213 |
| PerplexityBot | 5,498 | 841 | 15.3% | 4,657 |
| Applebot | 9,208 | 755 | 8.2% | 8,453 |
| ClaudeBot | 11,123 | 828 | 7.4% | 10,295 |
| ChatGPT-User | 21,137 | 1,135 | 5.4% | 20,002 |

The mechanism is visible in the arithmetic. Never-served volume per label spans 3.9x, from 376 to 1,473 requests. Real retrieval volume spans 869.7x, from 23 to 20,002. Attackers distribute themselves roughly evenly across the bot names they might wear; real crawlers do not.

So the contamination rate of any bot label is, to a first approximation, a function of how little genuine traffic that label carries. **The smaller a crawler's true presence on your site, the more of its reported number is somebody else's attack traffic.** This inverts the way such a table is normally read. A dashboard row showing modest activity from an emerging engine is the row most likely to be mostly noise.

The same law holds per property:

| Property | Requests | Never-served | Share |
| --- | ---: | ---: | ---: |
| paralax.ai | 819 | 819 | 100.0% |
| paralabs.ai | 3,946 | 1,149 | 29.1% |
| christianlehman.com | 2,641 | 397 | 15.0% |
| jaxonparrott.com | 9,741 | 1,374 | 14.1% |
| authoritytech.io | 31,814 | 3,103 | 9.8% |
| machinerelations.ai | 10,205 | 711 | 7.0% |

The first row is the finding in miniature. Every one of the 819 requests that reached paralax.ai claiming to be an AI crawler asked for a path the site has never served. Not one fetched a page. A crawl dashboard would have reported 819 AI-bot requests for that property over 24 days. The correct number is zero, and it took the site's own logs to say so.

## The string is a filter only where the vendor maintains it

Two of the 24 days retain the full claimed user-agent string — 5,115 requests across 25 distinct strings. That slice contains a natural experiment.

| Requests | Probe share | Claimed string |
| ---: | ---: | --- |
| 1,153 | 0.0% | `…compatible; ChatGPT-User/1.0; +https://openai.com/bot |
| 807 | 11.5% | `…compatible; ClaudeBot/1.0; +claudebot@anthropic.com` |
| 718 | 0.0% | `…Version/17.4 Safari/605.1.15 (Applebot/0.1; +http://www.apple.com/go/applebot)` |
| 570 | 0.0% | `…compatible; GPTBot/1.4; +https://openai.com/gptbot |
| 419 | 20.0% | `…compatible; PerplexityBot/1.0; +https://perplexity.ai/perplexitybot |
| 359 | 0.0% | `…Chrome/131.0.0.0 Safari/537.36; compatible; OAI-SearchBot/1.4; …` |
| 202 | 83.7% | `…compatible; GPTBot/1.3; +https://openai.com/gptbot |
| 153 | 73.2% | `…compatible; OAI-SearchBot/1.0; +https://openai.com/searchbot |
| 125 | 75.2% | `…Version/17.0 Safari/605.1.15 (Applebot/0.1)` |

The fourth and seventh rows differ by one character. `GPTBot/1.4` is the version [OpenAI currently documents](https://developers.openai.com/api/docs/bots); across 570 requests it asked for a never-served path zero times. `GPTBot/1.3` is the superseded version; across 202 requests, 83.7% were probes. Same structure, same suffix URL, one digit apart, opposite populations.

Apple gives the same result. The 718-request Applebot string is character-for-character the example in [Apple's own documentation](https://support.apple.com/en-us/119829), including the `+http://www.apple.com/go/applebot suffix, and carries no probe traffic. The 125-request variant drops that suffix and advertises `Version/17.0` instead of `17.4`, and is 75.2% probes. Apple notes that Applebot "will update the browser version that it advertises" — so the current version is a moving target, and the forgeries are working from a stale copy.

OpenAI's OAI-SearchBot splits the same way. The three variants carrying the documented `Chrome/131.0.0.0 Safari/537.36` prefix account for 494 requests and 0.0% probes, including the `robots.txt`-marked form OpenAI documents for robots fetches. The three truncated variants account for 196 requests at 52% to 73%.

Then the rule breaks, and where it breaks is instructive.

PerplexityBot's 419-request string is exactly the one in [Perplexity's documentation](https://docs.perplexity.ai/guides/bots), and it carries 20.0% probe traffic. Perplexity has never moved past `PerplexityBot/1.0`, so there is no stale version for a forger to get wrong — the documented string is the only string, and copying it perfectly is free. ClaudeBot's dominant 807-request form carries 11.5%, and [Anthropic publishes no user-agent string at all](https://support.claude.com/en/articles/8896518-does-anthropic-crawl-data-from-the-web-and-how-can-site-owners-block-the-crawler), directing site owners to its IP list instead.

The pattern, stated as a finding: **version rotation is an accidental anti-forgery mechanism.** Vendors who publish an exact string and keep bumping it (OpenAI, Apple) leave a clean current form and a contaminated stale one. Vendors who never rotate, or publish no string, hand out a permanently valid costume. In neither case is the string proof — it is a heuristic whose strength depends entirely on the vendor's release discipline, and it collapses the moment a forger refreshes its copy.

## The fix exists, is free, and is published by every vendor

Every operator of a bot in this dataset publishes the IP ranges its crawler uses. All six files were fetched on 2026-09-18:

| Publisher | File | Prefixes | Last updated |
| --- | --- | ---: | --- |
| OpenAI — ChatGPT-User | [chatgpt-user.json](https://openai.com/chatgpt-user.json) | 219 | 2026-09-18 |
| OpenAI — GPTBot | [gptbot.json](https://openai.com/gptbot.json) | 21 | 2025-10-30 |
| OpenAI — OAI-SearchBot | [searchbot.json](https://openai.com/searchbot.json) | 39 | 2026-01-02 |
| Anthropic — Claude bots | [bots.json](https://claude.com/crawling/bots.json) | 26 | 2026-08-18 |
| Apple — Applebot | [applebot.json](https://search.developer.apple.com/applebot.json) | 24 | 2026-09-15 |
| Perplexity — PerplexityBot | [perplexitybot.json](https://www.perplexity.ai/perplexitybot.json) | 8 | 2025-02-07 |

Two things stand out. The ChatGPT-User file was refreshed the morning these figures were computed and carries ten times the prefixes of any other, which is consistent with it being the label carrying the most genuine traffic here. And Perplexity's file has not been touched in nineteen months while listing eight prefixes — so a publisher choosing to allowlist by IP should expect that list to be the least reliable of the six.

Every one of the 337 prefixes across all six files is IPv4. Not one IPv6 prefix is published by any vendor. A site reached over IPv6 by something claiming to be GPTBot cannot be confirmed or refuted from the published ranges at all, and that gap belongs to the vendors, not to site owners.

The complementary method is reverse DNS. Google documents [verifying its crawlers](https://developers.google.com/search/docs/crawling-indexing/verifying-googlebot) by reverse lookup to `googlebot.com`, and Apple documents the same against `*.applebot.apple.com` with a forward confirmation. Both are two lookups per address and neither requires vendor cooperation beyond what is already published. Cloudflare additionally maintains a [verified-bots list](https://developers.cloudflare.com/bots/concepts/bot/verified-bots/) that performs this check at the edge — available to the same account whose analytics API produced this dataset, and not consulted by it.

Longer term the industry is moving to cryptography rather than address lists. The IETF's [web bot auth](https://datatracker.ietf.org/doc/draft-meunier-web-bot-auth-architecture/) work proposes that agents sign their requests using [HTTP Message Signatures](https://www.rfc-editor.org/rfc/rfc9421.html), which would make a forged bot identity computationally hard instead of a header edit. Until that ships and is adopted, IP verification is the only available answer, and it is available today.

## What the IPs said

So we did it. The corrected collector groups by client IP at Cloudflare's maximum row limit, matches each group against the file its vendor publishes, records the verdict and drops the address before anything is stored — the address decides the answer and is not the answer. Dry run against live Cloudflare for 2026-09-17, all six properties:

| Verdict | Requests | Share |
| --- | ---: | ---: |
| Verified inside the vendor's published range | 2,584 | 73.0% |
| Not verified | 932 | 26.3% |
| Impossible by vendor contract (`Google-Extended`) | 24 | 0.7% |
| **Total for the day** | **3,540** | |

Three things in that table need separating. The 73.0% is a measurement rather than an estimate: an address either falls inside a published prefix or it does not. The 932 is not a synonym for forged — it mixes addresses outside the published ranges with labels whose vendor publishes no range file at all, and with requests arriving over IPv6, which no vendor file can confirm either way. And the day's total is 3,540 where the old query reported 2,736 for that same day, because the old query stopped at 100 grouped rows and the difference was never reported as missing.

That is the headline this study was first published under, corrected by its own recommendation. "None verified" was true of the dataset and misleading as a statement about AI crawlers. Most of this traffic is what it says it is. The string still is not what proves it.

## Three defects this audit found in our own collector, all three now measured

Stated plainly, because the same three are likely present in any log pipeline built the same way.

**It cannot verify.** No client-IP dimension was requested, so no identity check was possible and `identityVerified` was a hardcoded `false` — not a check that failed, a check that was never attempted. Adding the dimension and matching against the six published files above converts every number in this study from a claim into a measurement: 2,584 verified identities on the first day it was tried, against zero across the pipeline's entire 48-day life.

**One of its nine patterns has never matched anything.** The configured list includes `Anthropic`, intended to catch Anthropic's crawlers. In 48 days it returned zero rows. Cloudflare's `userAgent_like` is case-sensitive, and of the 867 ClaudeBot requests whose full string was retained, 861 carry lowercase `anthropic.com` and none carry a capitalised `Anthropic`. Measured on 2026-09-17, the capitalised pattern returns 0 groups where the lowercase form returns 76 on machinerelations.ai and 100 on authoritytech.io. Lowercasing it is the wrong repair: it would collapse `ClaudeBot`, `Claude-User` and `Claude-SearchBot` into one bucket and double-count all three against the pattern already collecting ClaudeBot. The three are named separately instead — and two of them, the user-initiated fetch and the search indexer, had never been collected at all.

**Every total is a floor.** The query was capped at 100 grouped rows per bot, per property, per day. Of the 788 queries that returned anything, 104 — 13.2% — came back with exactly 100 rows, concentrated on the busiest property and the highest-volume labels. Re-running 2026-09-17 at the 10,000-row maximum puts a number on what that cost: six of 54 queries were capped, and 451 requests, 14.15% of the day, never appeared. Wherever this study says a count for the 24-day window, the true count is that or higher.

**And the class, not the three instances.** A pattern that matches nothing in any zone is now named in the snapshot and warned to the log, and a query that still fills its page is named the same way. `Anthropic` hid for 48 days because its neighbours' totals looked plausible and nobody was ever told. The next dead string announces itself on its first run, which is the only version of this fix worth shipping.

## Checking your own logs

1. **Pull a day of AI-bot requests with the client IP included.** If your pipeline does not retain the source address, stop here and fix that first; nothing else in this list is possible without it.
2. **Match each address against the publisher's own range file** from the table above. Reverse DNS works too, and for Google and Apple it is the documented method.
3. **Split the unverified remainder by path.** Requests for `.env`, `.git`, `id_rsa`, `wp-json` and their kin are not crawlers, whatever their header says.
4. **Check for a `Google-Extended` or `Applebot-Extended` user agent.** Any request claiming either is forged with certainty, and its presence tells you your log has never been filtered.
5. **Look at your smallest bot labels first.** That is where contamination concentrates, because attack volume is roughly constant per label while real volume is not.
6. **Compare requested paths against paths your site actually serves.** A label that has never fetched a real page has a true retrieval count of zero, regardless of its request count.
7. **Check whether your query is truncating.** If a grouped result comes back at exactly your row limit, that day's total is a floor.

Step 4 is the fastest and the most diagnostic. It takes one search and returns a yes or no about whether any filtering has ever been applied to the numbers you have been reading.

## What this does and does not establish

It does not establish that AI crawler traffic is mostly fake. The opposite, for the labels that matter: ChatGPT-User, ClaudeBot and Applebot account for 41,468 of the 59,166 requests here, and 93.4% of their traffic asked for paths these sites genuinely serve. Real retrieval by real crawlers is the bulk of this dataset. The claim is narrower and harder: **no individual request across the 24-day window was attributed, because the instrument that collected it never kept the evidence — and the aggregate is overstated by an amount that varies from 5% to 100% depending on which row you read.** The single day re-run with identity says that missing evidence was recoverable the whole time, and that when you go and get it, most of the traffic holds up.

It does not establish that anything leaked. 295 requests to credential-family paths were logged with HTTP 200. All the paths involved were re-requested live on 2026-09-18 and every one returned 404 or 403. The 404 responses are served as a fully rendered 55,933-byte page, which is the likeliest explanation for the logged 200s: a framework catch-all route answering a miss with a page. That is worth naming as a hazard in its own right — a 200 in a crawl log does not establish that content was served.

It does not generalise cleanly to larger sites. Six properties in one subject area, 24 days, one CDN's analytics. The direction should generalise, because the mechanism is a missing verification step rather than anything specific to these sites, and third-party inventories of AI agent user agents such as [Dark Visitors](https://darkvisitors.com/agents) show the same labels in wide circulation. The magnitudes are ours.

One number is not laundered. The collector's own `totals` field sums to 59,415 against the 59,166 reconstructable from stored rows — an excess of 249 requests, 0.42%, spread across all four bot categories, which could not be accounted for from the rows. Every figure in this study uses the rows, and this paragraph exists because the discrepancy is small enough to have been quietly dropped.

## Why this belongs in machine relations

The discipline has a measurement problem shaped like a chain. An engine retrieves your page, decides whether to cite it, and a person may or may not arrive. Three legs, three instruments, and the first one turns out to rest on an unverified self-report.

That matters beyond log hygiene, because retrieval counts are load-bearing. They get used to argue that a page is working, that an engine has discovered a section, that a robots.txt change took effect. Every one of those arguments is only as sound as the identity behind the request, and across this window the identity behind every single request was an unchecked claim, because nothing checkable was ever stored — with 914 of them claiming something that cannot exist.

This is also why the [Machine Relations Index](https://machinerelations.ai/index) is built the way it is. The Index does not read crawler logs. It observes what answer engines actually cite, across 124,397 source events over 125 days and 22,179 domains in the 2026-09-18 release, and a domain's standing there depends on nothing any third party can spoof, because the evidence is the engine's own output rather than a header a visitor wrote about itself. A publisher can look up [its own domain's position](https://machinerelations.ai/research/ranked-without-a-grade-ai-citation-index-domain-lookup-2026) in that release. The citation leg is measurable from outside. The retrieval leg is measurable only from inside — and this study is what we found when we checked whether ours was measuring anything at all.

The useful conclusion is not that crawl analytics are worthless. It is that a crawl-analytics number without an identity check is a count of claims, that the error runs largest exactly where a publisher is most likely to be looking for early signal from a new engine, and that the correction costs one extra field in a query and a file every vendor already publishes.

## Methodology

Source: 24 daily Cloudflare `httpRequestsAdaptiveGroups` snapshots across six zones, window 2026-08-23 to 2026-09-17, collected daily at approximately 00:10Z for the preceding complete UTC day. 2026-09-03 and 2026-09-04 were not collected. 25,730 grouped rows totalling 59,166 requests. Dimensions retained per row: request path, edge response status, host, and (on 2026-09-16 and 2026-09-17 only) the claimed user-agent string. No client IP is retained, which is the subject of this study.

Bot attribution is the collector's own substring match on the user-agent header, `userAgent_like "%pattern%"`, across nine configured patterns, of which eight ever matched. Requests are counted, not rows; where a figure counts rows or distinct paths it says so.

"Never-served" is defined without reference to path semantics: a host-and-path pair is never-served if no row in any of the 48 collected snapshots records a 2xx status for it. 4,283 pairs met that bar; requests for any pair outside it are counted as never-served. The credential-family classifier is a separate, stricter measure using explicit pattern families, listed in the table above with their counts; it excludes all content routes by prefix, so a content slug containing a word like "secret" is never classified as a probe. Both measures are reported because they bound the answer from either side and agree on every ordering.

Probe shares in the user-agent variant table use the credential-family classifier on the 5,115 requests from 2026-09-16 and 2026-09-17 that retain a claimed string. Vendor range files and vendor documentation were fetched on 2026-09-18 and prefix counts and timestamps are as of that date. Live status re-checks of probe paths were performed on 2026-09-18 against authoritytech.io and machinerelations.ai.

Limits that bound every figure in the 24-day window: the 100-row query cap truncates 104 of 788 non-empty queries, so all totals are floors; two days are missing from the window; the collector's own totals exceed the row-level reconstruction by 249 requests (0.42%), and the row-level figures are used throughout; and no request in that window carries a verified identity, because no client IP was retained, which means the genuine-versus-forged split across it is inferred from request behaviour rather than measured from identity.

The identity figures are a separate measurement and are not part of the 24-day dataset. They come from a dry run of the corrected collector against live Cloudflare on 2026-09-19, covering 2026-09-17 across all six zones, grouping by `clientIP` at a 10,000-row limit and matching each group against the six vendor range files listed above. That run reports 3,540 requests where the capped query reported 2,736 for the same day, no query near the row limit and every configured pattern matching, so its counts are measurements rather than floors. Client addresses decide each verdict and are discarded; the stored snapshot carries the verdict and no address. One day and six properties is the whole of it — the 73.0% is that day's figure, not a rate for AI crawler traffic generally.

## Attribution

This research is published by Machine Relations Research, the research program of machinerelations.ai — the public research and standards initiative that publishes the glossary, research, evidence, and measurements for the Machine Relations discipline. Provenance and editorial standards: https://machinerelations.ai/about

## Machine-readable related links

### Related concepts

- [Machine Relations Index (MRI)](https://machinerelations.ai/glossary/machine-relations-index)
- [Machine Relations (MR)](https://machinerelations.ai/glossary/machine-relations)
- [MRI Score](https://machinerelations.ai/glossary/mri-score)
- [RAG Citation (RAG)](https://machinerelations.ai/glossary/rag-citation)

### Supporting research

- [Citation Absorption vs Citation Selection: Why Getting Cited Is Not the Same as Getting Used](https://machinerelations.ai/research/citation-absorption-vs-selection-ai-search-2026)
- [Citation Architecture: How AI Search Engines Structure Source Selection in 2026](https://machinerelations.ai/research/citation-architecture-ai-search-source-selection-2026)
- [Grand View Research Answer-Engine Citation Authority: Consensus Rises to 78.4 as Volume Corrects 29%](https://machinerelations.ai/research/grand-view-research-answer-engine-citation-authority-mri)
- [How to Run an AI Citation Gap Analysis: The Step-by-Step Methodology for Finding What AI Engines Won't Cite (2026)](https://machinerelations.ai/research/ai-citation-gap-analysis-methodology-2026)

### Framework context

- [Machine Relations Index](https://machinerelations.ai/index)
- [Machine Relations Stack](https://machinerelations.ai/stack)
- [Evidence Base](https://machinerelations.ai/evidence)
