DEV Community

Aaron VanSledright
Aaron VanSledright

Posted on

A free SEO audit API for developers: score any URL with one request

Short answer: yes, there is a free SEO API you can call from code. SEO Score API has a free tier of 2 audits per day with no credit card: send GET /audit?url=... with an X-API-Key header and you get back JSON with a 0-100 score, a letter grade, per-category scores and a list of fixes. The free tier runs 55 checks per URL; paid plans run 83 and start at $5 a month.

I'm Aaron, the solo developer who built it, so read this as a tutorial from the person with the bias. I've tried to be plain about what the free tier leaves out and when you should use something else.

How do I check a website's SEO score programmatically?

Three steps: get a key, make one GET request, read the JSON.

Sign up on the homepage or do it from the terminal. Signup is two calls because the key is tied to a verified email address:

curl -s -X POST https://seoscoreapi.com/signup \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com"}'

# a 6-digit code arrives by email
curl -s -X POST https://seoscoreapi.com/verify \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "code": "123456"}'
Enter fullscreen mode Exit fullscreen mode

Then audit a URL:

curl -s --max-time 120 -H "X-API-Key: YOUR_API_KEY" \
  "https://seoscoreapi.com/audit?url=https://example.com" \
  | jq '{score, grade, issues: (.priorities | length)}'
Enter fullscreen mode Exit fullscreen mode

With a paid key, that printed this when I ran it for this post:

{
  "score": 65.567,
  "grade": "C",
  "issues": 8
}
Enter fullscreen mode Exit fullscreen mode

Note that score is a decimal, not an integer. Compare it as a number.

What does the SEO audit API return?

Here is an excerpt of the real response for https://example.com, trimmed to one check per category and one fix. I removed items; I did not rename or add any field.

{
  "url": "https://example.com",
  "score": 65.567,
  "grade": "C",
  "response_code": 200,
  "response_time": "0.50s",
  "audit": {
    "meta": {
      "score": 52.75,
      "checks": [
        {
          "name": "title",
          "status": "warning",
          "value": "Example Domain",
          "score": 50,
          "recommendation": "Title is short (14 chars). Aim for 50-60 characters."
        }
      ]
    },
    "technical": {
      "score": 70.0,
      "checks": [
        { "name": "response_time", "status": "pass", "value": "0.50s", "score": 100 }
      ]
    }
  },
  "priorities": [
    {
      "severity": "high",
      "category": "meta",
      "issue": "Missing meta description",
      "fix": "Add a meta description (150-160 chars)",
      "plain_english": "The page has no summary for search results, so Google picks a random snippet that may not make people click.",
      "who_fixes_it": "content"
    }
  ],
  "ai_readability": {
    "ai_readability_score": 43,
    "ai_readability_grade": "F"
  }
}
Enter fullscreen mode Exit fullscreen mode

The audit object has five categories: meta, technical, social, performance and accessibility. Each has a score and a checks array, and each check has a name, a status (pass, warning, fail or info), the value found and usually a recommendation. priorities is the fix list sorted by severity, and who_fixes_it is developer, content or marketing. The response also carries a core_web_vitals block, which can come back with "status": "unavailable" when the upstream lookup fails, so don't assume it is populated.

How do I call it from Python?

There is an official client on PyPI (pip install seoscoreapi). It is a thin wrapper over requests:

import os
import sys

from seoscoreapi import audit

url = sys.argv[1] if len(sys.argv) > 1 else "https://example.com"
result = audit(url, api_key=os.environ["SEOSCORE_API_KEY"])

print(f"{result['url']}: {result['score']}/100 ({result['grade']})")

for name, category in result["audit"].items():
    print(f"  {name:<14} {category['score']}")

for p in result["priorities"]:
    print(f"  [{p['severity']}] {p['issue']} ({p['who_fixes_it']})")
Enter fullscreen mode Exit fullscreen mode

Output from my run:

https://example.com: 65.567/100 (C)
  meta           52.75
  technical      70.0
  social         50.0
  performance    96.25
  accessibility  66.667
  [high] Missing meta description (content)
  [high] No H1 tag found (content)
  [medium] Thin content (133 words) (content)
  ...
Enter fullscreen mode Exit fullscreen mode

audit() raises requests.HTTPError on a non-2xx response, so a 401 (bad key) or 429 (out of quota, or too many requests per minute) surfaces as an exception.

How do I call it from Node.js?

Same idea with the npm package (npm install seoscoreapi). It uses the built-in fetch, so you need Node 18 or later:

const { audit } = require("seoscoreapi");

async function main() {
  const url = process.argv[2] || "https://example.com";
  try {
    const result = await audit(url, process.env.SEOSCORE_API_KEY);
    console.log(`${result.url}: ${result.score}/100 (${result.grade})`);
    for (const p of result.priorities) {
      console.log(`  [${p.severity}] ${p.issue} -> ${p.fix}`);
    }
  } catch (err) {
    // err.status is the HTTP status: 401 bad key, 429 out of quota or too fast
    console.error(`Audit failed (${err.status || "network"}): ${err.message}`);
    process.exit(1);
  }
}

main();
Enter fullscreen mode Exit fullscreen mode

If you'd rather not add a dependency, the curl call above translates directly to fetch or requests.get. There is nothing else to the protocol.

What does the free tier not include?

The free tier is real (no trial clock, no card), but it is small, and the response is trimmed. From the pricing table and the API docs:

  • 2 audits per day and 2 requests per minute. Enough to test the API or watch one page. Not enough to audit a sitemap.
  • 55 checks, not 83. The SXO, AEO and AIO scoring blocks are paid. A free response has an _extended_gated placeholder where they would be.
  • A capped fix list and capped check detail. The overall score, grade and category scores are complete, but the priorities list and the per-category checks arrays are shortened on free keys. A _priorities_gated or _gated field tells you how many more there are.
  • No history, batch or monitoring. Score deltas, POST /audit/batch and scheduled monitoring start on the $5 Starter plan.
  • No accessibility (WCAG) audit, GEO audit or AI citation tracking. Those are paid endpoints.
  • One URL per call. /audit scores a page. It does not crawl a site.

Two more things worth knowing before you build on it. Audits add the audited domain to a public scoreboard unless you opt your key out with PUT /scoreboard/opt-out?opt_out=true. And set a client timeout of a minute or two: the site says most pages finish in about two seconds, but in my runs for this post one call took under 7 seconds and another took about a minute.

Paid plans, for reference: Starter $5/month (200 audits), Basic $15 (1,000), Pro $39 (5,000), Ultra $99 (25,000).

Which free SEO API should I use?

It depends on what you are measuring. I'd pick a different tool in several of these cases.

Tool Cost What you get Better choice when
SEO Score API (free tier) $0, 2 audits/day One score plus on-page, technical, social and AI-readability checks as JSON You want a single number and a fix list from one HTTP call, with nothing to host
Google PageSpeed Insights API Free Lighthouse lab data plus real-user Core Web Vitals where Google has them Performance is the question. It is Google's own data and I can't match it
Lighthouse CI Free, open source Lighthouse runs on your own machine or CI runner You need to test a local build or a page behind a login, or you want no third party and no quota
Open-source crawlers (Scrapy, advertools) Free, you host it Whatever you program it to collect, across a whole site You need site-wide crawling, broken-link checks or custom rules, and can maintain it

None of these, mine included, do keyword research or rank tracking. That is what Ahrefs, Semrush and Moz are for.

FAQ

Is there a free SEO API for developers?
Yes. SEO Score API's free tier gives 2 audits per day and 2 requests per minute, with no credit card. Google's PageSpeed Insights API is also free and is the better choice for performance data.

How many checks does the free tier run?
55 per URL, across meta and content, technical SEO, social tags, performance, accessibility and AI readability. Paid plans add 28 SXO, AEO and AIO checks for 83.

Do I need a credit card?
No. Signup is an email address and a 6-digit verification code.

Can I audit a whole site?
Not with one free call. /audit takes one URL. Batch audits (up to 10 URLs per request) and multi-page crawls are on paid plans.

Can I use it in CI?
Yes. There is an official GitHub Action, SeoScoreAPI/seo-audit-action, that fails a build when the score drops below a threshold. On the free tier, budget for 2 runs a day.

Where are the full docs?
The OpenAPI reference is at seoscoreapi.com/docs.

Top comments (0)