# Québec Law 25 Privacy Auditor (Loi 25 Website Check) (`verif96/quebec-law-25-privacy-auditor`) Actor

Audit websites for Québec privacy law (Law 25): privacy policy, privacy officer contact, tracking pixels without consent tool, forms without notice. 0–100 score, FR/EN.

- **URL**: https://apify.com/verif96/quebec-law-25-privacy-auditor.md
- **Developed by:** [verif96 Audit](https://apify.com/verif96) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $50.00 / 1,000 website auditeds

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

## Québec Law 25 Privacy Auditor — Loi 25 Website Compliance Check

**Check in seconds whether a website meets the visible requirements of Québec's privacy law (Law 25 / Loi 25).**

Paste one or hundreds of website URLs. For each site, the Actor finds and reads the privacy policy, looks for the published contact of the person in charge of personal information, detects tracking pixels and cookie consent tools, and checks forms that collect personal data. You get a **0–100 score**, a verdict and a precise list of issues.

> 🇫🇷 **En bref :** collez des adresses de sites web. Pour chaque site, l'Actor vérifie la politique de confidentialité, la publication du responsable de la protection des renseignements personnels, les outils de suivi (Google Analytics, pixel Meta…) sans outil de consentement, et les formulaires sans mention de confidentialité. Score sur 100 et liste claire des problèmes, en français ou en anglais.

### Who is it for?

- **Web agencies & freelancers**: audit client sites, sell Law 25 compliance updates, or check sites before delivery.
- **Privacy, legal and compliance consultants**: run a fast first-pass audit on many websites before a detailed review.
- **Businesses operating in Québec**: monitor your own websites (and franchisees') on a schedule.

### What it checks

| Check | Why it matters under Law 25 |
|---|---|
| Privacy policy published | Businesses collecting personal information through technological means must publish a privacy policy on their website. |
| Privacy policy reachable | Detects privacy links leading to a missing page (404). |
| Policy language & content | Policy in French, and covering purposes, cookies, retention, access/correction rights, disclosure to third parties. |
| Privacy officer published | The title and contact details of the person in charge of the protection of personal information must be published on the website. |
| Trackers vs consent tool | Detects Google Analytics, Google Tag Manager, Google Ads, Meta Pixel, TikTok, LinkedIn, Hotjar, Clarity, Pinterest, Snapchat, X and Bing, and 19 cookie consent tools (Cookiebot, OneTrust, Axeptio, Didomi, CookieYes, Complianz, Google Consent Mode…). Tracking technologies must be off by default. |
| Forms without privacy notice | Forms collecting emails or phone numbers without any privacy notice or link. |

### Output example

```json
{
  "domain": "example.ca",
  "score": 50,
  "verdict": "likely_non_compliant",
  "verdictLabel": "Non conforme (probable)",
  "summary": "Le titre et les coordonnées du responsable de la protection des renseignements personnels ne sont pas publiés sur le site. Outils de suivi détectés (Google Analytics, Meta Pixel) sans outil de consentement aux témoins : ils doivent être désactivés par défaut.",
  "pagesAudited": 10,
  "privacyPolicyUrl": "https://example.ca/politique-de-confidentialite",
  "privacyPolicyLanguage": "fr",
  "privacyPolicyMissingTopics": ["durée de conservation"],
  "privacyOfficerPublished": false,
  "trackersDetected": ["Google Analytics", "Meta Pixel"],
  "consentToolDetected": [],
  "formsWithoutPrivacyNotice": 0,
  "issues": [
    { "severity": "high", "code": "NO_PRIVACY_OFFICER", "message": "..." },
    { "severity": "high", "code": "TRACKERS_WITHOUT_CONSENT_TOOL", "message": "..." },
    { "severity": "low", "code": "PRIVACY_POLICY_INCOMPLETE", "message": "..." }
  ],
  "auditedAt": "2026-10-22T12:00:00.000Z"
}
```

Verdicts: `likely_compliant` (score ≥ 85), `needs_review` (60–84), `likely_non_compliant` (< 60), `unreachable`.

### How to use

1. Add the websites to audit in **Websites to audit** (homepage URLs; `example.ca` without `https://` also works).
2. Choose how many pages to crawl per site (10 is a good default). Privacy and contact pages are always visited first.
3. Pick the report language (Français / English).
4. Run, then export results as JSON, CSV, Excel or via API.

💡 **Tip — combine with Bill 96:** audit the same list with the [Québec Bill 96 Website Auditor](https://apify.com/verif96/quebec-bill-96-website-auditor) to cover both French-language and privacy compliance.

💡 **Tip — monitoring:** create a Schedule (e.g. monthly) and connect an integration (email, Slack, Google Sheets, Make, Zapier).

### Pricing

Pay only for what you use: you are charged **per website successfully audited**. Unreachable or bot-protected websites are not charged.

### How it works

- Fast HTTP crawler (no browser) that reads the public HTML of each site, prioritizing privacy and contact pages.
- Trackers and consent tools are detected from the page source (scripts and tags).
- The privacy policy is analysed for language and key topics.

### Limitations

- This is an **automated indicator, not legal advice**. It does not replace a review by a privacy professional or the Commission d'accès à l'information du Québec.
- It analyses the **public HTML**: tools injected later by JavaScript (for example through Google Tag Manager) may not all be listed, and it does not verify that trackers actually wait for consent.
- It cannot check internal obligations (privacy impact assessments, incident register, governance policies).
- Websites that block bots (HTTP 403) are not bypassed: they are reported as not audited and are not charged.

### Responsible use

- Only public pages are read; the Actor does not submit forms and does not store personal data, only compliance indicators.
- **Anti-spam laws:** if you use these reports for prospecting, you are responsible for complying with Canada's Anti-Spam Legislation (CASL / LCAP). Do not send unsolicited commercial emails without the required consent.
- Do not present results as an official or legal certification, and do not imply any endorsement by the Commission d'accès à l'information.

# Actor input Schema

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

Homepage URLs of the websites to audit (one report per website). You can paste hundreds of URLs or upload a list.

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

How many pages to crawl on each website. Privacy and contact pages are always visited first.

## `reportLanguage` (type: `string`):

Language of the verdict, summary and issue messages.

## `proxyConfiguration` (type: `object`):

The default Apify proxy works for most websites. Websites that block bots are reported as not audited and are not charged.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.quebec.ca"
    }
  ],
  "maxPagesPerSite": 10,
  "reportLanguage": "fr",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `reports` (type: `string`):

One item per website audited.

# 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": [
        {
            "url": "https://www.quebec.ca"
        }
    ],
    "maxPagesPerSite": 10,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("verif96/quebec-law-25-privacy-auditor").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": [{ "url": "https://www.quebec.ca" }],
    "maxPagesPerSite": 10,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("verif96/quebec-law-25-privacy-auditor").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": [
    {
      "url": "https://www.quebec.ca"
    }
  ],
  "maxPagesPerSite": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call verif96/quebec-law-25-privacy-auditor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,verif96/quebec-law-25-privacy-auditor"
        }
    }
}
```

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/gdvJanxYKyf7PvMOy/builds/9Ruze5ZDjtdqk8WEt/openapi.json
