# Site Compliance Checker (`vizellie/site-compliance-checker`) Actor

Flags likely cookie banner, accessibility, AI-readiness and privacy page issues on public websites. One row per site with a score, plus an optional HTML or PDF client report. $0.04 per site and $0.04 per report. It flags likely issues and is not legal advice or a compliance certification.

- **URL**: https://apify.com/vizellie/site-compliance-checker.md
- **Developed by:** [Vi Zellie](https://apify.com/vizellie) (community)
- **Categories:** SEO tools, Business, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $40.00 / 1,000 site checkeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Site Compliance Checker

Check a list of public websites and flag likely issues. Each site comes back as one row, with a score, a short list of findings, and a shareable HTML report.

Not legal advice; general information only.

These findings flag likely issues. This is not legal advice or a compliance certification.

### Who it is for

Site owners, agencies and consultants who want a quick, repeatable look at cookies set before anyone clicks, accessibility issues, AI crawler readiness, and basic privacy signals.

### What you get

- One result per website, even when several pages are opened.
- Cookies set before any click: name, domain, expiry, and whether the cookie is first party or third party. Cookie values are never saved.
- Known third party tracker domains that the page contacted, and whether a consent banner appears to be present. When it does, the result names the signals that matched. A script from a consent tool, on its own, is not reported as a banner. Cookie values are not among those signals.
- An accessibility scan: how many issues were found by severity, the main rule ids, and a few example selectors. Page text is not saved.
- AI readiness: robots.txt rules for well known AI crawlers, whether llms.txt is present, whether a sitemap was found, and meta robots or noai tags.
- Privacy signals: HTTPS, a privacy policy link, and which common security headers are present. Header values are not saved.
- A score from 0 to 100 and a letter grade, plus a short list of likely issues. If a check does not finish, the grade is incomplete and there is no score. That is not a pass.
- An HTML report saved with the run.
- An optional client-ready report you can hand to a client. Turn it on under **Client-ready report**. Off leaves the run unchanged.

Private and internal addresses are skipped and are not charged, including a redirect or a file the page itself tries to load. A site that could not be checked is saved with no score and is not charged. That includes a site whose robots.txt answered when the browser could not open a page. A robots.txt rule that tells this checker not to open pages is still a completed check. Sites that time out are not charged. The checker does not fill in forms, click buttons, or type into the page.

### Tutorial

1. Paste public website URLs into **Website URLs**. One result is returned per website.
2. Leave **Max pages per site** at 3 unless you need a wider look. The price is per site, not per page.
3. Set **Max sites** to the budget you want for this run. The default is 5 and the maximum is 25.
4. Leave **Respect robots.txt** on unless you operate the site and you want pages opened anyway.
5. Leave the four checks on, or turn off any you do not need. At least one check has to stay on.
6. Run the Actor.
7. Open the dataset for one row per site. Open the `OUTPUT` record for the summary, and the `REPORT` record for the HTML report.
8. Schedule the task if you want a standing check. A run that checks nothing still pays only the small start fee.

### Client-ready report

Use this when you want one file to send to a client. It is off by default. Off does not add a file and does not add a fee.

1. Paste the websites you want to check.
2. Set **Client-ready report** to **HTML**, or to **PDF** if you also want a PDF of the same page.
3. Run the Actor.
4. Open the Output tab. **Client report (HTML)** is `REPORT.html` in the key-value store. **Client report (PDF)** is `REPORT.pdf` when you chose PDF. **Client report summary** lists those keys.

The page has a cover with the site, the date and an overall grade, a short summary in plain language, and a table of findings. Each finding says what it means and how to fix it. A run with more than one site has a section per site. Pass, warning and fail stay readable in black and white. The footer says Generated with Site Compliance Checker.

The report fee is charged once per run, and only after the file is saved. HTML and PDF together are one fee. A failed save is not charged. The dataset and the existing `REPORT` summary stay included in the site fee.

### Example input

```json
{
  "startUrls": ["https://example.com/", "https://crawlee.dev"],
  "maxPagesPerSite": 3,
  "maxSites": 5,
  "concurrency": 1,
  "respectRobotsTxt": true,
  "includeCookies": true,
  "includeAccessibility": true,
  "includeAiReadiness": true,
  "includePrivacySignals": true
}
```

### Example output

One dataset row per website that was actually checked:

```json
{
  "url": "https://example.com/",
  "score": 72,
  "grade": "C",
  "disclaimer": "These findings flag likely issues. This is not legal advice or a compliance certification.",
  "pagesChecked": 3,
  "consentBannerLikely": true,
  "consentVendor": "OneTrust",
  "consentSignals": ["cookie:OptanonConsent", "global:OneTrust", "script:cdn.cookielaw.org"],
  "thirdPartyCookies": 2,
  "trackerDomains": 1,
  "criticalAccessibility": 0,
  "likelyIssues": [
    { "severity": "medium", "message": "Third-party cookies were set before any interaction." }
  ]
}
```

Cookie rows inside the result list the cookie name, domain, expiry and party. They never include the cookie value.

### Pricing

You pay a small fee when the run starts, plus a fee for each public website that is checked.

| What | Price |
|---|---|
| Run start | $0.00005 |
| Site checked | $0.04 |
| Client-ready report | $0.04 |

The site fee covers every page opened for that site, up to **Max pages per site**. Private addresses are not charged. A site that could not be checked is not charged, including when robots.txt answered but no page opened. A robots.txt block is still charged, because that check finished. A site whose grade is incomplete, because a check did not finish, is not charged. Sites that time out are not charged. The score, the findings and the HTML summary in `REPORT` are included. The client-ready report is charged once per run, only when that file is saved. Leave **Client-ready report** on Off and that fee is not charged. Add $0.04 to any example below when the report is saved.

**Examples**

- 1 site: about $0.04005
- 5 sites, the default: about $0.20005
- 25 sites, the maximum: about $1.00005
- A scheduled run that finds nothing new to check: $0.00005

### Privacy

The Actor does not collect personal data. It does not store cookie values, form contents, names, email addresses, phone numbers, or IP addresses. Page text and security header values are not saved. Logs are scrubbed the same way. Please do not put personal data in the input URLs. Query values that look like addresses, tokens or passwords are removed before a URL is stored.

### Limits

- At most 25 websites per run, and at most 10 pages on each website.
- At most 2 websites open at the same time. The default is 1. Choose 2 when the run has at least 4 GB of memory. The sites share one browser. Each site gets its own browser context, and that context is closed when the site finishes or runs out of time.
- The default memory is 2 GB. A heavy page plus the accessibility scan needs more than 1 GB.
- Each site has a time limit of 45 seconds plus 20 seconds per page, and never more than 180 seconds. The limit covers the file fetches and the browser. A site that runs out of time is saved as incomplete and is not charged. One slow site does not hold up the others.
- No new site starts in the last 60 seconds of the run. The summary then says the run stopped early. Sites already saved stay saved.

### Next additions

- Agency white-label logo
- Dutch report

# Actor input Schema

## `startUrls` (type: `array`):

Public websites to check, for example https://example.com/. One result is returned per website. Private and internal addresses are skipped and are not charged. A site that could not be checked is not charged. Sites that time out are not charged.

## `maxPagesPerSite` (type: `integer`):

How many pages to open on each website, starting from the URL you entered. Kept small by default. The price is per site, not per page.

## `maxSites` (type: `integer`):

Maximum number of websites to check in one run. Keeps the cost predictable.

## `concurrency` (type: `integer`):

How many websites to open at the same time. The default is 1, which fits the default 2 GB. Choose 2 only when the run has at least 4 GB. They share one browser.

## `respectRobotsTxt` (type: `boolean`):

Do not open pages that robots.txt disallows for this checker. The robots.txt file itself is still read. Turn this off only for sites you operate.

## `includeCookies` (type: `boolean`):

Open the page with no clicks and record cookie names, domains and expiry, plus known tracker domains. Cookie values are never saved.

## `includeAccessibility` (type: `boolean`):

Count accessibility issues by severity and list the main rule ids with a few selectors. Page text is not saved.

## `includeAiReadiness` (type: `boolean`):

Read robots.txt rules for well known AI crawlers, and note whether llms.txt, a sitemap, and noai directives are present.

## `includePrivacySignals` (type: `boolean`):

Note HTTPS, whether a privacy policy link was found, and which common security headers are present. Header values are not saved.

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

Save a report you can hand to a client. Off is the default: the run, the dataset and the price stay as they are today. HTML saves one self-contained page. PDF saves that page and a PDF of the same report. The report fee is charged once per run, and only after the file is saved.

## Actor input object example

```json
{
  "startUrls": [
    "https://example.com/"
  ],
  "maxPagesPerSite": 1,
  "maxSites": 5,
  "concurrency": 1,
  "respectRobotsTxt": true,
  "includeCookies": true,
  "includeAccessibility": true,
  "includeAiReadiness": true,
  "includePrivacySignals": true,
  "report": "off"
}
```

# Actor output Schema

## `sites` (type: `string`):

One dataset row per site.

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

The OUTPUT record in the default key-value store.

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

The REPORT record in the default key-value store.

## `clientReport` (type: `string`):

The REPORT.html record. Saved when Client-ready report is HTML or PDF.

## `clientReportPdf` (type: `string`):

The REPORT.pdf record. Saved when Client-ready report is PDF.

## `clientReportSummary` (type: `string`):

The CLIENT_REPORT record, with the report keys.

# 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 = {
    "startUrls": [
        "https://example.com"
    ],
    "maxPagesPerSite": 1,
    "maxSites": 5,
    "concurrency": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("vizellie/site-compliance-checker").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 = {
    "startUrls": ["https://example.com"],
    "maxPagesPerSite": 1,
    "maxSites": 5,
    "concurrency": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("vizellie/site-compliance-checker").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 '{
  "startUrls": [
    "https://example.com"
  ],
  "maxPagesPerSite": 1,
  "maxSites": 5,
  "concurrency": 1
}' |
apify call vizellie/site-compliance-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,vizellie/site-compliance-checker"
        }
    }
}
```

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/vUahIZh10Nwxhwsb3/builds/Yd9hbNVI0a3i9qpYe/openapi.json
