Cookie Consent Audit avatar

Cookie Consent Audit

Pricing

from $42.50 / 1,000 domain auditeds

Go to Apify Store
Cookie Consent Audit

Cookie Consent Audit

Check any website for cookie consent problems from an EU address. One row per domain: consent platform, reject button on the first layer, cookies and trackers fired before consent and after reject, and Global Privacy Control response. Signals for privacy teams and DPOs.

Pricing

from $42.50 / 1,000 domain auditeds

Rating

0.0

(0)

Developer

Mamba Labs

Mamba Labs

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

8 hours ago

Last modified

Share

Check any website for cookie consent problems the way an EU visitor meets them. The actor loads each domain from an EU address in fresh browser sessions: once before any consent click, once after clicking the reject button, and once with Global Privacy Control on. You get one flat row per domain with the consent platform it found, whether a reject button sits on the first layer of the banner, the tracking cookies and tracker requests that fired before consent and after the reject, and how the site responds to Global Privacy Control.

Built for privacy teams, data protection officers, and the agencies that audit sites for them. The output is a list of signals for a human to review. It is not a legal finding.

Features

  • An EU vantage point. Banners change by visitor region, so a US address audits the wrong banner. In every browser session, the page itself and every request that decides the banner (the consent platform, Google tags, and consent hosts) go through the Apify proxy in the EU country you pick (Germany by default). Other requests, such as tracker calls and static files, are fetched directly and handed to the browser with its own cookies, so they are still seen and recorded. If no address in that country is available, the actor does not audit the domain from somewhere else; the row says so and is free.
  • Three fresh sessions per domain. No cookie or browser storage carries from one session to the next: before consent, after reject, and with Global Privacy Control on.
  • Before consent. Every cookie set and every request sent to a known tracker host before anyone clicks, with vendor and category (analytics, advertising, session replay, marketing automation).
  • First layer controls. Whether accept and reject (or "necessary only") controls are visible on the first layer of the banner, without opening settings. The actor reads controls inside open shadow roots and frames, and knows the selectors of 17 consent platforms plus accept and reject wording in 16 languages.
  • After reject. The actor clicks the reject control, reloads the page, and records the tracker requests and new tracking cookies that still appear.
  • Consent platform detection. IAB TCF (__tcfapi, with the CMP ID and gdprApplies from a TCF ping), OneTrust, Cookiebot, Usercentrics, Didomi, TrustArc, Quantcast Choice, Sourcepoint, iubenda, Complianz, CookieYes, Osano, Termly, Axeptio, consentmanager, Borlabs Cookie, Klaro, and Google Funding Choices.
  • Google Consent Mode. Cookieless Consent Mode pings sent with ad and analytics storage denied (gcs=G100) are counted on their own, so you can judge them apart from full tracking.
  • Global Privacy Control. A session that sends Sec-GPC: 1 and exposes navigator.globalPrivacyControl, compared with the plain session, plus a read of /.well-known/gpc.json.
  • A fixed, versioned tracker list. 173 tracker hosts and 83 tracker cookie patterns ship in the actor, and every row names the list version it was checked against, so two audits are comparable.
  • No personal data out. Cookie names and domains only, never cookie values.

Input

FieldTypeDescription
domainstringThe website to audit, for example example.de or https://www.example.de/. The homepage is audited.
domainsarrayMore domains or URLs in the same run. Duplicates are skipped. Up to 500 per run.
proxy_countryselectThe EU country the browser connects from: DE, FR, NL, IE, IT, ES, SE, PL, AT, BE, DK, FI, or none. Default DE. none connects without a proxy, which is not an EU vantage point.
check_gpcbooleanAlso run the Global Privacy Control session and read /.well-known/gpc.json. Default true.
max_charge_usdnumberStop before the audit charges would pass this amount.
skip_cachebooleanA domain audited in the last 24 hours with the same country and GPC setting comes back from cache at no charge. Turn this on to audit it again. Default false.

Output

One row per domain. Every row carries every field, with null where a value was not measured.

FieldTypeExample
domain, url_audited, final_urlstringexample.de
vantage_country, proxy_used, proxy_groupstring, boolean, stringDE, true, residential
render_statusstringrendered, blocked, timeout, unreachable, robots_disallowed
cmp_detected, cmp_vendor, cmp_vendors_allboolean, string, stringtrue, onetrust, onetrust
tcf_api_present, tcf_cmp_id, tcf_gdpr_appliesboolean, integer, booleantrue, 28, true
banner_detected, accept_on_first_layer, reject_on_first_layerbooleantrue, true, false
reject_control_textstringAlle ablehnen
cookies_before_consent, non_essential_cookies_before_consentinteger14, 6
non_essential_cookies_before_consent_jsonstring (JSON list of name, domain, vendor, category)
tracker_requests_before_consent, consent_mode_denied_pings_before_consentinteger23, 0
tracker_hosts_before_consent_json, tracker_vendors_before_consentstring`Google Analytics
reject_clickedbooleantrue
tracker_requests_after_reject, consent_mode_denied_pings_after_reject, tracker_hosts_after_reject_jsoninteger, integer, string0, 2
non_essential_cookies_after_reject, non_essential_cookies_after_reject_jsoninteger, string0
gpc_checked, gpc_tracker_requests, gpc_non_essential_cookies, gpc_reduces_trackingboolean, integer, integer, booleantrue, 20, 6, false
gpc_well_known_found, gpc_well_known_gpcbooleanfalse, null
signals, signals_countstring, integer`trackers_before_consent
tracker_list_versionstring2026-10-19.1
from_cache, duration_msboolean, integerfalse, 41000
row_status, error_reasonstringok, null
billable_events_json, checked_atstring["domain-audited"]

The signals are: trackers_before_consent, non_essential_cookies_before_consent, no_reject_on_first_layer, trackers_after_reject, non_essential_cookies_after_reject, gpc_no_change, no_consent_banner_detected, and tcf_gdpr_applies_false_from_eu.

What the signals check, and the rules behind them

  • ePrivacy Directive 2002/58/EC, Article 5(3). Storing or reading information on a visitor's device needs consent unless it is strictly necessary. The before consent fields show what a site stores and sends before any choice.
  • GDPR, Article 4(11) and Article 7. Consent must be freely given, specific, informed, and unambiguous, and as easy to withdraw as to give. The after reject fields show whether a refusal is honored.
  • EDPB Cookie Banner Taskforce report, 2023-01-18. The taskforce lists practices national regulators treat as problems, among them no reject option on the first layer and non essential cookies set before consent. reject_on_first_layer and the before consent counts map to those practices.
  • Global Privacy Control. The GPC specification (w3c.github.io/gpc) defines the Sec-GPC header and /.well-known/gpc.json. The CCPA regulations treat it as an opt out preference signal for California. The actor reports whether the site sent fewer trackers with GPC on; it does not decide whether a law requires that.

Pricing

Pay per event. You pay for each domain that was fully audited, plus one small start fee per run.

EventFree planStarter (Bronze)Scale (Silver)Business (Gold)
domain-audited, per audited domain0.05 USD (50.00 per 1,000)0.0475 USD (47.50 per 1,000)0.045 USD (45.00 per 1,000)0.0425 USD (42.50 per 1,000)
apify-actor-start, per run0.001 USD0.001 USD0.001 USD0.001 USD
  • Only rows with row_status ok are charged. Blocked, timed out, partial, unreachable, cached, and invalid input rows are free, and so are the rows of a run where no EU address was available; that run still pays the start fee.
  • Free plan cap: 30 audited domains a month on the Apify free plan (1.50 USD of evaluation). After that the run stops with a cap_reached row.
  • The run stops at the maximum charge you set for it on Apify, and at max_charge_usd when you set it.

Usage examples

Apify Console or API. One domain:

{ "domain": "example.de" }

A batch audited from France, without the GPC session:

{ "domains": ["example.fr", "example.de", "example.nl"], "proxy_country": "FR", "check_gpc": false }

A re-audit of a site you fixed today:

{ "domain": "example.de", "skip_cache": true }

Clay. Call the actor from an HTTP API column with your Apify token, one domain per row, {"domain": "{{Domain}}"}. Every input also works as a string, so "check_gpc": "false" is read the same as false. Map the flat output fields into columns.

MCP. The MCP server @mambalabsdev/mcp-cookie-consent-audit exposes the tool audit_cookie_consent to Claude, Cursor, and any MCP client.

Error handling

CaseWhat you get
The site shows a challenge page (Cloudflare, Akamai, DataDome, and similar)render_status blocked, row_status blocked, free
The page does not load within 30 secondsrender_status timeout, free
The domain does not resolve or refuses the connectionrender_status unreachable, row_status error, free
robots.txt disallows the whole site for every agentrender_status robots_disallowed, free
One of the sessions failsrow_status partial, with the measured fields filled, free
No proxy address in the chosen countryrow_status error, nothing audited, free
The whole domain passes its 150 second budgetrow_status timeout, free
Not a web domainrow_status invalid_input, free

Limitations

  • A row is one sample. Sites change their banner by device, time, and A/B test, and some show it only after a delay or a scroll.
  • Automated checks cannot prove compliance. A clean row is not a statement that a site is lawful, and a signal is not a finding that it is not.
  • Only the homepage is audited, on a desktop viewport.
  • The tracker list is fixed and versioned. A tracker it does not list is not counted; the list grows with new versions, and every row names its version.
  • Controls inside closed shadow roots, or banners drawn on a canvas, cannot be read.
  • The GPC comparison counts requests. Ad requests vary from load to load, so a small difference is weak evidence.
  • Strictly necessary cookies that the list does not recognize are counted in cookies_before_consent but not as tracking cookies.

Mamba Labs suite

Every actor in the suite takes a domain or a company and returns one flat row, so they stack in the same table.

ActorActor ID
GTM Hiring Signal ScraperD7O1SA2EqwHGsGr1P
Tech Stack Signal Detectorqyd7nNyqFPelQViBx
GTM Signals AggregatorxKdRfnfFNkdMpFuNs
Job Board Keyword Signal Scanner4DvqpvhMR74NLcDDY
Domain to LinkedIn URL Resolver3HtnSaqPHOg1Qg5gx
ICP Fit ScorerW161DT8W4kW55dMFh
Domain Deliverability Checker0tVgxI7A6o9jMlxmc
Company Firmographic EnricherYlUtLWjfPpqykmB8g
Company Social Presence Mapper4k6CCemkgBDz18m2h
Company Identity Resolverlr8fTRAmZCBZmuwwh
Company Change Event FeedoX44rS0fkEJ3rXLWe
Funding and Press Signal ScannerFS13X6dhQVgX3XOM6
Job Posting MonitorQCfICD9kOPiOdj5iI
Agent Accessibility AuditoranxbRv0lKrpQ1pnua
AI Tooling DetectorEwkHhmqiuJgRoVEbE
Prospect Engineq9rT6v64nUJdPexOQ
Publishing Frequency TrackerTbLwaUUATdYb6wp4N
Sequencer Lead Push0Jv27VeWM5tSZQs9x
Company Discovery List Builderjch0HdaZnpbMqlcGS
Contact Classifier0lGSeYJmniXhGANnO
Work Email WaterfallOT6xqTFThC0Rjf7Zj
Event Presence IndexWLhMy8fMDgsxdYxv5
Legal Entity ResolverKHFyPCDIx7CyqULYm
LinkedIn Post TrackeroiGLNPuaf5BRaz9K5
Outbound Stack Detectorv43UJC8r7qW7cBSTG
People Finder & Email VerifierLEgloG7tWgQl4o6TD
Government Contract Award MonitorzhEtllASykOcx9hJ8
Team Page People Extractorj8a9zX0k4mNbvDbWK
Workplace Program DetectorLi6pPDhqbdzFz3h7G
Page Finder and ExtractorTpurgcOZbVnknlaiC
Reporting Window FinderuINxR7a1IW8qUTRUX
Bluesky Brand Presence MappereLpxzP4IuXznlFVND
Company Contact Details Extractor4mMncKaJykiq94grz
Ecommerce Platform Profiler5G2NeYjBbQTjaTn9L
Company Funding RecordOFS4Mt1gyYNtGfUbE
GitHub Organization Signal ScannerahF8RRpv5mzPao5CN
LinkedIn Company Page MapperzOPm6A9JEhUGcIdFW
Meta Ad Library MonitorJ1GWlSXfSGU3u8Wng
Instagram Facebook Brand Presence MapperHXh65I0JBjPsunbY8
Pinterest Brand Presence Mapperd1HvjZfKhgvWsoEwn
Reddit Brand Presence MapperpKQZmDaT70SEb54bZ
Trustpilot Reputation Enricher3lIqfCt61j4hqE1xz
TikTok Brand Presence Mapperfco8FvoJcSafbeyd1
Website Traffic Rank EstimatorGnOFUzlNVIoXgeJjH
X Brand Presence MapperoLOgadhHUkNAyDA3w
YouTube Channel Stats Extractor6hSpD3kd2s2IQ4VSs
Influencer Change Monitord2VVgahNL6UmcLkhg
Influencer FindertpkedmloIIWtXx6sg
Influencer Lead List BuilderKnmByszcv135yM30G
Influencer Profile ScraperEqEnklDVMIcB1V499
Link in Bio Scraper and Newsletter DetectorOorucdheTIgu7RFzK
Influencer Talent Agency LookupzCuX4Mgyg6JvXgGzd
Expert Witness DirectoryLIpwlgfE3LaQBaXd4
Account Hiring WatchgRAZA5WBi1r6L0gy7
Career Change Signal EnginevX2Yga1a6wGaXaP14
Job Change TrackerL8UbEmMJC1XYPSZOb
New Hire FindercKuc38p4nYHNF3IW8

Shared code: @mambalabsdev/gtm-core (output validation).

Sourcing and legal. The actor loads public web pages the way a visitor's browser does, with the page and its banner deciding requests sent through the Apify proxy. No login is used. It returns cookie names and request hosts, never cookie values or personal data. You are responsible for how you use the output.

Built by Mamba Labs.