Free: what loads before consent
One tool needs no account, no API key and no sign-in: give it a public URL and it reports which trackers and cookies load before the visitor answers the cookie banner, which ones correctly wait, which other sites the page contacts (Google Fonts, CDNs…) and what to change. It's the same check over REST and over MCP (pre_consent_scan), limited to 10 checks per hour per visitor.
curl "https://privacy-pill-consent-studio.lovable.app/api/public/v1/pre-consent-scan?url=https://example.com"curl -X POST https://privacy-pill-consent-studio.lovable.app/api/public/v1/pre-consent-scan \
-H "Content-Type: application/json" \
-d '{ "url": "https://example.com/pricing" }'{
"name": "pre_consent_scan",
"arguments": { "url": "https://example.com" }
}{
"final_url": "https://shop.example/",
"verdict": "fail",
"summary": "2 trackers and 3 cookies that need consent load on shop.example before the visitor chooses: Google Analytics 4 and Meta Pixel. No consent banner was found in the page's HTML.",
"counts": { "trackers_before_consent": 2, "cookies_before_consent": 3, "waiting_for_consent": 0, "unclear": 0, "unidentified_cookies": 0, "third_party_hosts": 2 },
"consent_banner": { "detected": false, "tools": [], "auto_blocking": [] },
"consent_mode": { "default_denied_found": false, "set_before_google_tags": false, "v2": false },
"trackers": [
{
"id": "meta-pixel",
"name": "Meta Pixel",
"category": "marketing",
"needs_consent": true,
"status": "loads_before_consent",
"reason": "Runs on page load: nothing in front of it holds it back until consent.",
"cookies": ["_fbp"]
}
],
"cookies": [
{ "name": "_fbp", "category": "marketing", "observed": false, "set_by": "Meta Pixel", "needs_consent": true }
],
"third_party": [
{ "host": "connect.facebook.net", "kinds": ["script"], "service": "Meta Pixel", "needs_attention": true },
{ "host": "www.googletagmanager.com", "kinds": ["script"], "service": "Google Analytics 4", "needs_attention": true }
],
"fixes": [
"Add a consent banner that blocks trackers until visitors choose. …",
"Load Meta Pixel only after consent: change its tag to <script type=\"text/plain\" data-pp-category=\"marketing\"> …"
]
}verdict is fail when something that needs consent loads (or a cookie is set) before the visitor chooses, warning when some trackers or cookies can't be confirmed, and pass otherwise. Each tracker has a status:
| loads_before_consent | Runs on page load with nothing holding it back — a problem under GDPR / ePrivacy. |
| restricted_by_consent_mode | A Google tag that loads after a Consent Mode default of 'denied': no cookies until consent. |
| blocked_until_consent | Inert in the HTML (for example type="text/plain") until a consent tool turns it on. |
| may_be_gated_by_cmp | A consent tool that can block or restrict it loads first — confirm in a browser. |
| via_tag_manager | Fired from Google Tag Manager, so it depends on the container's consent settings. |
| unclear | Mentioned in the page but not as a tag we could see load (often added later by JavaScript). |
| no_consent_needed | Strictly necessary or cookieless. |
How it works: we fetch the page once as a first-time visitor and read its HTML, response headers and Google Tag Manager containers. No JavaScript runs, so trackers that other scripts add later may not show up — the report lists its limits. Over the limit you get HTTP 429 with a Retry-After header (MCP: a tool error with the same message). For a full graded report in the browser, use the tracker scanner.
MCP for AI agents
PrivacyPill runs a remote Model Context Protocol server. Connecting needs no account: pre_consent_scan works right away. The first time the assistant uses an account tool, your client asks you to sign in to PrivacyPill and approve access. The assistant then acts as you: it sees only your sites and is bound by your plan's limits. It can't buy plans, see payment details or delete sites.
https://privacy-pill-consent-studio.lovable.app/mcpclaude mcp add --transport http privacypill https://privacy-pill-consent-studio.lovable.app/mcpRun once. The free check works straight away; account tools ask you to sign in on first use (or type /mcp to manage the connection).
Try asking your agent
- “Add a PrivacyPill cookie banner to this site in German and English.”
- “Scan example.com, apply what you find and give me the embed for Webflow.”
- “Make my banner a bottom bar with our brand teal and rounded buttons.”
MCP tools
| Tool | What it does |
|---|---|
| pre_consent_scanFree · no sign-in | Which cookies and trackers load on any public page before the visitor consents, and how to fix it. |
| get_account | Your plan, licenses, site count and limits. |
| list_sites | Every site on your account with its domain, plan and site key. |
| get_site | One site's banner settings, install status and latest scan. |
| create_site | Create a site for a domain, optionally with banner settings. |
| configure_banner | Change layout, colours, languages, categories or texts. |
| get_embed_snippet | The one-line embed plus install steps for HTML, GTM, WordPress, Shopify and Webflow. |
| run_compliance_scan | Scan the live site for trackers and optionally apply results. |
| list_banner_presets | Built-in colour presets and allowed values. |
REST quick start
- Create a key under Dashboard → Developers and store it as
PRIVACYPILL_KEY. - Create a site with its banner settings.
- Fetch the embed snippet and paste it first in your site's <head>.
curl -X POST https://privacy-pill-consent-studio.lovable.app/api/public/v1/sites \
-H "Authorization: Bearer $PRIVACYPILL_KEY" \
-H "Content-Type: application/json" \
-d '{
"domain": "example.com",
"name": "Example shop",
"design": {
"preset": "mint",
"layout": "pill",
"languages": ["en", "de", "nl"],
"categories": { "marketing": true, "functional": false }
}
}'curl https://privacy-pill-consent-studio.lovable.app/api/public/v1/sites/$SITE_ID/embed \
-H "Authorization: Bearer $PRIVACYPILL_KEY"const res = await fetch("https://privacy-pill-consent-studio.lovable.app/api/public/v1/sites", {
headers: { Authorization: `Bearer ${process.env.PRIVACYPILL_KEY}` },
});
const { sites } = await res.json();Authentication
Send your key as Authorization: Bearer ppk_… (or an X-API-Key header). Keys act as your account and are shown once — we only store a hash. You can have up to 10 active keys and revoke them any time. Never put a key in browser code; the embed script doesn't need one.
Base URL: https://privacy-pill-consent-studio.lovable.app/api/public/v1
Endpoints
- GET
/pre-consent-scan?url=…Free: which cookies and trackers load before consent · no key needed - POST
/pre-consent-scanSame check with a JSON body { url } · no key needed - GET
/accountYour account, licenses and limits - GET
/sitesList your sites - POST
/sitesCreate a site, optionally with banner settings - GET
/sites/{siteId}Get a site and its banner settings - PATCH
/sites/{siteId}Update the banner, domain, geo-targeting or license - DELETE
/sites/{siteId}Delete a site - GET
/sites/{siteId}/embedEmbed snippet + per-platform install steps - GET
/sites/{siteId}/scansRecent compliance scans of a site - POST
/sites/{siteId}/scansScan the site now (optionally apply results to the banner) - POST
/scansScan any public URL for trackers and cookies - GET
/presetsBanner colour presets and allowed values · no key needed
Configuring the banner
The design object is a partial patch: send only what you want to change and nested objects (theme, categories, Consent Mode, text overrides) merge into the current settings. Strictly necessary cookies are always on. Use GET /presets to list colour presets and allowed values.
curl -X PATCH https://privacy-pill-consent-studio.lovable.app/api/public/v1/sites/$SITE_ID \
-H "Authorization: Bearer $PRIVACYPILL_KEY" \
-H "Content-Type: application/json" \
-d '{ "design": { "layout": "bar", "theme": { "accent": "#0f766e", "radius": 14 } } }'Compliance scans
Scans fetch the public page, detect common trackers (GA4, Google Ads, Meta Pixel, Hotjar, TikTok, LinkedIn and more) and check whether the PrivacyPill script loads first. Pass "apply": true to switch on the matching cookie categories automatically.
curl -X POST https://privacy-pill-consent-studio.lovable.app/api/public/v1/sites/$SITE_ID/scans \
-H "Authorization: Bearer $PRIVACYPILL_KEY" \
-H "Content-Type: application/json" \
-d '{ "apply": true }'Errors & limits
Errors use normal HTTP status codes (400 invalid input, 401 bad key, 402 plan limit, 404, 409 duplicate domain, 422 page couldn't be fetched, 429 rate limit, 503 briefly unavailable) with a JSON body. Each key can make 1,200 requests an hour; each account can run 30 API scans an hour. The free pre-consent check allows 10 checks per hour per visitor, without a key. Plan limits — like one site on the free plan — apply exactly as in the dashboard.
{
"error": {
"code": "invalid_request",
"message": "Some fields are missing or invalid.",
"details": [{ "path": "design.theme.accent", "message": "Invalid string: must match pattern" }]
}
}OpenAPI, llms.txt & discovery
Agents can find everything from the domain alone: the API catalog (RFC 9727) links to the OpenAPI spec, these docs and the MCP server card, and the MCP server card is also listed in the AI catalog.
| Document | URL |
|---|---|
| API catalog (RFC 9727 linkset) | /.well-known/api-catalog |
| OpenAPI 3.1 spec | /api/public/v1/openapi.json |
| MCP server card | /mcp/server-card |
| MCP server card (well-known alias) | /.well-known/mcp/server-card.json |
| AI catalog | /.well-known/ai-catalog.json |
| OAuth protected resource metadata | /.well-known/oauth-protected-resource |
| llms.txt | /llms.txt |