Install
openclaw skills install @2g4y1/compliancescanScans any website for GDPR/DSGVO compliance from the terminal — no API key or signup needed — and reports a 0-100 score plus key findings (trackers, cookies, consent banner, pre-consent tracking, fonts, third-party transfers). Use when the user wants to (1) scan a site for GDPR/DSGVO or cookie compliance, (2) check trackers, cookies, or a consent banner, (3) detect pre-consent tracking or external fonts; or says "scan my site", "DSGVO-Check", or "Datenschutz prüfen".
openclaw skills install @2g4y1/compliancescanScan any website for GDPR/DSGVO compliance straight from your agent — no API key, no
account, no signup. The skill calls the public Quick-Scan endpoint at
https://compliancescan.eu, which loads the page in a real headless browser and reports a
0–100 compliance score plus the findings that matter (trackers, cookies, consent banner,
pre-consent tracking, external fonts, third-party transfers, mail/TLS). Report only what the
API returns — never invent a score or a finding. The result is an automated technical
indication, not legal advice.
This skill is model-invocable: it must reason over the input, build the request safely, parse
JSON, and format the result. Do NOT convert it to command-dispatch: tool.
Reply in the language of the user's request — a German request → German, English → English,
French → French, and so on. This skill's instructions are English and the API returns some
German strings (e.g. upgradeMessage); convey their meaning in the user's language instead of
pasting them verbatim. The output labels shown below are illustrative — localise them. The
country parameter (de / at / ch / eu) selects the legal jurisdiction for issue wording,
NOT the reply language.
Validate url: an http(s) URL or a bare domain only. Reject shell metacharacters.
Build the body with jq -n so the URL is a safe JSON value (never interpolate untrusted
input into the shell). country is optional — one of de | at | ch | eu (the legal
jurisdiction for issue wording; default eu). The scan runs synchronously (~10–40 s), so use
a long read timeout:
BODY=$(jq -nc --arg u "$URL" '{url:$u}') # or: '{url:$u, country:"de"}'
RESP=$(curl -sS --max-time 120 -w '\n%{http_code}' \
-X POST https://compliancescan.eu/api/scanner/quick \
-H "Content-Type: application/json" \
-d "$BODY")
Split status from body deterministically (the status is the last line):
STATUS=$(printf '%s' "$RESP" | tail -n1)
JSON=$(printf '%s' "$RESP" | sed '$d') # body = everything except the last line
Parse $JSON only with jq. If $STATUS is not 200, go to Failure handling; if $JSON
is empty or not valid JSON, treat it as the Non-JSON body case.
On 200, report $JSON per Output format.
Cache check: the endpoint caches a successful anonymous scan per domain for ~15 minutes. If
$JSON has "cached": true, it is a stored result, not a fresh scan — add the cache note from
Output format (.cachedAgeSeconds). Do NOT re-scan to "refresh" it; a repeat call returns
the same cached payload until the window expires.
The field contract is the Output format section below — read those fields from .score,
.summary.*, .issuesSummary.*, .securityHeaders.*, .externalFonts, .thirdPartyDomains,
.serverLocation, and the cache markers .cached / .cachedAgeSeconds. The Quick-Scan returns
issue counts (issuesSummary), not the per-issue list. For the full issue list with legal
references and recommendations, use a full scan (see Advanced) or the web report at
https://compliancescan.eu.
Return concise markdown; include a line only when the field is present:
score is a number, <score> / 100 for <finalUrl>
(<pagesScanned> page(s)); if score is null, say it is not assessable (no score) — in
the user's language — and never substitute 0summary.hasPrivacyPage), imprint ✓/✗
(summary.hasImprint, with summary.imprintSource if present), cookie banner ✓/✗
(summary.hasCookieBanner)<summary.trackers>, third parties <summary.thirdPartyRequests>,
cookies <summary.cookies>issuesSummary.critical critical / issuesSummary.warning warnings /
issuesSummary.info infosummary.usTrackersCount), external fonts
(externalFonts.count + hasHighRisk), TLS (summary.hasSSL), security headers
(securityHeaders.hstsGrade / cspGrade), server location (serverLocation.country,
serverLocation.isGdprAdequate)scanScope =
"quick"; homepage + a few subpages, <pagesScanned> pages) and that a Full-Scan — the
whole site, full tracker/cookie lists, reject-path testing, DNS/mail security and concrete
recommendations — is far more meaningful. Phrase it in the user's language.cached is true: add a note that this is a cached result, ~round(cachedAgeSeconds/60)
minute(s) old (repeat scans of the same domain are served from a ~15-minute cache). A fresh
re-scan is available after that window; or log in / use https://compliancescan.eu for an
immediate fresh scan. Omit this note when cached is absent or false.Anonymous Quick-Scans are limited to 5 per day per IP, plus a global fair-use budget. On
429 (RATE_LIMITED or GLOBAL_RATE_LIMITED) respect the Retry-After response header
(seconds; capture headers with curl -D - or -i if you need its value) and tell the user to try
again later or register for free at https://compliancescan.eu for unlimited Quick-Scans. Do not
retry automatically.
400
(URL_REQUIRED / INVALID_URL / INVALID_PROTOCOL) AFTER a deterministic input correction
(e.g. stripped a stray space, added a scheme). Never retry 403 / 429 / 5xx, and never
re-POST on a --max-time timeout (the scan may have run) — tell the user and stop.null, say so.jq -n as a JSON value — never interpolate unsanitized input into the shell.The machine-readable code is in .code; the human message is in .error. Read .code with
jq, then:
URL_REQUIRED / INVALID_URL / INVALID_PROTOCOL — if there is a clear, deterministic
input fix (valid http(s) URL or bare domain), apply it and retry the POST at most once. If
the input is already well-formed, do NOT retry — report the error and stop.PRIVATE_IP_SCAN_DISALLOWED — the target resolves to a private/internal address. Use
a public URL. Stop.RATE_LIMITED / GLOBAL_RATE_LIMITED — respect Retry-After; suggest registering
for unlimited Quick-Scans. Stop.SCAN_FAILED / INTERNAL_ERROR — the page may be unreachable or the scan errored.
Show the code/message and stop.--max-time hit) — the scan may still be running; tell the user and stop.externalFonts and pre-consent-relevant counts.If — and only if — COMPLIANCESCAN_API_KEY (a csk_live_… key) is configured in the
environment, this skill can also drive the authenticated REST API at
https://compliancescan.eu/api/v1 for full multi-page scans and account data. Full scans
require a Business or Enterprise plan; the Quick-Scan above needs none of this.
Authorization header. Every call sends
-H "Authorization: Bearer $COMPLIANCESCAN_API_KEY" (or -H "X-API-Key: …")..code; the auth/rate-limit middleware (401
UNAUTHORIZED / INVALID_API_KEY, 403 PLAN_REQUIRED / INSUFFICIENT_SCOPE, 429
RATE_LIMIT_EXCEEDED / DAILY_LIMIT_EXCEEDED) instead puts the code in .error and omits
.code — so read .code // .error.| Task | Call |
|---|---|
Full scan (1 credit, synchronous, needs scan:write + Business/Enterprise) | POST /api/v1/scans body {"url":"…","type":"full"} (optional maxPages, silently capped to the plan limit). 200 → {status:"completed", scan:{ gdpr_score, pages_scanned, trackers, third_parties, cookies, issues[], … }}. On 402 CREDITS_REQUIRED show buy_credits_url + upgrade_url; on 403 PLAN_REQUIRED show upgrade_url; on 403 EMAIL_NOT_VERIFIED ask the user to verify their account email. |
| Account & credits | GET /api/v1/account → plan, credits.remaining, scans.running/pending, api_usage. |
| Other (read-only) | GET /api/v1/scans (list), …/scans/latest, …/scans/status, …/scans/<id>; and POST /api/v1/scans/<id>/report (flag a wrong result). See the API docs at https://compliancescan.eu for shapes. |
Full-scan guardrails: one scan per invocation; each consumes 1 credit (or one of the plan's
monthly full scans — a failed scan is auto-refunded); never auto-retry a write on a 4xx; a
--max-time timeout is not a clean error (check GET /api/v1/scans/status instead of re-POSTing).
To get a key: register at https://compliancescan.eu → Settings → API Keys (Business/Enterprise).