# SEO Audit API – On-Page Checks for Any URL (`sfoln/onpage-seo-audit`)

Audit the on-page SEO of any URL: title and meta description lengths, H1s, canonical, word count, links, images missing alt text, load time, page size, on-page score and the list of failed checks, one JSON record per page. $4 per 1,000 pages; JavaScript rendering is optional.

- Family: SEO & search
- Categories: SEO tools, Lead generation, Developer tools
- Availability: on request (private on Apify). Email contact@sfoln.com with subject "Access request: SEO Audit API – On-Page Checks for Any URL (sfoln/onpage-seo-audit)" before calling; calls fail until it is public.
- JSON: https://www.sfoln.com/actors/onpage-seo-audit.json
- MCP: https://mcp.apify.com?tools=sfoln/onpage-seo-audit
- REST (sync): POST https://api.apify.com/v2/actors/sfoln~onpage-seo-audit/run-sync-get-dataset-items
- REST (async): POST https://api.apify.com/v2/actors/sfoln~onpage-seo-audit/runs

SEO Audit API – On-Page Checks for Any URL runs a technical on-page SEO audit of any web page with one API call per URL. Each page is fetched live and checked for title and meta description (with lengths), H1 headings, canonical, word count, internal and external links, images and missing alt text, page size, load time, structured data and Open Graph. You also get DataForSEO's on-page score and the list of SEO checks the page fails (e.g. no_h1_tag, title_too_long, low_content_rate). Use it for SEO audits, pre-launch QA, client reports and monitoring, or as a tool for AI agents. Turn on JavaScript rendering for client-rendered sites.

## Price per delivered record

| Event | Price | Per 1,000 | Charged for |
| --- | --- | --- | --- |
| Page audit (`onpage-page-audit`) | $0.004 | $4 / 1,000 | Charged once per page audited. |
| JavaScript render (`onpage-javascript-render`) | $0.006 | $6 / 1,000 | Charged once per audited page when "Render JavaScript" is enabled. |

Pay-per-event, USD, billed by Apify; no platform usage charge. Only records with status `ok` are charged. Cap a run with `maxTotalChargeUsd`. Apify free plan: up to 10 per run.

## Run

```bash
curl -X POST "https://api.apify.com/v2/actors/sfoln~onpage-seo-audit/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"urls":["https://dataforseo.com/"]}'
```

MCP client configuration:

```json
{
  "mcpServers": {
    "apify": {
      "type": "http",
      "url": "https://mcp.apify.com?tools=sfoln/onpage-seo-audit"
    }
  }
}
```

Example prompt: Run an on-page SEO audit of https://apify.com/ and list the failed checks, the title and meta description lengths and the page load time.

## Input

Enter page URLs. Each URL is fetched live and audited (about 5–60 seconds per page).

| Field | Type | Default | Meaning |
| --- | --- | --- | --- |
| `urls` (required) | array | — | Page URLs: Page URLs to audit, one per line (https:// is added when missing). Accounts on the Apify free plan can process up to 10 pages per run. |
| `enableJavascript` | boolean | `false` | Render JavaScript: Execute JavaScript before auditing (for client-rendered sites). Adds the onpage-javascript-render event per page. Not available on the Apify free plan. |
| `checkSpell` | boolean | `false` | Check spelling: Run a Hunspell spell check and return misspelled words (no extra charge). |
| `acceptLanguage` | string | `"en-US,en;q=0.9"` | Accept-Language header: Sent with the page request; some sites refuse requests without it. |
| `maxUrls` | integer | `1000` | Max URLs: Safety cap on how many URLs are processed in this run. |
| `concurrency` | integer | `3` | Concurrency: How many pages are processed in parallel. |
| `includeRaw` | boolean | `false` | Include raw upstream response: Attach the unmodified DataForSEO item to each result record. |

Example input:

```json
{
  "urls": [
    "https://dataforseo.com/"
  ]
}
```

## Output

One record per input item with `status` (`ok` is charged; `not_found`, `error`, `skipped_*` are free) and `charged`. The run stores an `OUTPUT` summary record.

| Field | Type | Meaning |
| --- | --- | --- |
| `url` | string | URL: Audited URL. |
| `inputUrl` | string | Input URL: The URL as given in the input (ok records). |
| `statusCode` | integer | null | HTTP status: Status code returned by the page. |
| `resourceType` | string | null | Resource type: html \| broken \| redirect. |
| `redirectLocation` | string | null | Redirect location: Target of a redirect (resourceType redirect). |
| `fetchTime` | string | null | Fetch time: When the page was fetched. |
| `title` | string | null | Title: <title> text. |
| `titleLength` | integer | null | Title length: Characters. |
| `description` | string | null | Meta description: Meta description text. |
| `descriptionLength` | integer | null | Description length: Characters. |
| `h1` | array | H1: All H1 headings. |
| `h2Count` | integer | H2 count: Number of H2 headings. |
| `canonical` | string | null | Canonical: Canonical URL. |
| `metaFollow` | boolean | null | Follow: False when the page tells crawlers not to follow its links (meta robots nofollow). |
| `wordCount` | integer | null | Word count: Words of visible text. |
| `contentRate` | number | null | Text-to-HTML ratio: Plain-text share of the HTML. |
| `readabilityFleschKincaid` | number | null | Readability (Flesch-Kincaid): Flesch–Kincaid readability index. |
| `internalLinks` | integer | null | Internal links: Links to the same domain. |
| `externalLinks` | integer | null | External links: Links to other domains. |
| `images` | integer | null | Images: Images on the page. |
| `hasImagesWithoutAlt` | boolean | null | Images without alt: True when at least one image has no alt text. |
| `scripts` | integer | null | Scripts: Script files on the page. |
| `stylesheets` | integer | null | Stylesheets: Stylesheet files on the page. |
| `renderBlockingResources` | integer | null | Render-blocking resources: Render-blocking scripts plus stylesheets. |
| `pageSize` | integer | null | Page size (bytes): HTML size in bytes. |
| `domSize` | integer | null | DOM size (bytes): Total DOM size in bytes. |
| `loadTime` | number | null | Load time (ms): Time to interactive (falls back to DOM complete). |
| `largestContentfulPaint` | number | null | LCP (ms): Largest Contentful Paint (needs JavaScript rendering). |
| `cumulativeLayoutShift` | number | null | CLS: Cumulative Layout Shift score. |
| `hasMicromarkup` | boolean | null | Structured data: True when the page has schema.org / microdata markup. |
| `hasOpenGraph` | boolean | Open Graph: True when og: tags are present. |
| `brokenLinks` | boolean | null | Broken links: True when the page links to broken pages. |
| `brokenResources` | boolean | null | Broken resources: True when the page loads broken resources (images, scripts, stylesheets). |
| `onpageScore` | number | null | On-page score: DataForSEO on-page score 0–100. |
| `failedChecks` | array | Failed checks: Names of the SEO checks this page fails (e.g. no_h1_tag, title_too_long). |
| `failedChecksCount` | integer | Failed checks count: Number of failed checks. |
| `passedChecksCount` | integer | Passed checks count: Number of passed checks. |
| `misspelledWords` | array | Misspelled words: Only with checkSpell. |
| `server` | string | null | Server: Server software reported by the page response. |
| `mediaType` | string | null | Media type: Content type of the page (e.g. text/html). |
| `contentEncoding` | string | null | Content encoding: Compression of the response (e.g. gzip, br). |
| `javascriptRendered` | boolean | JavaScript rendered: Whether JavaScript rendering was requested. |
| `javascriptCharged` | boolean | JavaScript charged: Whether onpage-javascript-render was charged. |
| `input` | string | object | null | Input: URL as entered. |
| `status` | string | Status: ok \| not_found \| error \| skipped_invalid \| skipped_budget \| skipped_free_plan |
| `charged` | boolean | Charged: Whether this record incurred a pay-per-event charge. |
| `chargedEvent` | string | Charged event: onpage-page-audit. |
| `warnings` | array | Warnings: Non-fatal notes (limit reduced, budget reached...). |
| `error` | object | Error: {code, message, provider?} when status is not ok. |
| `source` | string | Source: Upstream data source. |
| `fetchedAt` | string | Fetched at: ISO timestamp. |

Example record:

```json
{
  "url": "https://dataforseo.com/",
  "statusCode": 200,
  "resourceType": "html",
  "fetchTime": "2026-10-14 10:00:00 +00:00",
  "title": "DataForSEO",
  "titleLength": 10,
  "description": "APIs for SEO",
  "descriptionLength": 12,
  "h1": [
    "Powerful API Stack"
  ],
  "h2Count": 1,
  "canonical": "https://dataforseo.com/",
  "metaFollow": true,
  "wordCount": 1300,
  "internalLinks": 150,
  "externalLinks": 12,
  "images": 30,
  "hasImagesWithoutAlt": true,
  "pageSize": 220000,
  "loadTime": 640,
  "hasMicromarkup": true,
  "hasOpenGraph": true,
  "onpageScore": 91.4,
  "failedChecks": [
    "no_image_alt",
    "title_too_short"
  ],
  "failedChecksCount": 2,
  "javascriptRendered": false,
  "javascriptCharged": false,
  "input": "https://dataforseo.com/",
  "status": "ok",
  "charged": true,
  "chargedEvent": "onpage-page-audit",
  "source": "dataforseo",
  "fetchedAt": "2026-10-14T10:00:00.000Z"
}
```

## Related

- [Website Traffic Checker – SEO Overview](https://www.sfoln.com/actors/domain-seo-overview.md) (`sfoln/domain-seo-overview`)
- [SEO Competitor Analysis – Traffic & Keywords](https://www.sfoln.com/actors/seo-competitor-snapshot.md) (`sfoln/seo-competitor-snapshot`)
- [URL Metadata & Open Graph Extractor](https://www.sfoln.com/actors/url-metadata.md) (`sfoln/url-metadata`)
- [Domain WHOIS & DNS Lookup](https://www.sfoln.com/actors/domain-intelligence.md) (`sfoln/domain-intelligence`)
- [Ranked Keywords Checker for Any Domain](https://www.sfoln.com/actors/ranked-keywords.md) (`sfoln/ranked-keywords`)

Publisher: SFOLN LLC, contact@sfoln.com. Catalogue: https://www.sfoln.com/catalog.json. Agent guide: https://www.sfoln.com/agents.md.
