Most SEO regressions are not strategy failures. Someone ships a template change and every product page loses its meta description. A staging noindex survives the deploy. A redesign wraps the logo in an <h1> and the real heading becomes the second one. Nobody notices for three weeks, because nobody looks at the <head> of a page they can already see rendered.
Those are exactly the problems a machine is good at catching. You do not need a crawler or a headless browser for them; you need the page's metadata and a handful of structural counts, checked against rules you wrote down. Two catalog APIs return that data, and this lesson turns them into an audit that runs from a script, a CI job or a cron schedule.
What each API sees
SEO Data Scraper (seoscraper) reads a URL and returns what the page declares about itself: the <title>, the meta description, Open Graph and Twitter card tags, the robots meta tag, the viewport and the charset. It is a POST with a JSON body containing url, and it costs 10 credits.
curl -X POST "https://api.apiverve.com/v1/seoscraper" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com"}'title is set, but description, robots and every og: field come back as empty strings.
Look at what came back for example.com. The title is Example Domain. Everything else that the page does not declare is an empty string, not null and not missing. That matters for your code: if (data.description) works, if (data.description !== null) silently passes a page with no description at all.
Also notice the key names. The scraper returns social tags under their literal attribute names, og:title, twitter:card and so on. In JavaScript that means data['og:title'], not data.og.title. In Python it is an ordinary dict key.
SEO Quick Validator (seovalidator) answers a different question: not "what does the page say" but "what is structurally wrong with it". It is also a POST with url, also 10 credits.
curl -X POST "https://api.apiverve.com/v1/seovalidator" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com"}'checks.h1Count is 0 and hasCanonical is false. The issues array explains each failure in words.
The useful part of this response is the checks object. When we ran it against example.com it reported:
| Check | Value | Reading |
|---|---|---|
hasTitle / titleLength | true / 14 | Title exists but is short |
hasMetaDescription / metaDescriptionLength | false / null | No description; length is null when absent |
h1Count | 0 | No H1 at all |
hasCanonical | false | No canonical link tag |
hasViewport | true | Mobile viewport declared |
imagesTotal / imagesMissingAlt | 0 / 0 | Nothing to check |
externalLinksTotal / externalLinksMissingRel | 1 / 1 | One external link without rel |
Alongside checks you get passed, issueCount and an issues array of plain-English strings. Paid plans also get seoScore (0-100) and a letter grade.
So between them: the scraper gives you the content of the tags, the validator gives you counts and presence flags, including the heading structure the scraper does not report. A useful audit needs both, because "has a title" and "the title is the same on all 400 product pages" are different failures.
Your audit code checks `if (seo.description === null) flag('missing description')`. A page with no meta description passes. Why?
Answer the check above to continue.
Robots, noindex and what the scraper does not read
The robots field is the content of the robots meta tag on that page. It is the field that catches the most expensive mistake in this lesson: a staging environment configured with <meta name="robots" content="noindex"> and a deploy that carries the template to production. A regular expression on \bnoindex\b is enough; the tag can also say none, which means noindex, nofollow, so match that too if your stack ever emits it.
Be precise about what this does not cover. A page can be excluded from search in other ways that are not in its HTML: a robots.txt disallow rule, or an X-Robots-Tag response header. Those are not part of this response. If indexing is critical (and for revenue pages it is), check your robots.txt separately in the same job.
Run it across a site without wasting credits
One URL is 20 credits with both calls. Auditing a 2,000-page site daily is 40,000 credits a day, and almost all of it is re-confirming that nothing changed. Three habits keep the cost in proportion:
- Audit templates, not pages. A site with 2,000 product pages usually has one product template. Pick two or three representative URLs per template, plus the pages that make money. A template bug shows up on every sample.
- Run on change, not on a clock. The audit's natural trigger is a deploy. Run it in CI against the preview URL, then once against production after release.
- Store results and diff them. Keep each run's findings keyed by URL. Alert when a rule newly fails, not every time it fails. A known warning that has been accepted should not page anyone.
Run the URLs with modest concurrency (three or four at a time is plenty) rather than all at once. You are auditing your own site, but the requests still hit your servers, and the per-minute rate limit applies to your key. If you get a 429, read the x-api-remaining-credits header: 0 means the month is used up and retrying will not help; anything else is the rate limit, and retry-after tells you how long to wait.
There is one more failure mode to plan for: the page that was not reachable. A 404, a login wall or a bot challenge produces either an API error or a response that describes the wrong page (a challenge page has a title too). Treat errors as their own outcome, unreachable, never as a pass, and sanity-check that the returned title is not something like "Just a moment..." before trusting the rest.
Where to go from here
You now have an audit that fails on real problems, ignores noise, and costs a predictable number of credits. The next step in analysing a site is the layer underneath the HTML: what it is built with. Detect a website's tech stack covers how fingerprinting works, how to read confidence scores, and where detection is blind.