Why I built a free website privacy check
The privacy check loads your site in a real Chromium and reports trackers, Google Fonts and cookie banner issues. Nothing to install, nothing stored.Most site owners I talk to have a cookie banner and consider the topic closed. Yet on the first visit the page often loads fonts from Google, a map or an analytics script before anyone has clicked anything. The privacy check shows exactly that, in the browser, with nothing to install.
The checks come from PrivaLint, my open-source tool for privacy checks in a real browser. PrivaLint itself has its own article. It runs as a CLI, a GitHub Action and a Node.js API. That suits developers, not the owner of a beauty studio or the managing director of a joinery. If checking your own website means installing Node.js and Chromium first, you skip it.
So I put PrivaLint behind a form: enter the address, confirm it is your own site, pick a region profile. The scan takes three minutes at most, then the report is on the page. The findings are the same the CLI produces, with evidence and a suggested fix.
The scanner opens the home page in a fresh Chromium with no cookies and no stored data. It waits for the network to settle and records every request, cookie and link. If the banner shows up late, it waits one more settle period. If it finds a cookie banner, it first presses the Tab key up to 60 times to see whether the reject button gets focus. Then it clicks “Reject”, reloads the page and records a second time, and follows up to two more pages of the same site in link order. It loads the Impressum and privacy policy the home page links once more and reads their text, plus a cookie policy linked there, also as a PDF on the same site.
28 rules of PrivaLint 0.10.0 evaluate what was recorded, summarised here:
The region profile (Germany, Austria, Switzerland, Hungary or EU) sets the legal references in each finding and, for Switzerland, the severity of some rules. For Hungary, PrivaLint also recognises Hungarian banner buttons such as “Elutasítom” and links such as “Impresszum”. The profile does not move the browser: that stays where the server is.
Without a code, the page shows the five most important entries, sorted by severity and with at least one error and one warning where there are any. The full report arrives by email: every finding as a designed mail, plus a PDF report and PrivaLint's JSON export.
- Without a code: the home page plus two pages, three in total.
- With an access code: up to ten pages and the full report right on the page. I hand out codes on request.
- More pages: for larger sites I run PrivaLint myself or set it up in your pipeline.
None. A result stays in memory for an hour at most and can only be reached through a random link. A restart of the service clears everything. There are no accounts, no database and no stored reports.
- To limit abuse, the service counts scans per visitor. It keeps only an HMAC of the IP address under a key that changes daily, never the address itself.
- The email address for the report goes to the mail server (IONOS) only and is not stored afterwards.
- If you want me to get in touch, you tick a separate box and confirm through a link in the mail (double opt-in). Only then do I learn the address.
A service that opens arbitrary addresses is a target: someone could try to reach internal systems through it. So the scanner runs in its own container without credentials. Every browser request passes a network adapter that resolves the address and refuses internal ranges. A firewall lets only DNS, HTTP and HTTPS leave the container, plus mail delivery.
The browser sends read-only requests (GET and HEAD). It deliberately does not send beacons, the pings that carry usage data. Their addresses still end up in the report, because a tracker beacon is a finding in itself.
The first full 50-page scan of jexcellence.de showed yellow on every rule of the home page: “not all content loaded”. One request caused it. Next.js prefetches linked pages in the background and cancels those prefetches when the network is slow. PrivaLint took the cancelled request for a loading failure and marked the whole home page incomplete.
Since PrivaLint 0.6.1 the tool notices when the page cancels a request itself and lists it in the loading details as “cancelled by the page”. Real failures such as timeouts or DNS errors still limit the result. Without the web scanner running under real load I would not have caught it.
- “Reject” on the home page is tested. PrivaLint can also switch everything off in the banner settings with --check-settings, but the web scanner does not run that check, because the second browser run does not fit the time limit. Whether the choice is stored permanently is not checked either.
- Only the CLI checks HTTPS and HSTS. The web scanner makes no request of its own to http://.
- Pages behind a login are out of scope. Forms are only checked for a privacy link next to them; nothing is submitted.
- Some sites hide their banner from automated browsers. The report then shows no banner although visitors see one.
- PrivaLint recognises trackers from a maintained vendor list and, for cookies, about 1,000 entries from the Open Cookie Database. New or very small vendors can still be missing.
Two ways. Set PrivaLint up yourself: it is MIT-licensed, and the commands are below the report and in the repository. Or hand the findings to me. I self-host fonts, load maps and videos only after consent, set up the banner with Reject on the first layer and send a re-test afterwards. I quote a price once I have seen the report.
Check your website now or talk the findings through with me. If you hit a false positive, please open an issue on GitHub. privalint gets better with every such report.