Read the results
Read what an audit found: the main problems, every issue with its pages, page and link records, the folder tree, the crawl log and earlier audits.
Start with the summary: its notes say how complete the audit is (why the crawl stopped early, rate limiting, the external URLs we did not check), then the ten most important problems in plain words, each with the pages it affects, how to fix it and an example. Then go as deep as you need. Every call works during the crawl too, on what was found so far.
Parameters
Headers
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
Authorization | string | Yes | – | Bearer followed by your API key. See Authentication. |
Path parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
id | string | Yes | – | The audit's id, from Audit a website. |
Every way to read an audit
| Call | Answer |
|---|---|
GET /v1/site-audit | Your audits, newest first. |
GET /v1/site-audit/{id} | Status, live progress and counts. See Follow an audit. |
GET …/{id}/summary | notes, plain sentences on how complete the audit is (why the crawl stopped early, rate limiting, the external URLs we did not check), then the ten most important problems in plain words. |
GET …/{id}/issues | Every issue found, worst first, with the report's groups in order (Internal pages, Indexability, AI discoverability, Links, Redirects, Content and so on, each with its subgroups). Each issue: id, a short name such as "404 page", severity, group, groupName, subgroup, description, fix, urls out of of, share, indexable and notIndexable, site for site-wide findings, found, change against an earlier audit, history and five examples. In Links and Content a page issue comes as two rows, Indexable and Not indexable (split); split=none gives one row per issue, split=indexability splits every group. view=all lists all 213 checks, those that found nothing with found: false. Filters severity, group; compare names another finished audit of the same site to compare with. |
GET …/{id}/issues/{issue} | The URLs with one issue as a table: columns names its fields in order, url, status, depth, indexable and inlinks, then the issue's own (title and titleLength for title issues, redirectTo, canonical, ttfbMs…), then detail. Each URL also has its template, and total counts them. Against an earlier audit a URL may carry mark (new or added); lost=true lists the URLs that no longer have it, marked removed or missing; compare as for …/issues. |
GET …/{id}/pages | Page records. Filters kind (page, resource, external, all), status (a code, a class such as 4xx, failed, blocked, broken, or unchecked: external URLs we did not check), type (html, document, image, css, js), indexable, noindex, nofollow, canonical (self, other, none), orphan, template, depth, minDepth, maxInlinks, minWords, maxWords, issue and q (the URL contains it); sort (url, status, depth, inlinks, words, ttfb, bytes, title) with order (asc, desc); total counts every match. url gives one page with its issues, inlinks and outlinks. |
GET …/{id}/pages/filters | Ready-made page lists with their counts, in groups: internal URLs by status, resources, external URLs (all, broken, not checked), content type, indexability, canonical, depth and links. Each has params: send them as the query of …/pages to list it. |
GET …/{id}/links | Links, each with type (href, image, resource, redirect), flags, sourceStatus, targetStatus and targetNotCrawled, and total. Filters q (either URL contains it), from, to, broken, external, nofollow, resources, status (of the target: 2xx to 5xx, failed, blocked, unchecked, notCrawled) and type (image, resource, navigation, redirect). |
GET …/{id}/links/filters | Ready-made link lists with their counts: all, internal, external and to resources; internal links by the status of their target; external links to a broken URL or to one we did not check; followed, nofollow, image, navigation and redirect hops. Each has params for …/links. |
GET …/{id}/structure | The site as a folder tree: the folders under path (none for the hosts), each with urls, hasChildren and dist, its URLs spread by by: status (the default), type, depth or indexability. |
GET …/{id}/log | The crawl log: from, to, durationSeconds and urls, minutes (each minute's URLs by status class and fetches a second) and the latest fetches. |
GET …/{id}/history | Every audit of the same site by your key, newest first, with its health score, urls, htmlPages, resources, urlsWithErrors and issues per severity. |
GET …/{id}/redirects | Redirects with their whole chain and the final status; chains=true for chains only. |
GET …/{id}/duplicates | Groups of exact duplicates (body, title, description, h1) and near duplicates; filter kind. |
GET …/{id}/orphans | Pages known from your sitemaps or urls that no followed internal link reaches, with where we know them from. |
GET …/{id}/templates | URL templates (/blog/{slug}) with page counts and their issues; estimates for sampled audits. |
GET …/{id}/sitemaps | Each sitemap file read, and the consistency checks. |
GET …/{id}/diff/{previousId} | New and fixed issues, new and gone pages, changed titles, canonicals and status, against an earlier audit of the site. |
GET …/{id}/export | Every page record, 1,000 at a time, by cursor. |
POST …/{id}/cancel | Stops the crawl. What was found stays readable, and the site-wide checks run on it. |
Lists take cursor (from the previous answer) and limit (1 to 1,000, default 100), and answer {cursor, hasMore, items}: pass cursor back while hasMore is true.
The pages behind one issue
GET /v1/site-audit/{id}/issues/title-duplicate, from an audit of rankfield.dev: the ?tab= addresses repeat the homepage's title.
{
"cursor": null,
"hasMore": false,
"items": [
{
"url": "https://rankfield.dev/",
"status": 200,
"depth": 0,
"indexable": true,
"inlinks": 102,
"title": "Rankfield — Open web link metrics",
"titleLength": 33,
"detail": "3 pages",
"template": "/"
},
{
"url": "https://rankfield.dev/?tab=key",
"status": 200,
"depth": 2,
"indexable": true,
"inlinks": 99,
"title": "Rankfield — Open web link metrics",
"titleLength": 33,
"detail": "3 pages",
"template": "/?tab={v}"
},
{
"url": "https://rankfield.dev/?tab=strength",
"status": 200,
"depth": 2,
"indexable": true,
"inlinks": 3,
"title": "Rankfield — Open web link metrics",
"titleLength": 33,
"detail": "3 pages",
"template": "/?tab={v}"
}
],
"issue": {
"id": "title-duplicate",
"name": "Duplicate title",
"severity": "warning",
"group": "content",
"groupName": "Content",
"subgroup": "",
"description": "Several indexable pages share this exact title.",
"fix": "Give each page its own title."
},
"of": {
"set": "indexable",
"urls": 103,
"label": "indexable pages"
},
"total": 3,
"columns": [
"url",
"status",
"depth",
"…"
],
"compared": true
}Severity
- error (45 rules): hurts indexing or visitors now, such as a page or internal link that answers 4xx or 5xx, a redirect loop, or a canonical that points at a broken page.
- warning (78 rules): likely costs traffic, such as duplicate pages, thin content, orphan pages, or a linked page served as something other than HTML.
- notice (90 rules): worth a look, such as missing structured data, short titles or missing social cards.
How counts read
- Names and groups. Each issue has a short
name("404 page", "Title too long"), adescriptionof what was found and afix, and sits in agroupof the report, sometimes in asubgroup. - URLs affected. An issue's
urlscounts each URL that has it once, out of the set the rule reads, given inof({set, urls, label}): every crawled URL of the site (internal), HTML pages that answered 200 (htmlPages), the indexable ones (indexable),redirects,sitemapUrls, or the whole site (site, with no URL count). Read it as "3 of 103 HTML pages".shareis the same as a percentage and never passes 100. - Documents are not HTML pages. Markdown, PDF and other files count in the inventory's
documentsand only in theinternalset. - Indexable split. Page issues give
indexableandnotIndexable, so you can tell the pages that matter for search apart. - Issues found. Per severity,
issueTypesis how many kinds of issue were found andaffectedUrlshow many URL–issue pairs: a URL with three issues counts three times. - Health score. The share of crawled internal URLs with no error-level issue, 0 to 100, given with its parts in
counts.health. - Change. Against an earlier finished audit of the same site (
comparewhen you name one, elseprevious, else your latest one), each issue giveschange:added(crawled both times, has it now and didn't),new(first crawled now and has it),removed(had it and doesn't),missing(had it and wasn't crawled this time) andnet. An issue that is gone showsurls0. - History.
historygives the issue'surlsin up to ten earlier finished audits of the site, oldest first, ending with this one. - Not checked is never broken. An external URL we did not check carries
error:siteExcluded(a site we never fetch, such as the social networks' share links),robotsDisallowed, orbotBlocked(its bot protection answered our check with a401,403or429, or a challenge page;facts.firewallsays what we saw). None of them counts as a broken link, in issues, thebrokenfilters or the inventory.status=uncheckedlists them, on…/pagesand…/links.
Errors
| Status | Code | When |
|---|---|---|
| 400 | invalid_input | A parameter is missing, unknown or malformed (unknown parameters are refused), or the body is over 1 MB. |
| 401 | unauthorized | No valid API key. |
| 404 | not_found | No audit with this id for this key (only the key that started an audit can read it), an unknown issue, or a page that is not in the audit. |
| 500 | internal | Our bug. Retry. |
| 503 | unavailable | New audits are paused while the service is short of storage, or it is restarting. Retry after Retry-After. |
MCP
On the MCP server, the tools for this are site_audit_summary, site_audit_issues, site_audit_issue_pages, site_audit_pages, site_audit_links, site_audit_redirects, site_audit_duplicates, site_audit_orphans, site_audit_templates, site_audit_sitemaps, site_audit_diff, site_audit_export, site_audit_page_filters, site_audit_link_filters, site_audit_structure, site_audit_log and site_audit_history.