Try the RankNibbler SEO API

Keyword analysis Beta

GET /api/v1/keyword-analysis

Scores a page against the keywords you actually care about and tells you exactly which placements are missing. Dozens of placement checks per keyword across metadata, headings, body copy, the URL slug, images and Open Graph, returned as a 0–100 score with every check labelled pass, warn or fail.

Beta. This endpoint is new: it is live and safe to call on every plan, but its response shape may still change while we take feedback. Nothing here is scheduled for removal — if you depend on a particular field, tell us and we will keep it stable for you.
No search-volume or ranking data. This endpoint scores on-page placement of keywords you supply. It does not return search volume, difficulty, SERP positions or competitor rankings — none of those are exposed by this API.

Authentication

Send your API key as an X-API-Key header, or as a key query parameter. Available on every plan, including Free — plans differ only in requests per day. This call costs one request against your daily quota, which is shared across every key on the account. See Authentication.

Query parameters

NameTypeDescription
url requiredstringThe page to analyse.
keywords requiredstringComma-separated target keywords, maximum 5 (anything beyond the fifth is dropped). Alias: keyword.
key optionalstringYour API key, if not sent as the X-API-Key header.

Request

Response

200 · application/json
  1. {
  2. "url": "https://example.com", "host": "example.com", "statusCode": 200,
  3. "title": "Example Domain", "metaDescription": null,
  4. "keywords": ["coffee beans", "arabica"],
  5. "results": [{
  6. "keyword": "coffee beans", "score": 68, "issues": 8,
  7. "categories": [
  8. { "key": "meta", "label": "Meta data", "score": 60, "checks": 5 },
  9. { "key": "html", "label": "HTML optimization", "score": 75, "checks": 9 },
  10. { "key": "other", "label": "Other", "score": 50, "checks": 4 }
  11. ],
  12. "checks": [{ "cat": "meta", "imp": "high", "label": "Keyword in the title tag",
  13. "status": "pass", "detail": "“coffee beans” is in the title" }],
  14. "stats": { "occurrences": 14, "density": 3.4, "position": 12, "totalWords": 412 }
  15. }],
  16. "elements": {
  17. "headings": [{ "level": 1, "text": "Best Coffee Beans", "dup": false }],
  18. "blocks": [{ "text": "…", "len": 240, "repeated": false }],
  19. "topKeywords": [{ "word": "coffee", "count": 22, "density": 5.3, "score": 85 }],
  20. "media": [{ "url": "/a.png", "alt": "a", "title": "" }]
  21. }
  22. }

Response fields

FieldTypeDescription
results[]arrayOne entry per keyword, in the order you supplied them.
results[].scoreinteger0–100 optimisation score for that keyword on that page.
results[].categoriesarrayPer-category roll-up — meta data, HTML optimisation and other — with a score and the number of checks in each.
results[].checksarrayEvery individual check: cat, importance (imp), label, status (pass/warn/fail) and a human-readable detail.
results[].statsobjectOccurrences, density (%), first-occurrence position and the page's total word count.
elementsobjectThe raw page material the checks were run against — headings, text blocks, the page's own top keywords and its images.

Errors

This endpoint validates before it authenticates. The keyword-engine availability check and the keywords parameter check both run before the API key is verified, so a request with a missing or invalid key does not reliably return 401 — a call with no keywords returns 400, and a call made while the engine is unavailable returns 503, regardless of the key. Send a valid keywords value if you want to test your authentication against this endpoint.
StatusWhen
400keywords (or keyword) is missing or empty: { "error": "Missing keywords parameter (comma-separated, max 5)" }. Returned before the key is checked.
503The keyword engine is unavailable on this server. Also returned before the key is checked.
401Missing or invalid API key — only once keywords is present and the engine is available.
403The URL is a private, loopback or cloud-metadata address and was blocked by SSRF protection.
429Burst rate limit (60 req/10s per IP, 30 req/10s per key) or your daily quota. See Rate limits.
502The target URL could not be fetched.

Errors return { "error": "…" }; see Errors.