Trigger on-demand SEO audits for your domains, list past runs, and fetch detailed results. The crawler discovers pages, checks for SEO issues, and reports back. Only one audit can run per domain at a time.
All endpoints accept both session auth (dashboard) and API key auth (programmatic access). API keys scoped to a specific domain are restricted to that domain's runs.
API key access requires a Pro plan or above. Lower-tier API keys receive 403 { "error": "plan_required", "requiredPlan": "pro" }.
Start an Audit
/api/seo-spider/runsStart a new SEO audit run for a domain. The crawler will discover and analyze pages based on the selected mode.
Request Body
| Parameter | Type | Description |
|---|---|---|
domainrequired |
string | Domain to audit (e.g., "your-app.com"). |
urlsrequired |
string[] | Seed URLs to crawl (min 1, must be valid URLs). All URLs must belong to the target domain. In follow mode, typically just the homepage. |
moderequired |
"follow" | "selected" | "sitemap" | follow — spider from seed URLs following links. selected — only audit the specified URLs. sitemap — discover URLs from the domain's sitemap. |
allowSampling |
boolean | Enable URL pattern sampling on the crawler. Default: true. |
newPagesOnly |
boolean | Only audit new or updated pages since the last completed run (sitemap mode). Default: false. |
sitemapUrl |
string (URL) | Custom sitemap URL override. Falls back to the domain's configured sitemap if omitted. |
Response Body
{"ok": true,"runId": "a1b2c3d4-e5f6-...","status": "running"}
Response Codes
Audit started. Returns runId and status: "running".
Validation failed: invalid_urls, no_sitemap, or schema error.
Missing or invalid API key / session.
domain_not_owned, no_seo_spider_access, on_demand_limit_reached, or
max_pages_per_month_limit_reached.
run_already_active. An audit is already running for this domain. Response
includes the active runId.
no_new_pages. No new or updated pages found in sitemap since last audit
(when newPagesOnly: true).
Example
const response = await fetch("https://lovablehtml.com/api/seo-spider/runs", {method: "POST",headers: {"Content-Type": "application/json","x-lovablehtml-api-key": "<API_KEY>",},body: JSON.stringify({domain: "your-app.com",urls: ["https://your-app.com"],mode: "follow",allowSampling: true,}),});const result = await response.json();// { "ok": true, "runId": "a1b2c3d4-e5f6-...", "status": "running" }
curl -X POST \"https://lovablehtml.com/api/seo-spider/runs" \-H "Content-Type: application/json" \-H "x-lovablehtml-api-key: <API_KEY>" \-d '{"domain": "your-app.com","urls": ["https://your-app.com"],"mode": "follow","allowSampling": true}'
Limits: Audit access and page-per-run limits depend on your plan. Only one audit can run per domain at a time.
List Runs
/api/seo-spider/runsList the 50 most recent SEO audit runs across your domains, optionally filtered by domain.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
domain |
string | Filter to runs for a single domain. If the API key is scoped to a domain, only that domain's runs are returned regardless of this parameter. |
Response Body
{"runs": [{"id": "a1b2c3d4-e5f6-...","domain": "your-app.com","startedAt": 1762400000000,"completedAt": 1762400180000,"status": "success","trigger": "manual","frequency": "weekly","pagesCrawled": 42,"healthScore": 87.5,"issueCount": 12,"deltaIssues": -3,"deltaHealth": 2.1,"robotsAnalysis": { "...": "..." },"crawlStats": { "...": "..." },"runCount": 1,"closeReason": "finished","needsContinuation": false,"hitUrlLimit": false,"errorMessage": null}]}
status is one of queued, running, success, limit_reached, partial, or error. Timestamps are Unix epoch milliseconds. Results are ordered by startedAt descending and capped at 50.
Response Codes
Returns up to 50 runs. Empty runs array if the caller has no access to any
matching domain.
Missing or invalid API key / session (invalid_api_key).
Example
const response = await fetch("https://lovablehtml.com/api/seo-spider/runs?domain=your-app.com",{headers: {"x-lovablehtml-api-key": "<API_KEY>",},},);const { runs } = await response.json();// runs[0] = { id, domain, status, healthScore, issueCount, ... }
# All recent runs across your domainscurl "https://lovablehtml.com/api/seo-spider/runs" \-H "x-lovablehtml-api-key: <API_KEY>"# Filter to a single domaincurl "https://lovablehtml.com/api/seo-spider/runs?domain=your-app.com" \-H "x-lovablehtml-api-key: <API_KEY>"
Get Run Details
/api/seo-spider/runs/:runIdFetch a single audit run with its per-page results.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
runIdrequired |
string | The run ID returned by `POST /api/seo-spider/runs`. |
Response Body
{"run": {"id": "a1b2c3d4-e5f6-...","domain": "your-app.com","startedAt": 1762400000000,"completedAt": 1762400180000,"status": "success","trigger": "manual","frequency": "weekly","pagesCrawled": 42,"healthScore": 87.5,"issueCount": 12,"deltaIssues": -3,"deltaHealth": 2.1,"robotsAnalysis": { "...": "..." },"crawlStats": { "...": "..." },"runCount": 1,"closeReason": "finished","needsContinuation": false,"hitUrlLimit": false,"errorMessage": null,"sitemapIssues": []},"pages": [{"id": "page-uuid","path": "/","statusCode": 200,"loadTimeMs": 420,"healthScore": 92,"previewScore": 88,"indexable": true,"issueCount": 2,"issues": [{ "id": "missing_meta_description", "severity": "warning" }],"trendPoints": [85, 88, 92]}]}
pages is sourced from the live store while a run is recent and from cold storage once archived; the response shape is identical either way.
Response Codes
Returns the run and its pages.
Missing or invalid API key / session (invalid_api_key).
api_key_domain_scope_mismatch — the API key is scoped to a different domain.
domain_access_forbidden — session user lacks access to the run's domain.
Run does not exist or does not belong to the authenticated account.
Example
const response = await fetch("https://lovablehtml.com/api/seo-spider/runs/a1b2c3d4-e5f6-...",{headers: {"x-lovablehtml-api-key": "<API_KEY>",},},);const { run, pages } = await response.json();// run.healthScore, run.issueCount, pages[i].path, pages[i].issues, ...
curl "https://lovablehtml.com/api/seo-spider/runs/a1b2c3d4-e5f6-..." \-H "x-lovablehtml-api-key: <API_KEY>"
