# Website Audit: PageSpeed, Core Web Vitals & WCAG Accessibility (`iiclabs/site-audit-pagespeed-wcag`) Actor

Audit every page of a sitemap or URL list in one run: Google PageSpeed Insights Lighthouse scores and real-user Core Web Vitals, plus a full WCAG 2.2 accessibility audit (axe-core) listing each failing element, its fix and EN 301 549 clause. Client-ready PDF report.

- **URL**: https://apify.com/iiclabs/site-audit-pagespeed-wcag.md
- **Developed by:** [IIC Labs](https://apify.com/iiclabs) (community)
- **Categories:** SEO tools, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $7.00 / 1,000 page auditeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Website Audit: PageSpeed, Core Web Vitals & WCAG Accessibility

**Audit every page of a website in one run: Google PageSpeed Insights (Lighthouse) scores and real-user Core Web Vitals, plus a full WCAG 2.2 accessibility audit that lists each failing element with its fix, WCAG success criterion and EN 301 549 clause. You get a dataset with one item per page and a client-ready report (HTML and PDF).**

Give it page URLs or a sitemap. For each page it:

- asks Google's official **PageSpeed Insights API** for the Lighthouse scores (performance, accessibility, best practices, SEO), lab timings (LCP, CLS, TBT, FCP, Speed Index, server response) and **real-user Core Web Vitals** from the Chrome UX Report (LCP, INP, CLS, with Google's fast/average/slow verdict);
- opens the page in Chrome and runs **axe-core** with the WCAG 2.2, 2.1 or 2.0 A/AA rules, returning every failing element with the rule, impact (critical, serious, moderate, minor), how to fix it, the WCAG success criteria and the **EN 301 549** clauses used for the European Accessibility Act;
- adds a site-wide summary: average scores, Core Web Vitals verdicts, and the accessibility failures that appear on the most pages.

### Why this one

PageSpeed tools report Lighthouse's accessibility *score*. That score comes from a subset of checks and doesn't tell you which elements fail or how to fix them. This Actor runs the full axe-core WCAG rule set on every page (the engine behind most accessibility testing tools, also used by our Website Audit browser extension for [Chrome](https://chromewebstore.google.com/detail/ofjgbdecoflmpcijgjpjlfaenkhklhjo) and [Edge](https://microsoftedge.microsoft.com/addons/detail/accessibility-auditor-wc/ocdfilleipjggniangdmacinjhbbdlnp)) next to the speed audit. Agencies, developers and site owners get both findings, per element, in one run and one report.

### Input

| Field | What it does |
|---|---|
| **Pages** | Page URLs to audit. |
| **Sitemaps** | `sitemap.xml`, a sitemap index or `.xml.gz`; their pages are added after the ones above. |
| **Maximum pages** | Stops after this many pages (default 50). |
| **Speed** / **Device** | PageSpeed Insights on mobile, desktop or both. |
| **Accessibility** / **WCAG version** | The full WCAG audit, against WCAG 2.2 AA (default), 2.1 AA or 2.0 AA. |
| **Include axe best practices** | Also reports axe-core's best-practice rules, which go beyond WCAG. |
| **Elements listed per issue** | How many failing elements each issue lists (counts always include all). |
| **PDF report** | Saves the report as a PDF too. |
| **Report title**, **Your brand name**, **Your logo** | White-label client report: your title, name and logo at the top of the report. |
| **Remove the "Made with Website Audit" line** | Leaves out our credit line. No extra charge. |
| **Compare with the previous audit** / **History name** | Remembers each page's last audit in your own Apify storage and shows what is **new** and what was **fixed** since then, plus performance score changes. Run it on a schedule to track progress; the first run is the baseline. |
| **Your PageSpeed Insights API key** | Optional; speed checks use our key by default. |

Example input:

```json
{
  "sitemaps": ["https://example.com/sitemap.xml"],
  "maxPages": 100,
  "strategy": "both",
  "standard": "wcag22aa"
}
```

### Output

One dataset item per page (the *Overview* view shows the scores and issue counts as a table):

```json
{
  "url": "https://example.com/pricing",
  "title": "Pricing",
  "speed": {
    "mobile": {
      "performance": 87, "accessibility": 95, "bestPractices": 100, "seo": 92,
      "lab": { "lcpMs": 2346, "cls": 0.012, "tbtMs": 120, "fcpMs": 1235, "speedIndexMs": 3456, "ttfbMs": 210 },
      "field": { "scope": "page", "overall": "FAST", "lcpMs": 2100, "inpMs": 180, "cls": 0.05 }
    }
  },
  "accessibility": {
    "standard": "WCAG 2.2 AA",
    "counts": { "critical": 2, "serious": 4, "moderate": 0, "minor": 0, "needsReview": 1, "elements": 46 },
    "issues": [
      {
        "ruleId": "image-alt", "kind": "violation", "impact": "critical",
        "help": "Images must have alternative text",
        "wcag": ["1.1.1"], "level": "A", "en301549": ["9.1.1.1"], "elements": 33,
        "nodes": [{ "target": "#logo", "html": "<img id=\"logo\" src=\"/logo.png\">", "summary": "Fix any of the following: Element does not have an alt attribute ..." }]
      }
    ]
  },
  "errors": []
}
```

In the run's key-value store:

- **REPORT**: the report as an HTML page, ready to send or print;
- **REPORT.pdf**: the same report as a PDF (when *PDF report* is on);
- **OUTPUT**: the summary as JSON (averages, Core Web Vitals verdicts, the most common failures).

### Pricing

Pay per event:

- **Page audited**: charged once per page that returned results, whichever checks you turned on. Pages that fail to load (for example HTTP 404) are listed with the error and not charged.
- **PDF report**: charged once per run when the PDF is saved.
- A small start fee per run, set by Apify.

The *Maximum cost per run* you set in Apify is respected: the run stops before going over it.

### Good to know

- **Automated checks find a subset of WCAG issues.** Manual testing is still needed (keyboard use, screen readers, meaning of content). Issues marked *check by hand* (`needs-review`) could not be decided automatically. A page without failures is not necessarily accessible, and this audit does not certify compliance.
- **Real-user data** comes from Google's Chrome UX Report (last 28 days). Pages with too few visits show the whole site's data (`"scope": "origin"`) or none.
- Pages are loaded like a visitor's browser would load them, without logging in. The audit only reads pages; it doesn't change anything.
- Audit only sites you're allowed to test. Very large audits (thousands of pages a day) should use your own free PageSpeed Insights key. On the free Apify plan, runs that use our key for speed checks cover up to 10 pages; paid plans and runs with your own key have no such limit.

### FAQ

**Can I audit pages behind a login?** Not yet; public pages only.

**Which axe-core version?** 4.14, as in our browser extension.

**Can I hand the report to clients as my own?** Yes: set your brand name and logo, a report title, and remove the credit line.

**Can it show what changed since the last audit?** Yes: turn on *Compare with the previous audit* and run it on a schedule. The report and every dataset item show new, fixed and remaining failures and performance changes.

**Can I run it on a schedule?** Yes, with Apify Schedules; each run produces its own report.

**Support:** support+siteaudit@iiclabs.com. If something looks wrong, include the run ID. If the audit helped you, a rating on this page helps others find it.

# Actor input Schema

## `urls` (type: `array`):

Page URLs to audit (http or https). Add a sitemap below to audit a whole site.

## `sitemaps` (type: `array`):

Sitemap URLs (sitemap.xml, a sitemap index or .xml.gz). Their pages are added after the ones above, up to the maximum.

## `maxPages` (type: `integer`):

Stop after this many pages (you pay per page audited).

## `speed` (type: `boolean`):

Google Lighthouse scores (performance, accessibility, best practices, SEO), lab timings and real-user Core Web Vitals (LCP, INP, CLS) from Google's PageSpeed Insights API.

## `strategy` (type: `string`):

Which Lighthouse run to request for speed. Both doubles the PageSpeed calls but not the price.

## `accessibility` (type: `boolean`):

Runs axe-core in Chrome on each page and lists every failing element with the rule, the fix, its WCAG success criteria and EN 301 549 clauses.

## `standard` (type: `string`):

Rules to check, at level A and AA.

## `bestPractices` (type: `boolean`):

Also report axe-core's best-practice rules, which are not WCAG requirements.

## `maxElementsPerIssue` (type: `integer`):

How many failing elements each issue lists in the dataset (counts always include all).

## `pdfReport` (type: `boolean`):

Also save the run's report as REPORT.pdf (charged once per run). The HTML report (REPORT) is always saved.

## `reportTitle` (type: `string`):

Replaces the default title ("Site audit: example.com") on the report. For client reports.

## `brandName` (type: `string`):

Shown at the top of the report, so you can hand it to clients as your own.

## `logoUrl` (type: `string`):

A link to your logo (PNG, JPG, SVG or WebP) shown at the top of the report.

## `hideBranding` (type: `boolean`):

White-label report: leaves out our credit line. No extra charge.

## `compareWithPrevious` (type: `boolean`):

Remembers each page's last audit in your own Apify storage and reports what is new and what was fixed since then, plus performance score changes. Use it on a schedule to track progress. The first run becomes the baseline.

## `historyName` (type: `string`):

Separate history per site or client. Only used with "Compare with the previous audit".

## `pageSpeedApiKey` (type: `string`):

Only needed for very large audits, or to audit more than 10 pages per run on the free Apify plan: speed checks use our key by default. A key is free from Google Cloud (PageSpeed Insights API).

## Actor input object example

```json
{
  "urls": [
    "https://iiclabs.com/",
    "https://iiclabs.com/accessibility-auditor"
  ],
  "sitemaps": [
    "https://iiclabs.com/sitemap.xml"
  ],
  "maxPages": 50,
  "speed": true,
  "strategy": "mobile",
  "accessibility": true,
  "standard": "wcag22aa",
  "bestPractices": false,
  "maxElementsPerIssue": 10,
  "pdfReport": true,
  "hideBranding": false,
  "compareWithPrevious": false,
  "historyName": "default"
}
```

# Actor output Schema

## `pages` (type: `string`):

One item per page: speed scores, Core Web Vitals and WCAG findings.

## `report` (type: `string`):

The client-ready report for the whole run.

## `reportPdf` (type: `string`):

The same report as a PDF, when the PDF option is on.

## `summary` (type: `string`):

Totals: pages audited, average scores, Core Web Vitals verdicts and the most common WCAG failures.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        "https://iiclabs.com/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("iiclabs/site-audit-pagespeed-wcag").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "urls": ["https://iiclabs.com/"] }

# Run the Actor and wait for it to finish
run = client.actor("iiclabs/site-audit-pagespeed-wcag").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "urls": [
    "https://iiclabs.com/"
  ]
}' |
apify call iiclabs/site-audit-pagespeed-wcag --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,iiclabs/site-audit-pagespeed-wcag"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/bqgorEAbDs1jexBNj/builds/T7nkMMXzDj5XqF8jF/openapi.json
