AvocadoScore

Developers

AvocadoScore API

The same checks that power the free tools, over plain HTTP. JSON in, JSON out. No account, no API key, no signup. Check whether a site is ready for ChatGPT, Claude and Perplexity, which AI crawlers it lets in, generate an llms.txt, run a full scan, or embed a live score badge.

Quick start

Every endpoint takes a JSON body and returns JSON. Send content-type: application/json. A URL can be written with or without https://.

curl -s https://avocadoscore.io/api/readiness \
  -H 'content-type: application/json' \
  -d '{"url":"example.com"}'

That returns the site’s SEO and AI-readiness scores and every check behind them, in a few seconds. The endpoints only fetch public pages: private, internal and non-routable addresses are refused.

Readiness check

POST/api/readiness

An instant SEO and AI-readiness check of a site’s homepage (no PageSpeed run, so it answers in seconds). The same engine and checks as the full scan, applied to the homepage.

Request

{ "url": "example.com" }

Response 200

{
  "url": "https://example.com",
  "domain": "example.com",
  "seo": {
    "score": 83, "passed": 10, "warned": 1, "failed": 1, "total": 12,
    "checks": [ /* { id, label, status, detail? } … */ ]
  },
  "ai": {
    "score": 71, "passed": 11, "warned": 3, "failed": 4, "total": 18,
    "checks": [ { "id": "llms-txt", "label": "/llms.txt",
                  "status": "fail", "pillar": "comprehension" } /* … */ ],
    "botPolicies": [ { "bot": "GPTBot", "vendor": "OpenAI",
                       "status": "unspecified", "kind": "training" } /* … */ ],
    "hasLlmsTxt": false,
    "hasLlmsFullTxt": false,
    "pillars": { "access":        { "score": 80, "passed": 4, "warned": 1, "failed": 1, "total": 6 },
                 "comprehension": { /* … */ }, "trust": { /* … */ } }
  },
  "stored": true
}

Abridged, values illustrative. Scores are 0–100. A check’s status is pass, warn or fail; a check flagged bonus is a positive-only signal that isn’t counted in the score. status for a crawler is allowed, blocked (robots.txt disallows it entirely), partial (some paths) or unspecified (no rule, so it may crawl). stored says whether the result was kept for 7 days so a comparison page can show the site without checking it again.

AI bot check

POST/api/bot-check

Which AI crawlers can read the site: every major crawler’s robots.txt policy, plus a live fetch as GPTBot to see whether the content is actually served (a firewall can block a bot that robots.txt allows).

Request

{ "url": "example.com" }

Response 200

{
  "url": "https://example.com",
  "domain": "example.com",
  "robotsPresent": true,
  "rows": [
    { "id": "GPTBot", "vendor": "OpenAI", "product": "ChatGPT (training)",
      "kind": "training", "note": "…", "status": "blocked" } /* … */
  ],
  "summary": { "allowed": 2, "blocked": 3, "partial": 0, "unspecified": 7, "total": 12 },
  "live": {
    "bot": "GPTBot", "bytesAsBot": 48211, "bytesAsBrowser": 48302,
    "ratio": 0.998, "botBlocked": false, "status": "pass", "detail": "…"
  }
}

kind is search for crawlers that fetch pages to answer or cite, and training for ones that feed models. live is null when the live fetch itself failed; that never fails the request.

llms.txt generator

POST/api/llms-generator

Reads a site’s sitemap and returns a starter llms.txt, with the URLs grouped into sections.

Request

{ "url": "example.com" }

Response 200

{
  "url": "https://example.com",
  "domain": "example.com",
  "title": "Example",
  "description": "…",
  "sections": [ { "title": "Docs", "links": [ { "title": "Guide", "url": "https://example.com/guide" } ] } ],
  "content": "# Example\n\n> …",
  "urlCount": 128
}

content is the finished Markdown, ready to save as /llms.txt. A site with no sitemap and no homepage links returns 502.

Full scans

A full scan is the free report: up to 10 pages picked from the sitemap, Core Web Vitals plus SEO and AI readiness, with every fix. It runs in the background, so you create it, poll its status, then read the report.

Create a scan

POST/api/scans

{ "url": "example.com" }
201 { "id": "8c1f…", "status": "queued" }
200 { "id": "8c1f…", "status": "done", "reused": true }

200 with reused: true means we already have a recent scan of that domain (one that hasn’t failed and was created in the last 10 minutes, or a free scan that finished in the last 24 hours), so you get that one back instead of a new run.

Poll the status

GET/api/scans/{id}

{
  "id": "8c1f…", "url": "https://example.com", "domain": "example.com",
  "tier": "free", "status": "scanning",
  "progress": { "phase": "scanning", "done": 3, "total": 10, "currentUrl": "https://example.com/pricing" },
  "discoveredCount": 42, "errorMessage": null, "hasData": false
}

status moves through queued, discovering, scanning, aggregating, done, failed. Poll every few seconds until it is done (or failed, with errorMessage set). Responses are never cached.

Read the result

The full report is a public page at https://avocadoscore.io/r/{id}, shareable by link. For just the headline scores as JSON:

GET/api/scans/{id}/summary

{ "id": "8c1f…", "domain": "example.com", "ready": true,
  "perf": 71, "seo": 88, "ai": 72 }

ready: false (with no scores) until the scan finishes; a score the engine couldn’t produce is null. A private (paid) scan’s scores are not returned without access. Cached for 5 minutes.

Badges

GET/api/badge/{domain}?metric=ai

A live SVG badge you can paste once (README, site footer, blog post): it always shows the domain’s latest result. metric is ai (the default), seo, perf or verdict. The score is coloured by band: 90+ green, 50–89 amber, below 50 red.

[![AI ready](https://avocadoscore.io/api/badge/example.com?metric=ai)](https://avocadoscore.io/)

GET /api/scans/{id}/badge?metric=… is the older per-scan version: a snapshot of one scan, which a re-scan doesn’t change.

Errors

Errors are JSON: { "error": "…" }, with a reason when the site itself couldn’t be read. Treat the message text as for humans and branch on the status code and reason.

reason values

dns
the domain doesn't resolve
refused
connection refused or reset
timeout
no response before the deadline
tls
certificate or TLS handshake problem
auth
the homepage needs a login (401)
forbidden
a firewall or CDN is blocking automated requests (403)
rate-limited
the site answered 429
not-found
the homepage is 404 or 410
client-error
another 4xx
server-error
the site answered 5xx
redirect-loop
too many redirects
redirect-invalid
a redirect we could not follow
bot-challenge
the site is behind a bot-protection challenge
login-wall
the homepage is a login page
unknown
something else went wrong

Limits and fair use

The endpoints are free and need no key, so they are rate limited per IP address. Limits are approximate: they reset over a rolling window and can vary slightly between our servers.

EndpointPer IPPer domain
POST /api/readiness30 / hour
POST /api/bot-check30 / hour
POST /api/llms-generator20 / hour
POST /api/scans5 / hour3 / day

Prefer a UI?

Everything above is also available without code: the readiness checker, the AI bot checker, the llms.txt generator and a full scan. Curious how sites compare? See the State of AI Readiness report.