Reference

This page lists what PXTA looks for, how it rates what it finds, and every option. The same reference is in the README on GitHub.

The Three Passes

When a site shows a consent banner, PXTA loads every page three times, with a fresh browser profile for each pass:

Pass What PXTA does first A tracker sending data here means
Banner not answered Nothing: the banner is left alone it fired before consent
After reject Rejects on the start page it ignored the visitor’s “no”
After accept Accepts on the start page this is what the site sends with consent

With no banner, each page is loaded once, and the report says the site never asked.

On each page PXTA waits until two seconds pass without a new request (at most 15 seconds), scrolls to the bottom, types the marker address pxta-probe@example.com into email fields without submitting, then fires the events a page gets when the visitor leaves and records the beacons they set off. Requests from iframes and workers are included.

Platform How PXTA finds it How PXTA answers
OneTrust OneTrust object, #onetrust-banner-sdk the Reject All or Accept All button, else RejectAll() / AllowAll()
Cookiebot Cookiebot object, #CybotCookiebotDialog the Deny or Allow all button, else submitCustomConsent()
Didomi Didomi object, #didomi-host the Disagree or Agree button, else setUserDisagreeToAll() / setUserAgreeToAll()
Usercentrics UC_UI object, #usercentrics-root the Deny or Accept All button, else denyAllConsents() / acceptAllConsents()
Any other buttons that say “Reject all”, “Decline”, “Only necessary”, “Alle ablehnen”, “Tout refuser” and similar, next to text about cookies or consent a click on that button

Banners are found in the page, in open shadow roots and inside iframes, and PXTA waits up to six seconds for one to appear. A banner inside a closed shadow root is found by what it covers on screen and answered through its platform’s API. After answering, PXTA checks the banner went away. If it can’t reject or accept, the report says so and that pass is left out.

Trackers

Tracker Collection endpoint
Meta Pixel facebook.com/tr
Google Analytics 4 google-analytics.com/g/collect, analytics.google.com/g/collect
Google Ads conversion tag googleads.g.doubleclick.net/pagead/viewthroughconversion/, googleadservices.com/pagead/conversion/, www.google.com/pagead/1p-conversion/
Google Tag Manager www.googletagmanager.com/gtm.js (a loader, listed when present)
TikTok Pixel analytics.tiktok.com/api/v2/pixel
LinkedIn Insight Tag px.ads.linkedin.com/collect, /wa/
Microsoft Advertising UET bat.bing.com/action/
Pinterest Tag ct.pinterest.com/v3/, /user/
Snap Pixel tr.snapchat.com/p
X (Twitter) Pixel analytics.twitter.com/i/adsct, t.co/i/adsct

A third-party request that isn’t in the catalog still appears, as “unclassified”, when it looks like a beacon or carries personal data. Each catalog entry is a small JSON file in catalog/; --catalog folder adds your own.

What Gets Decoded

Every request is unpacked before the rules run: query strings, form bodies, JSON bodies, several events in one body, a URL inside a parameter (and that URL’s own parameters), JSON inside a parameter, base64 text, and up to three rounds of percent-encoding.

The Rules

Rule Finds
Email addresses plain, URL-encoded, double-encoded, base64, inside JSON, inside the page address
Email hashes SHA-256 and MD5 of addresses PXTA knows: those you pass with --email, its marker address, and addresses shown on the site or seen in other requests
Hashed customer fields fields the tag labels as a hashed email, phone or name, such as Meta’s advanced matching or Google’s enhanced conversions
Phone numbers and names in fields named for them
User IDs the site’s own user ID, such as Google Analytics uid
Search terms what the visitor searched for on the site, found anywhere in a tracker request
Sensitive pages the address or title of a page about health, money trouble, or a checkout or account
Consent Mode Google’s gcs value: granted before an answer or after a reject, or denied while personal data still goes out

Findings and Severity

The codes are stable: a code is never renamed, so scripts can rely on them.

Code Severity Meaning
personal-data high, low after accept a tracker request carried personal data
sensitive-page high, low after accept a tracker got the address or title of a sensitive page
search-term high, low after accept a tracker got what the visitor searched for
consent-mode-granted high after reject, medium before an answer Google tags reported consent as granted
consent-mode-mismatch high, low after accept Consent Mode said denied, and personal data went out anyway
tracker-after-reject medium a tracker sent data after the visitor rejected
tracker-before-consent medium a tracker sent data before the banner was answered, or on a site with no banner
banner-not-handled for information PXTA couldn’t answer the banner, so a pass is missing
tracker-present for information a tracker sent data from these pages

The severities are fixed and written down so they can be argued with. They aren’t a legal judgment: PXTA records traffic, and whether that traffic breaks a law is for a lawyer to say.

Options

Option Default What it does
--out pxta-report folder for report.html, findings.json and requests.har
--pages 20 most pages to visit
--depth 3 links deep from the start page
--sitemap sitemap address to add pages from
--passes none,reject,accept which consent passes to report; the unanswered pass always runs, since it finds the pages
--email an address whose hashes to look for (repeatable)
--no-fill off don’t type the marker address into email fields
--wait 15s longest time on one page
--idle 2s a page is done after this long without a new request
--banner-wait 6s how long to look for a consent banner
--delay 1s pause between page loads
--ignore-robots off visit pages robots.txt disallows, on your own site only
--resume off carry on an interrupted audit from --out
--browser found automatically Chrome, Chromium or Edge to use (or PXTA_BROWSER)
--catalog folder of extra tracker catalog files
--quiet off print only the summary

pxta audit exits with 0 when the audit finished, whatever it found, 2 on an error, and 130 when it was interrupted. PXTA saves its progress after every page, so --resume picks up where an interrupted audit stopped, and it restarts the browser by itself if it crashes mid-crawl.

What PXTA Can’t See

  • Data a site sends from its own servers, such as conversion APIs and server-side tag managers.
  • Pages behind a login, and anything that happens only after a click PXTA doesn’t make.
  • Trackers it doesn’t know, apart from the unclassified-beacon rule.