# Global Privacy Control Checker - Does Your Site Honor Opt-Out? (`that_red_bird/gpc-opt-out-checker`) Actor

California and other US states require sites to honor the Global Privacy Control opt-out signal. This Actor visits a site normally and again with Sec-GPC: 1, compares which ad pixels and cookies still fire, and gives a verdict per site. Two-visit check, not legal advice.

- **URL**: https://apify.com/that_red_bird/gpc-opt-out-checker.md
- **Developed by:** [mohamed alaya](https://apify.com/that_red_bird) (community)
- **Categories:** Developer tools, Lead generation, Other
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$5.00 / 1,000 site 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

## Global Privacy Control Checker - Does Your Site Honor Opt-Out?

Visits a website normally, then again sending the Global Privacy Control signal (`Sec-GPC: 1` plus `navigator.globalPrivacyControl`), and compares which advertising and analytics trackers fire and which tracking cookies are set. Gives a verdict per site.
For US privacy counsel, compliance teams and agencies checking California (CCPA/CPPA) and other state opt-out rules.

### Input examples

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

```json
{ "datasetId": "YOUR_MAPS_DATASET_ID", "websiteField": "website", "maxUrls": 40 }
```

US view through an Apify US proxy:

```json
{ "urls": ["https://www.example.com/"], "proxyConfiguration": { "useApifyProxy": true, "apifyProxyCountryCode": "US" } }
```

### Input guide

| Field | Meaning |
|---|---|
| `urls`, `datasetId`, `websiteField` | Sites to test; dataset website column optional |
| `settleSeconds` | Seconds to record after load, in both visits |
| `maxUrls`, `concurrency`, `locale`, `proxyConfiguration` | Size, speed, language, proxy |

### Output (one row per site)

| Field | Meaning |
|---|---|
| `verdict` | `HONORED` (ad/social trackers fire normally, none with GPC), `PARTIAL`, `NOT_HONORED`, `NO_ADVERTISING_TRACKERS`, `NO_TRACKERS` |
| `stillFiringUnderGpc[]` | Advertising/social hosts contacted although GPC was on |
| `disappearedUnderGpc[]` | Hosts contacted only in the normal visit |
| `adCookiesStillSetUnderGpc[]` | Advertising-looking cookies still set with GPC |
| `gpcWellKnown` | Result of `/.well-known/gpc.json` (found, `gpc: true`, last update) |
| `pageReadsGpcSignalInJs` | Whether a script read `navigator.globalPrivacyControl` |
| `normalVisit`, `gpcVisit` | Tracker hosts (operator, country, category) and tracking cookies of each visit |
| `findings[]` | For example `TRACKERS_FIRE_WITH_GPC`, `DECLARES_BUT_DOES_NOT_HONOR` |

Sample (shortened):

```json
{ "type": "site", "url": "https://www.espn.com/", "verdict": "HONORED",
  "verdictExplanation": "Advertising/social trackers fired in the normal visit (36) but none fired when GPC was sent.",
  "disappearedUnderGpc": ["securepubads.g.doubleclick.net", "ib.adnxs.com"], "gpcWellKnown": { "found": false } }
```

### Use it with

Google Maps scraper -> this Actor to find non-compliant local businesses; `consent-mode-v2-checker` and `gdpr-risky-embeds-checker` for the EU side.

### FAQ

**Is "NOT_HONORED" proof of a violation?** No. It means ad/social trackers loaded despite GPC. A loaded ad script is a signal to review, not proof that data was sold or shared.

**Why can two runs differ?** Ad tech changes between page loads. Re-run before drawing conclusions.

### Honest limits

Two anonymous visits, no banner clicked, from a datacenter IP (US proxy optional). Server-side sharing cannot be seen. The cookie check is name-based and the tracker list covers about 90 well-known services. Public pages only. Not legal advice.

### Price

**$0.005 per site audited** (`site-audited`). Errors free. Example: 40 sites = $0.20.

# Actor input Schema

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

Public pages to test, one per line. Each page is visited twice in fresh browsers: once normally and once sending the Global Privacy Control signal (Sec-GPC: 1 plus navigator.globalPrivacyControl).

## `datasetId` (type: `string`):

Pick the dataset of a Google Maps scraper run. The website column of every place is added to the URLs above. Social-media links are skipped.

## `websiteField` (type: `string`):

Name of the field in the dataset that holds the website address. Google Maps scrapers use 'website'. Only used when a dataset is selected.

## `maxUrls` (type: `integer`):

Upper limit on how many sites are tested in one run. Each site needs two browser visits, roughly 40 to 60 seconds in total.

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

How many sites are tested at the same time. Keep it low; each one uses full browser contexts.

## `settleSeconds` (type: `integer`):

Seconds to keep recording after each page has loaded, so late-firing pixels are caught in both visits.

## `locale` (type: `string`):

Language the browser announces (Accept-Language), for example en-US.

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

Optional Apify proxy. GPC rules apply to US visitors (California, Colorado and others), so for a realistic US view you can pick an Apify proxy with country code US. Off by default: the Actor visits sites directly from an Apify datacenter IP.

## Actor input object example

```json
{
  "urls": [
    "https://www.bbc.com/",
    "https://example.com/"
  ],
  "websiteField": "website",
  "maxUrls": 30,
  "concurrency": 2,
  "settleSeconds": 5,
  "locale": "en-US",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `downloadCsv` (type: `string`):

No description

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

No description

# 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://www.bbc.com/",
        "https://example.com/"
    ],
    "websiteField": "website",
    "locale": "en-US",
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("that_red_bird/gpc-opt-out-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 = {
    "urls": [
        "https://www.bbc.com/",
        "https://example.com/",
    ],
    "websiteField": "website",
    "locale": "en-US",
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("that_red_bird/gpc-opt-out-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 '{
  "urls": [
    "https://www.bbc.com/",
    "https://example.com/"
  ],
  "websiteField": "website",
  "locale": "en-US",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call that_red_bird/gpc-opt-out-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,that_red_bird/gpc-opt-out-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/6iiGOFq2QGK4PlaJB/builds/qFqd3icTdG1ZiMdg9/openapi.json
