Audit a page for SEO
Most audit tools hand back a wall of a hundred flagged items with no sense of which five are actually bleeding traffic. This SEO Audit API crawls a URL, checks the on-page fundamentals that search engines and users both depend on, and orders the findings by how much they realistically cost you, not by how easy they were to detect. Point it at a page and get a prioritized list instead of a checklist to argue about.
Run it online
Run this on our servers with your account. Free tools run in your browser; this one bills your KIT balance per the price above.
The problem with flat issue lists
A missing alt attribute on a decorative icon and a missing canonical tag on your highest-traffic landing page will often show up as two identical-looking bullet points in a typical audit report, even though one is cosmetic and the other can quietly split your ranking signals across duplicate URLs. Teams that triage audits by severity level instead of estimated impact end up spending a sprint fixing forty low-value items while the two that mattered sit untouched.
What the audit actually checks
POST /seo/audit crawls the given URL and evaluates the on-page elements that consistently correlate with rankings and click-through: title and meta description presence and quality, heading structure, canonical and indexability signals, image alt coverage, internal linking basics, and structured data validity where present. Each finding is returned with a severity ranking based on how directly it affects discoverability or user experience, so a broken canonical outranks a missing alt tag on a footer icon.
Why prioritization matters more than coverage
On-page SEO auditing as a discipline has existed since search engines first started rewarding structured, crawlable pages, and the checklist of things to verify has grown steadily longer with every algorithm update. The result is that thoroughness stopped being the hard part decades ago; ranking findings by actual consequence is the part most tools still get wrong, returning everything they found with equal visual weight regardless of whether it moves a needle.
Running it across a whole site, not one page
Because the endpoint is asynchronous, you can queue an audit per URL across an entire sitemap without waiting on each one to finish; a task_id comes back immediately and the full report arrives by signed webhook or a 24-hour signed link. That makes it practical to schedule a recurring audit — weekly, after every deploy, or after a content migration — and diff the results over time instead of running one-off checks by hand.
Where it fits in your workflow
Feed the audit's output straight into a ticketing system, sorted by the priority score, or gate a deploy on no new high-severity findings appearing. Nothing crawled is stored past the retention window, and no page content is ever used to train anything.
What you can do with it
Auditing before a site migration goes live
Run the audit against staging URLs before cutover to catch missing canonicals or broken heading structure while it's still cheap to fix.
Weekly monitoring of top landing pages
Schedule a recurring audit on your highest-traffic URLs and get alerted only when a new high-severity issue appears, not every minor variance.
Prioritizing a backlog of legacy pages
Audit an entire old blog archive at once and triage cleanup work by the severity ranking instead of guessing where to start.
Verifying a fix actually resolved the issue
Re-run the audit on a single URL after a change ships to confirm the flagged item is gone rather than trusting the deploy alone.
FAQ
What does the SEO audit actually check?
Title and meta description quality, heading structure, canonical and indexability signals, image alt coverage, basic internal linking, and structured data validity, ranked by how much each finding likely costs you in traffic.
How is severity ranking calculated?
Findings are ordered by their realistic impact on discoverability and user experience, not by how many issues were detected, so critical problems surface above cosmetic ones.
Can I audit a whole site at once?
Each call audits one URL, but because the endpoint is asynchronous you can queue one request per URL across a full sitemap without waiting in sequence.
Is there a free version to try?
There's no free tier — free tiers get abused and slow everyone down. Access runs on a prepaid ForHosting KIT balance: top up from $10.00 (it never expires) and each request is charged at its published price, so a call with no balance returns HTTP 402. No subscription, no tokens, no invented credits, and a failed task is never charged.
How do I get the audit results?
POST /seo/audit returns a task_id right away, and the finished report is delivered by signed webhook or a signed link valid for 24 hours.
What's the cost of auditing a large site?
It's $0.040 per request plus $0.001 per URL, so the total for a full sitemap scales predictably with page count.
What happens if a URL fails to load during the audit?
The task retries automatically up to three times before returning a clear error, and a failed task is never charged.
Does this replace manual SEO review?
It replaces the repetitive part — scanning and prioritizing on-page issues — so a human reviewer can focus on strategy instead of checklist work.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, and soon from our app, email and Telegram.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/seo/audit \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://ejemplo.com"}'const res = await fetch("https://api.kit.forhosting.com/seo/audit", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"url": "https://ejemplo.com"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/seo/audit",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"url": "https://ejemplo.com"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/seo/audit", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"url":"https://ejemplo.com"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"url":"https://ejemplo.com"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/seo/audit", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"url": "https://ejemplo.com"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "seo.audit",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
422 | task_failed | The task failed after 3 retries. You are never charged for it. |