Einen Shop prüfen, bevor du ihn automatisierst
Session öffnen, Consent-Bericht auf einem deutschen Shop laufen lassen, lesen was vor jeder Wahl gesetzt war, Ziele der Formulare kartieren, Screenshot sichern.
Zuletzt aktualisiert:
Wann ein Bericht besser passt als eine Agentenaufgabe
Du könntest einen Agenten bitten, einen Shop zu besuchen und dir zu erzählen, was sein Cookie-Banner treibt. Das ginge, kostete Tokens, dauerte eine Minute und lieferte jedes Mal eine leicht andere Antwort — weil ein Modell die Antwort geschrieben hat. Ein Bericht ist die andere Bauform: ein POST, gerechnet aus derselben Wahrnehmung, auf der der Agent arbeitet, ohne jedes Modell im Aufruf. Er ist deterministisch, er ist billig, und wenn du ihn nächsten Monat noch einmal laufen lässt, bekommst du ein Dokument, das sich gegen das von heute diffen lässt.
Greif zum Bericht, wenn die Frage strukturell ist: Was setzt diese Seite, bevor jemand wählt, wohin schicken ihre Formulare, ist eine Kündigung von hier aus erreichbar, wie sieht sie gerade aus. Greif zu einer Agentenaufgabe, wenn die Frage Urteilskraft oder mehrere Schritte braucht — anmelden, die Rechnung vom letzten Quartal finden, sie herunterladen. Beide teilen sich eine Session, du kannst also beides in einem Browser tun, ohne zwei zu bezahlen.
Diese Anleitung lässt drei der fünf Berichte der Reihe nach gegen einen deutschen Shop laufen. Alles hier braucht einen API-Schlüssel und ein Deployment, das reports in GET /v1/me führt; die Feldreferenz zu jedem Parameter steht auf der Berichtsseite.
Schritt 1: eine Session, dann der Consent-Bericht
Sessions starten standardmäßig als de-DE-Browser in Europe/Berlin, also so, wie ein deutscher Shop es erwartet. Drei Minuten reichen für eine Handvoll Berichte.
Voraussetzungen: api-key
import { Browserberg } from '@browserberg/sdk';
const bb = new Browserberg({
apiKey: process.env.BROWSERBERG_API_KEY!,
baseUrl: 'https://browserberg.com',
});
// A short session is enough: a report is one call, not a conversation.
await using session = await bb.sessions.create({ ttlSeconds: 180 });
const consent = await session.consentReport({
url: 'https://shop.example.com/',
policy: 'reject',
waitMs: 5000,
});
console.log('platform:', consent.cmp, 'seen after', consent.bannerDetectedAtMs, 'ms');
console.log('cookies before any choice:', consent.summary.cookiesBeforeChoice);
console.log('third-party hosts before any choice:', consent.summary.thirdPartyHostsBeforeChoice);
console.log('new cookies after the reject:', consent.summary.newCookiesAfterReject);
for (const cookie of consent.cookies.beforeChoice) {
if (cookie.thirdParty) console.log(' third party:', cookie.name, cookie.domain);
}
import os
from browserberg import Browserberg
bb = Browserberg(os.environ["BROWSERBERG_API_KEY"], base_url="https://browserberg.com")
with bb.sessions.create(ttl_seconds=180) as session:
consent = session.consent_report(
"https://shop.example.com/", policy="reject", wait_ms=5000
)
print("platform:", consent.cmp, "seen after", consent.banner_detected_at_ms, "ms")
print("cookies before any choice:", consent.summary["cookiesBeforeChoice"])
print("third-party hosts:", consent.summary["thirdPartyHostsBeforeChoice"])
for cookie in consent.cookies_before_choice:
if cookie["thirdParty"]:
print(" third party:", cookie["name"], cookie["domain"])
Das Consent-Ergebnis lesen
cmp benennt die Plattform, die geantwortet hat — usercentrics, cookiebot, consentmanager und borlabs gehören zu den namentlich erkannten —, oder heuristic, wenn ein unbekanntes Banner allein über seine Beschriftungen erkannt wurde, oder null, wenn die Seite keines zeigte. bannerDetectedAtMs erklärt, wozu waitMs da ist: Mehrere Plattformen zeichnen ihre Wand ein bis zwei Sekunden nach der Seite, und ein Bericht, der nur einmal hinsieht, erklärte eine Site für bannerfrei, auf der jeder Besucher vor einer Wand steht.
Die beiden wichtigen Hälften sind cookies.beforeChoice und requests.beforeChoice. Sie entstehen, bevor irgendetwas geklickt wird, und der Sammler für Anfragen hängt schon vor der Navigation, deshalb sind die Dritten mitgezählt, die eine Seite beim Laden anspricht. summary.thirdPartyHostsBeforeChoice ist die eine Zahl, auf die die meisten aus sind. Danach zählt summary.newCookiesAfterReject, was nach dem Ablehnen auftauchte und vorher fehlte — eine kleine Zahl ist unauffällig, eine große ein Befund, den man von Hand ansehen sollte.
Unter policy: 'detect-only' wird nichts auf der Seite angefasst, und jede Nach-der-Wahl-Hälfte kommt als null zurück. Nimm das, wenn du wissen willst, was erscheint, ohne den Zustand des Browsers zu verändern.
Schritt 2: wohin die Elemente führen, dann ein Bild
Der Ziel-Bericht löst jedes Bedienelement in der Seite auf, statt aus dem Markup zu raten, und schickt jedes einzeln durch den Ziel-Wächter.
Voraussetzungen: api-key
import { writeFile } from 'node:fs/promises';
import { Browserberg } from '@browserberg/sdk';
const bb = new Browserberg({
apiKey: process.env.BROWSERBERG_API_KEY!,
baseUrl: 'https://browserberg.com',
});
await using session = await bb.sessions.create({ ttlSeconds: 180 });
// Where does every control on this page actually lead?
const map = await session.destinationReport({
url: 'https://shop.example.com/',
limit: 200,
});
console.log('page site:', map.anchorSite, '| served over https:', map.secure);
console.log('off-site form posts:', map.summary.offSiteSubmit);
console.log('insecure submits:', map.summary.insecureSubmit);
for (const control of map.controls) {
if (control.risk) {
console.log(control.risk, '|', control.name, '->', control.destination.url);
}
}
// A picture to file beside the numbers. The banner is already gone.
const shot = await session.screenshot({ fullPage: true });
await writeFile('shop.jpg', Buffer.from(shot.base64, 'base64'));
import os
from browserberg import Browserberg
bb = Browserberg(os.environ["BROWSERBERG_API_KEY"], base_url="https://browserberg.com")
with bb.sessions.create(ttl_seconds=180) as session:
page_map = session.destination_report("https://shop.example.com/", limit=200)
print("page site:", page_map.anchor_site, "| served over https:", page_map.secure)
print("off-site form posts:", page_map.summary["offSiteSubmit"])
print("insecure submits:", page_map.summary["insecureSubmit"])
for control in page_map.controls:
if control["risk"]:
print(control["risk"], "|", control["name"], "->", control["destination"]["url"])
shot = session.screenshot(full_page=True)
with open("shop.jpg", "wb") as handle:
handle.write(shot.bytes)
Was die Zahlen heißen, und was nicht
Ein Element mit risk: 'off_site_submit' ist ein Formular dieses Shops, das an eine andere registrierbare Site schicken würde — meist ein Newsletter-Feld, das direkt an eine Marketing-Plattform verdrahtet ist. insecure_submit ist eine https-Seite, die über http abschickt. Beides verweigert der Ziel-Wächter schon unter seiner Standard-Policy, also genau so, wie es käme, wenn ein Agent dieses Element benutzen wollte. Der Bericht ist damit zugleich eine Vorschau darauf, was deine Automatisierung darf und was nicht. off_site_navigation wird standardmäßig nicht blockiert: Die Site zu verlassen ist normal, und eine SSO-Weiterleitung tut es mit Absicht.
Der Screenshot ist der billigste der fünf und als Beleg neben den Zahlen nützlich: Er entsteht, nachdem das Banner geräumt ist, das Bild zeigt also die Seite, die eine Besucherin als zweites sieht, nicht die Wand davor. fullPage nimmt das ganze Dokument auf, gekappt bei 16384 CSS-Pixeln.
Vier der fünf Berichte sind auch MCP-Tools — browser_consent_report, browser_destination_report, browser_cancellation_report und browser_screenshot —, ein Modell in einem MCP-Client kann also danach greifen, ohne dass du irgendetwas davon schreibst. Die Agentensicht ist bewusst kein Tool: Ein Modell hat bereits observe, und eine zweite Darstellung desselben Baums kostete nur Kontext. Alle fünf brauchen Protokoll 1.5, und auf einem Deployment ohne sie sind die Routen gar nicht registriert — ein Aufruf antwortet also not_found, statt auf halbem Weg zu scheitern.
Hinweis · Diese Berichte benoten niemanden
Ein Consent-Bericht ist eine Liste dessen, was der Browser hielt und wen die Seite angesprochen hat. Ein Kündigungs-Bericht ist die Feststellung, dass ein Element mit einer bestimmten Beschriftung gefunden wurde oder eben nicht, wohin es führte und was die Seite dahinter verlangte. Keiner von beiden sagt, ob eine Site rechtmäßig handelt, und nichts auf der Leitung trägt ein Urteil. Wenn du einen Befund veröffentlichst, veröffentliche die Beobachtung und überlass den Schluss der Leserin.