scripts/tcf_external_checks.sh. @iabtcf/core has 91 published versions ending at 1.5.6; @iabtechlabtcf/core has 16, from 1.5.7 to 1.5.21. Neither dist-tags.latest is marked deprecated.A European site with a banner usually writes down what it thinks you agreed to, in a format that a machine can read: a TC string under IAB Europe's Transparency and Consent Framework, and often a second, much less studied Additional Consent (AC) string invented by Google for the vendors the TCF does not cover. Both are visible to a crawler. Decoding them turns “did the site respect my choice?” from a question about pixels and cookies into a question about two byte arrays. That is why the slice of the compliance literature that audits recording rather than behaviour is almost entirely TCF work — though, as this page's own corpus section shows, that slice is very small.
This page is about those strings as measurement artefacts: where they are, how to decode one so that the decode is still reproducible next year, and — the part that gets papers rejected — what a decoded string does and does not license you to claim. Whether your crawler should click Accept or Reject at all, how to find the banner, and what the wider consent-signal landscape looks like are on Granting Consent to Websites; this page starts after the choice is made.
Three things to fix before you write a sentence about a TC string.
__tcfapi after the user revoked, and on 101 (74.2%) at least one third party was told about the acceptance and never told about the revocation.npm install @iabtcf/core still succeeds, still carries no deprecation notice, and installs 1.5.6 from 2023-04-04. The maintained package is @iabtechlabtcf/core, currently 1.5.21 (2026-02-10), from the same repository.1) They decode differently — see below. Name the package and the version in your paper.__cmp() API, shared consensu.org cookie and five-purpose model have all been retired. The method survived; the mechanics did not.SharedPreferences under IABTCF_* keys rather than in a cookie. The first study to decode what a mobile CMP stores — [5Koch, Simon; Altpeter, Benjamin; Johns, Martin (2023): "The OK Is Not Enough: A Large Scale Study of Consent Dialogs in Smartphone Applications", in: Proceedings of the USENIX Security Symposium. (Link)] had already counted apps setting IABTCF_ keys three years earlier, but not read the values. The web methods do not transfer unchanged.A TC string is dot-separated web-safe base64. Segment 0 is the Core String and is always present. Later segments carry a 3-bit segment type in their first bits, so they can appear in any order:
| Segment | Type | Status | What it holds | Why a measurement cares |
|---|---|---|---|---|
| Core | — | mandatory | metadata, per-purpose consent and legitimate interest, per-vendor consent and legitimate interest, publisher restrictions | This is where almost every published figure comes from |
| Disclosed Vendors | 1 | mandatory since TCF v2.3 (was optional) | which vendors the CMP says it showed the user | Distinguishes “not disclosed” from “disclosed and refused” — before v2.3 those were the same blank |
| Allowed Vendors | 2 | gone — the current spec's SegmentType enum lists only 0, 1 and 3 | out-of-band allowed vendors, which went with the deprecation of out-of-band consent in 2021 | You may meet it in archived strings; a decoder that errors on an unknown segment type will choke on them |
| Publisher TC | 3 | optional | the publisher's own purposes, including custom ones | Vendors are told not to rely on it unless they have an agreement with the publisher; treat it as publisher self-description |
A string with only one segment is either pre-v2.3 or non-conformant. Count segments before you conclude anything about disclosure.
The Core String is a fixed bit layout. These are the fields that change what a paper can claim; the full table is in the spec.
| Field | Bits | What it actually tells you |
|---|---|---|
Version | 6 | 2 for every string you will meet today. A v1 string is invalid since 30 September 2020 |
Created / LastUpdated | 36 each | Both carry the same day-level value since December 2021. You cannot tell a first choice from a re-confirmation, and you cannot recover a time of day |
CmpId | 12 | Which CMP says it wrote the string. Joins to the Global CMP List. Not authenticated |
CmpVersion , ConsentScreen | 12 , 6 | CMP self-report. Useful for grouping, useless as ground truth |
ConsentLanguage | 12 | The language the CMP says the UI was in — not the site's language and not the user's |
VendorListVersion | 12 | The GVL version every vendor ID in this string must be resolved against |
TcfPolicyVersion | 6 | Policy generation. 4 = TCF v2.2, 5 = v2.3 and later. This is how you bucket a longitudinal dataset |
IsServiceSpecific | 1 | Should be 1. A 0 means a global-scope string, which has been invalid since 1 September 2021 |
UseNonStandardTexts | 1 | The CMP is telling you it did not show the standard purpose descriptions |
PurposesConsent | 24 | One bit per purpose. 11 purposes exist since TCF v2.2; papers written against v2.1 and earlier describe 10 |
PurposesLITransparency | 24 | Legitimate interest established and not objected to. Not consent |
PurposeOneTreatment | 1 | 1 means Purpose 1 was not disclosed because the publisher's jurisdiction does not require it. A 0 in PurposesConsent bit 1 then does not mean refusal |
PublisherCC | 12 | The publisher's establishment or “the legislative country of reference” — the spec allows either. See the caveat below: in an eight-site probe it tracked the crawler's IP |
| vendor sections | variable | Either a bitfield up to MaxVendorId or run-length ranges. Both encode the same thing; a decoder that handles only one silently returns an empty set |
Every figure about the TCF is a figure about one version of it. This is the specification's own changelog, re-fetched on 2026-08-26, filtered to changes a measurement can see — two v2.1 rows about a JSON example and a document merge are dropped:
| Date | Version | What changed that a measurement can see |
|---|---|---|
| April 2018 | 1.1 | __cmp() API, five purposes, euconsent cookie on consensu.org |
| August 2019 | 2.0 | __tcfapi, ten purposes, publisher restrictions, segments |
| June 2021 → 1 Sept 2021 | 2.0 | Global scope, out-of-band consent and the shared consensu.org cookie deprecated; global-scope strings invalid from 1 September 2021 |
| December 2021 | 2.0 | Created and LastUpdated collapsed to one day-level value |
| May 2023 | 2.2 | Eleven purposes; legitimate interest removed for purposes 3–6; getTCData API command deprecated; policy version 4, older strings invalid after 30 September 2023 |
| February 2024 | 2.2 | gdpr_pd macro deprecated; environments field added to the CMP list |
| April 2025 | 2.3 | Disclosed Vendors segment mandatory, replacing the workaround of setting the vendor LI bit for special-purpose-only vendors. The changelog dates the workaround's end to strings created on or after 1 March 2026; it puts no date on the segment itself becoming mandatory, and this page assumes the same boundary because they are the same change3) |
| May 2026 | 2.4 | StandardTexts field added to the GVL JSON; the text requiring special-purpose-only vendors to be disclosed under the Legitimate Interest declaration removed from the spec |
Two consequences for anyone crawling now. A dataset that spans 1 March 2026 spans two different meanings of the vendor legitimate-interest bit: before that date it was also set for vendors that declared only special purposes, so a naive “share of vendors asserting legitimate interest” is inflated on the early side of the boundary and not on the late side. And a dataset that spans May 2023 spans the change from ten purposes to eleven and the removal of legitimate interest for purposes 3–6, which is exactly the quantity [3Smith, Michael; Torres-Agüero, Antonio; Grossman, Riley; Sen, Pritam; Chen, Yi; Borcea, Cristian (2024): "A Study of GDPR Compliance under the Transparency and Consent Framework", in: Proceedings of the ACM Web Conference. (DOI)] measured under the old rules.
The TCF has never required one storage location — v2 explicitly leaves it to the CMP, including non-cookie storage. Reading only one channel is the single most common way to under-count.
| Channel | How you capture it | What it proves | Seen in |
|---|---|---|---|
CMP JavaScript API — window.__tcfapi, or the __tcfapiLocator iframe for third-party frames | inject a script, register an addEventListener callback | what the CMP will tell a first-party script right now | [2Matte, Célestin; Bielova, Nataliia; Santos, Cristiana Teixeira (2020): "Do Cookie Banners Respect my Choice? Measuring Legal Compliance of Banners from IAB Europe's Transparency and Consent Framework", in: Proceedings of the IEEE Symposium on Security and Privacy. (DOI), 1Kancherla, Gayatri Priyadarsini; Bielova, Nataliia; Santos, Cristiana; Bichhawat, Abhishek (2025): "Johnny Can't Revoke Consent Either: Measuring Compliance of Consent Revocation on the Web", in: Proceedings on Privacy Enhancing Technologies. (DOI)] |
First-party storage — a cookie or localStorage key of the CMP's choosing | read cookie jar and localStorage after load | what persists to the next visit | TCString in first-party cookies on 122 of 136 TCF sites [1Kancherla, Gayatri Priyadarsini; Bielova, Nataliia; Santos, Cristiana; Bichhawat, Abhishek (2025): "Johnny Can't Revoke Consent Either: Measuring Compliance of Consent Revocation on the Web", in: Proceedings on Privacy Enhancing Technologies. (DOI)] |
URL macros on GET — gdpr=1 and gdpr_consent=${GDPR_CONSENT_<vendorId>} | log outgoing request URLs | what a named vendor was actually sent | GET on 764 of 1,426 (53.6%) TCF sites [2Matte, Célestin; Bielova, Nataliia; Santos, Cristiana Teixeira (2020): "Do Cookie Banners Respect my Choice? Measuring Legal Compliance of Banners from IAB Europe's Transparency and Consent Framework", in: Proceedings of the IEEE Symposium on Security and Privacy. (DOI)] |
| POST bodies | log postData, not just URLs | the same, for vendors that POST | 3,423 TC strings found in POST bodies in one crawl [1Kancherla, Gayatri Priyadarsini; Bielova, Nataliia; Santos, Cristiana; Bichhawat, Abhishek (2025): "Johnny Can't Revoke Consent Either: Measuring Compliance of Consent Revocation on the Web", in: Proceedings on Privacy Enhancing Technologies. (DOI)]; POSTs carried a string on 399 sites in 2019 [2Matte, Célestin; Bielova, Nataliia; Santos, Cristiana Teixeira (2020): "Do Cookie Banners Respect my Choice? Measuring Legal Compliance of Banners from IAB Europe's Transparency and Consent Framework", in: Proceedings of the IEEE Symposium on Security and Privacy. (DOI)] |
| HTTP responses — JSON and HTML | parse response bodies | whether a third party changed the string before passing it on | 52 in JSON, 170 in HTML [1Kancherla, Gayatri Priyadarsini; Bielova, Nataliia; Santos, Cristiana; Bichhawat, Abhishek (2025): "Johnny Can't Revoke Consent Either: Measuring Compliance of Consent Revocation on the Web", in: Proceedings on Privacy Enhancing Technologies. (DOI)] |
Mobile app storage — IABTCF_TCString, IABTCF_PurposeConsents, IABTCF_PurposeLegitimateInterests, IABTCF_CmpSdkID in Android SharedPreferences or iOS NSUserDefaults | pull the app's preferences file off a rooted device or emulator | the in-app equivalent, and the only channel that exists there | [4Morel, Victor; Santos, Cristiana; Carlsson, Pontus; Ahlinder, Joel; Duvignau, Romaric (2026): "The TCF doesn't really A(A)ID - Automatic Privacy Analysis and Legal Compliance of TCF-based Android Applications", Proceedings on Privacy Enhancing Technologies 2026(3). (DOI), 5Koch, Simon; Altpeter, Benjamin; Johns, Martin (2023): "The OK Is Not Enough: A Large Scale Study of Consent Dialogs in Smartphone Applications", in: Proceedings of the USENIX Security Symposium. (Link)] |
| Inside a GPP string — section ID 2 of IAB Tech Lab's Global Privacy Platform | decode the GPP header, then the TCF-EU section | the same string, wrapped, on sites that have migrated to the multi-jurisdiction envelope | not measured in this corpus |
One channel is historical and must not be reported as current: the shared cookie on the consensu.org domain, euconsent under TCF v1.x and euconsent-v2 under v2.0's optional global scope. Either way a CMP could read a consent string written by a different CMP on a different site, which is how [2Matte, Célestin; Bielova, Nataliia; Santos, Cristiana Teixeira (2020): "Do Cookie Banners Respect my Choice? Measuring Legal Compliance of Banners from IAB Europe's Transparency and Consent Framework", in: Proceedings of the IEEE Symposium on Security and Privacy. (DOI)] found that “Using this protocol, 62 (4.3%) websites return the same consent strings” after planting one in 2019. IAB Europe announced the deprecation of global scope, out-of-band consent and the euconsent-v2 cookie on 22 June 2021, and global-scope strings have been invalid since 1 September 2021. If you crawl statefully today, a stale consent string is a problem you carry between page loads of the same site, not one you carry between sites via IAB infrastructure.
The API channel needs one specific piece of code, because the command most published crawlers use for it is deprecated. This is the current pattern, and it is what produced the output below:
// Inject BEFORE any page script (Playwright: context.addInitScript). // Uses addEventListener, not the getTCData command deprecated in TCF v2.2. // Records EVERY event, so a late 'useractioncomplete' is not lost, and leaves // a defined-but-silent __tcfapi visible as an empty event list rather than as // "no TCF". window.__probe = { events: [] }; (function poll(n) { if (typeof window.__tcfapi === 'function') { window.__tcfapi('addEventListener', 2, function (d, ok) { window.__probe.events.push({ ok: ok, eventStatus: d && d.eventStatus, // tcloaded | cmpuishown | useractioncomplete cmpStatus: d && d.cmpStatus, // stub | loaded | error gdprApplies: d && d.gdprApplies, // the PUBLISHER's determination, not yours cmpId: d && d.cmpId, tcfPolicyVersion: d && d.tcfPolicyVersion, tcString: d && d.tcString, addtlConsent: d && d.addtlConsent, // Google AC string, if the CMP supports it }); }); return; } if (n > 0) setTimeout(function () { poll(n - 1); }, 250); // 10s for the stub to resolve })(40);
A worked example, from a real crawl. Eight European news sites, one page load each, no banner interaction, from a residential Swiss vantage point on 2026-08-26. The probe is scripts/tcf_live_probe.mjs and the full output is on the provenance page. Four of the eight answered:
spiegel.de (CMP 6, Sourcepoint): a TC string exists before any click, with purposesConsent empty and purposesLITransparency = [7, 9, 10]. That is the specification working as designed — the CMP API says that when the UI is shown it shall create a string with legitimate-interest signals true and consent signals false — and it is why “a TC string exists pre-interaction” is not a violation on its own.corriere.it (CMP 218, RCS MediaGroup): purposesConsent empty, but 932 vendor-consent bits set, all resolving to real vendors in GVL 173. A detector that reads only the purpose array, as [2Matte, Célestin; Bielova, Nataliia; Santos, Cristiana Teixeira (2020): "Do Cookie Banners Respect my Choice? Measuring Legal Compliance of Banners from IAB Europe's Transparency and Consent Framework", in: Proceedings of the IEEE Symposium on Security and Privacy. (DOI)] explicitly did — “we focus on the purposes stored in a consent string, and do not analyze the array of allowed advertisers” — records nothing here. Which array you read decides whether you see anything.bild.de (CMP 345) and focus.de (CMP 35): empty strings, and both CMP IDs belong to the publisher (Axel Springer, BurdaForward), flagged isCommercial: false in the CMP list. Attributing a behaviour to “the CMP” attributes it to the publisher on these sites.lemonde.fr, elmundo.es, marca.com: __tcfapi is defined and the listener never fires within twelve seconds. Score these as “no TCF” and you have three false negatives out of eight. telegraph.co.uk has no __tcfapi at all from this vantage point.PublisherCC = CH, which is where the crawler is, not where Axel Springer, Spiegel or Burda are established. This is not necessarily a defect: the specification defines the field as “the country in which the publisher's business entity is established or the legislative country of reference”, so a CMP that sets it from the visitor's location is arguably using the second reading. But it does mean PublisherCC is not a publisher attribute — do not treat it as one without checking it from a second vantage point.
The canonical decoder is IAB Tech Lab's iabtcf-es. Use it — and then check which package you installed, because the project renamed its npm scope and left the old one on the registry, undeprecated, three years stale:
| npm package | Latest | Published | Deprecated on npm? |
|---|---|---|---|
@iabtcf/core | 1.5.6 | 2023-04-04 | no |
@iabtechlabtcf/core | 1.5.21 | 2026-02-10 | no |
This is not a cosmetic difference, and the failure is silent. Decode the same string with both and they disagree on useNonStandardTexts: the 2026 package exposes it, the 2023 package exposes the field under its old specification name useNonStandardStacks and returns undefined for the current one. Code written against the current spec gets undefined rather than an error, and undefined is falsy. Record the exact package and version in the paper, because a decoder that predates a field does not tell you the field is missing; it returns a default.
The other half of the warning is that a decoder returning a value is not evidence that the input was a TC string. [3Smith, Michael; Torres-Agüero, Antonio; Grossman, Riley; Sen, Pritam; Chen, Yi; Borcea, Cristian (2024): "A Study of GDPR Compliance under the Transparency and Consent Framework", in: Proceedings of the ACM Web Conference. (DOI)] searched requests and cookies for the keys gdpr_consent and euconsent_v2 and the C prefix, then found by hand that “we found 62 decoded strings that were not valid TC strings in TCF v2.1” — including the literal text cookie_banner_accepted — and concluded that “Currently, the IAB decoder lacks a solution for checking if a TC string is valid or not”. Validate structurally: version 2, a plausible VendorListVersion, a TcfPolicyVersion that exists, a PublisherCC that is two letters, and a segment inventory.
The decoder below reads the Core String fields listed above and nothing else, which is the point: it cannot silently disagree with a newer specification about a field it does not touch. It was checked field-by-field against @iabtechlabtcf/core 1.5.21 on the specification's own example string, a 2020-era string, and the four strings captured live on 2026-08-26 — all six agree exactly, on all eighteen fields. Its output is the spiegel.de row of the worked example above.
// Decode the Core segment of a TCF v2 TC String, plus the segment inventory. // // Why hand-rolled: the reference implementation is IAB Tech Lab's iabtcf-es, // published as @iabtechlabtcf/core (1.5.21, 2026-02-10) — NOT @iabtcf/core, // which is the same project's abandoned npm scope, undeprecated and frozen at // 1.5.6 from 2023. This reads the fields a measurement actually needs and // nothing else, so it cannot silently disagree with a newer spec about a field // it does not touch. Cross-checked field-for-field against 1.5.21 on 6 strings. // // node tcstring.mjs '<tcstring>' // // No try/catch: a string that is not a TC string must crash here, not be // silently reported as "no consent". const B64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; function bits(segment) { let out = ''; for (const ch of segment) { const i = B64.indexOf(ch); if (i < 0) throw new Error(`not web-safe base64: ${JSON.stringify(ch)} in ${segment.slice(0, 20)}`); out += i.toString(2).padStart(6, '0'); } return out; } const int = (b, s, n) => parseInt(b.slice(s, s + n), 2); const chars = (b, s, n) => { let out = ''; for (let i = 0; i < n / 6; i++) out += String.fromCharCode(65 + int(b, s + i * 6, 6)); return out; }; // Created / LastUpdated are deciseconds since epoch, but since Dec 2021 both // carry the SAME day-level value: you cannot recover the time of day, and you // cannot tell a first choice from a re-confirmation. const day = (b, s) => new Date(int(b, s, 36) * 100).toISOString().slice(0, 10); function vendorSection(b, start) { const maxVendorId = int(b, start, 16); const isRange = b[start + 16] === '1'; const ids = new Set(); let p = start + 17; if (!isRange) { for (let i = 0; i < maxVendorId; i++) if (b[p + i] === '1') ids.add(i + 1); p += maxVendorId; } else { const n = int(b, p, 12); p += 12; for (let i = 0; i < n; i++) { const isARange = b[p] === '1'; p += 1; const startId = int(b, p, 16); p += 16; if (isARange) { const endId = int(b, p, 16); p += 16; for (let v = startId; v <= endId; v++) ids.add(v); } else ids.add(startId); } } return { maxVendorId, encoding: isRange ? 'range' : 'bitfield', ids, end: p }; } export function decodeCore(tcString) { const segments = tcString.split('.'); const b = bits(segments[0]); const core = { version: int(b, 0, 6), created: day(b, 6), lastUpdated: day(b, 42), cmpId: int(b, 78, 12), cmpVersion: int(b, 90, 12), consentScreen: int(b, 102, 6), consentLanguage: chars(b, 108, 12), vendorListVersion: int(b, 120, 12), tcfPolicyVersion: int(b, 132, 6), isServiceSpecific: b[138] === '1', useNonStandardTexts: b[139] === '1', specialFeatureOptIns: [...Array(12)].map((_, i) => b[140 + i] === '1'), purposesConsent: [...Array(24)].map((_, i) => b[152 + i] === '1'), purposesLITransparency: [...Array(24)].map((_, i) => b[176 + i] === '1'), purposeOneTreatment: b[200] === '1', publisherCC: chars(b, 201, 12), }; const vc = vendorSection(b, 213); const vli = vendorSection(b, vc.end); const on = (a) => a.map((v, i) => (v ? i + 1 : 0)).filter(Boolean); return { ...core, specialFeatureOptIns: on(core.specialFeatureOptIns), purposesConsent: on(core.purposesConsent), purposesLITransparency: on(core.purposesLITransparency), vendorConsent: { ...vc, ids: [...vc.ids], end: undefined }, vendorLegitimateInterest: { ...vli, ids: [...vli.ids], end: undefined }, segments: segments.map((s, i) => ({ index: i, // Segment 0 is the Core String. Every later segment declares its own type // in its first 3 bits. The current spec's SegmentType enum is 0 = Core, // 1 = DisclosedVendors, 3 = PublisherTC; 2 = AllowedVendors was dropped // with out-of-band consent in 2021 and survives only in archived strings. segmentType: i === 0 ? 'core' : int(bits(s), 0, 3), length: s.length, })), }; } if (import.meta.url === `file://${process.argv[1]}`) { const s = process.argv[2]; console.log(JSON.stringify(decodeCore(s), (k, v) => (v === undefined ? undefined : v), 1)); }
Vendor IDs mean nothing on their own. The GVL is republished weekly, Thursdays at 17:00 CET, and the string tells you which version it was written against, so a reproducible decode is:
current : https://vendor-list.consensu.org/v3/vendor-list.json
archive : https://vendor-list.consensu.org/v3/archives/vendor-list-v{vendorListVersion}.json
Fetched on 2026-08-26, the current list is version 173, tcfPolicyVersion 5, last updated 2026-08-20, with 1,203 vendors and a highest vendor ID of 1,634 — so about a quarter of the IDs below the maximum resolve to nothing in the current list, whether because the vendor left or because the ID was never issued. That gap is the reason to archive: resolve a 2023 string against today's list and the departed vendors vanish silently rather than erroring. The specification also requires GVL fetches to be server-side and cached to the max-age header, and warns that over-fetching gets you blocked; a crawler that pulls the GVL once per site is doing it wrong and is also generating a distinctive traffic signature.
For scale over time: the list held 751 companies at the end of May 2021 [7Toth, Michael; Bielova, Nataliia; Roca, Vincent (2022): "On dark patterns and manipulation of website publishers by CMPs", Proceedings on Privacy Enhancing Technologies 2022(3). (DOI)] and 684 registered companies in February 2021 [6Hils, Maximilian; Woods, Daniel W.; Böhme, Rainer (2021): "Privacy Preference Signals: Past, Present and Future", in: Proceedings on Privacy Enhancing Technologies. (DOI)], against 1,203 today.
CmpId joins to the Global CMP List at https://cmplist.consensu.org/v2/cmp-list.json. On 2026-08-26 it held 264 entries of which 189 are active and 75 carry a deletedDate, with a highest ID of 515. Three consequences: an ID you decode may not be in the current list (join against the whole file, including deleted entries, not just the active ones); the ID space is sparse, so a “not found” is at least as likely to be an invalid string as a new CMP; and the list flags isCommercial, which distinguishes a CMP vendor from a publisher running its own — a distinction that matters the moment you attribute a design choice to “the CMP”, as [7Toth, Michael; Bielova, Nataliia; Roca, Vincent (2022): "On dark patterns and manipulation of website publishers by CMPs", Proceedings on Privacy Enhancing Technologies 2022(3). (DOI)] does.
And the field is not authenticated. [2Matte, Célestin; Bielova, Nataliia; Santos, Cristiana Teixeira (2020): "Do Cookie Banners Respect my Choice? Measuring Legal Compliance of Banners from IAB Europe's Transparency and Consent Framework", in: Proceedings of the IEEE Symposium on Security and Privacy. (DOI)] found “the following incorrect CMP IDs in consent strings: 1, 0 and 4095” on 155, 45 and 3 websites respectively, at a time when valid IDs ran from 2 to 265, and found “CMP IDs in GET and POST requests different from the ones found using the standard APIs on 48 websites”.
The TCF only covers vendors registered on the GVL. Google runs a parallel list — Ad Tech Providers (ATPs) — for partners that are not, and a parallel string to carry consent for them. If you are measuring “how many parties did this site get consent for”, ignoring it undercounts by whatever the ATP list contributes, and in the CMP consoles [7Toth, Michael; Bielova, Nataliia; Roca, Vincent (2022): "On dark patterns and manipulation of website publishers by CMPs", Proceedings on Privacy Enhancing Technologies 2022(3). (DOI)] inspected the ATP list held “a total of 641 companies at the same date” in May 2021 against the GVL's 751 — “almost the same size” then. It has not kept pace: on 2026-08-26 the ATP list held 715 providers against the GVL's 1,203, both re-fetched from their publishers' own files. Neither number is a share of the signal, only of the lists: how many parties a given site actually discloses through each is unmeasured.
The format is trivial compared with the TC string — it is not bit-packed at all:
ACv2: 2 ~ <dot-separated consented ATP IDs> ~ dv. <dot-separated disclosed ATP IDs> 2~1.10~dv.2.3.4 consented to 1 and 10; 2, 3 and 4 disclosed but not consented 2~~dv.1.2.3.4.10 all five disclosed, none consented (or no decision yet) 2~1.2.3.4.10~dv. all five consented
A vendor in the consented list is not repeated in the disclosed list. ACv2 has been the standard since December 2023; v1 strings — a bare dot-list with no dv part — are still accepted but cannot express disclosure-without-consent, so a v1 string tells you strictly less.4)
Where to look for it:
| Where | Key or parameter |
|---|---|
| CMP API | addtlConsent field on the TCData and InAppTCData objects |
| Web storage | CMP's choice; an addtl_consent cookie is common. [8Liu, Zengrui; Iqbal, Umar; Saxena, Nitesh (2024): "Opted Out, Yet Tracked: Are Regulations Enough to Protect Your Privacy?", in: Proceedings on Privacy Enhancing Technologies. (DOI)] record Quantcast setting three: euconsent-v2, _pbjs_userid_consent_data and addtl_consent |
| Mobile | IABTCF_AddtlConsent in SharedPreferences / NSUserDefaults |
| URL / pixels | &addtl_consent=${ADDTL_CONSENT} |
| Bid requests | consented_providers_settings.consented_providers in Google's OpenRTB extension |
Four rules from the specification that a measurement can test directly, and none of which anyone in this corpus has:
This is an open measurement gap, and an unusually clean one. A wide regex over all 5,869 full texts in this corpus — addtl_consent, “AC string”, “Additional Consent”, “Ad Tech(nology) Provider”, ATP, consented_providers — matches 26 papers. Reading every match in context leaves 3 that mean Google's mechanism: [7Toth, Michael; Bielova, Nataliia; Roca, Vincent (2022): "On dark patterns and manipulation of website publishers by CMPs", Proceedings on Privacy Enhancing Technologies 2022(3). (DOI)] names the ATP list and its size, [8Liu, Zengrui; Iqbal, Umar; Saxena, Nitesh (2024): "Opted Out, Yet Tracked: Are Regulations Enough to Protect Your Privacy?", in: Proceedings on Privacy Enhancing Technologies. (DOI)] names the addtl_consent cookie, and [9Tahaei, Mohammad; Ramokapane, Kopo M.; Li, Tianshi; Hong, Jason I.; Rashid, Awais (2022): "Charting App Developers' Journey Through Privacy Regulation Features in Ad Networks", in: Proceedings on Privacy Enhancing Technologies. (DOI)] lists Google's “Ad technology providers” console page among AdMob's GDPR controls. The other 23 are false positives — Advanced Threat Protection, “ATP: In-network Aggregation”, a D-Link binary called atp, “absolute true positives”, and seven papers using the ordinary English phrase additional consent about an IRB form or a second permission dialog.
No paper in these seven venues decodes an AC string, resolves an ATP ID, or checks any of the four rules above. The script and its full adjudication are scripts/tcf_ac_probe.mjs. If you are looking for a self-contained, fully specified, checkable measurement, this is one.
| A decoded string is evidence of… | …and is not evidence of |
|---|---|
| what a CMP recorded, at day granularity, against a named GVL version | what the user did. The string is written by the CMP; the mapping from click to bit is exactly the thing being audited. [2Matte, Célestin; Bielova, Nataliia; Santos, Cristiana Teixeira (2020): "Do Cookie Banners Respect my Choice? Measuring Legal Compliance of Banners from IAB Europe's Transparency and Consent Framework", in: Proceedings of the IEEE Symposium on Security and Privacy. (DOI)] found “141 websites register positive consent even if the user has not made their choice” and “27 websites store a positive consent even if the user has explicitly opted out” |
| what the CMP will tell a script on that page, at that moment | what the vendors received. [1Kancherla, Gayatri Priyadarsini; Bielova, Nataliia; Santos, Cristiana; Bichhawat, Abhishek (2025): "Johnny Can't Revoke Consent Either: Measuring Compliance of Consent Revocation on the Web", in: Proceedings on Privacy Enhancing Technologies. (DOI)] found five sites where the string in the cookie and the string from __tcfapi disagreed after revocation, and third parties on 101 of 136 sites that were told about acceptance and never about revocation |
| a claimed legal basis per purpose and per vendor | that any processing stopped. [3Smith, Michael; Torres-Agüero, Antonio; Grossman, Riley; Sen, Pritam; Chen, Yi; Borcea, Cristian (2024): "A Study of GDPR Compliance under the Transparency and Consent Framework", in: Proceedings of the ACM Web Conference. (DOI)], crawling with automatic rejection, still found tracking cookies on 30.8% of the domains whose TC string was empty — no legal basis claimed at all — averaging 0.58 per domain |
| a per-purpose consent bit | the absence of processing under legitimate interest. LI lives in a different array. Of the domains [3Smith, Michael; Torres-Agüero, Antonio; Grossman, Riley; Sen, Pritam; Chen, Yi; Borcea, Cristian (2024): "A Study of GDPR Compliance under the Transparency and Consent Framework", in: Proceedings of the ACM Web Conference. (DOI)] found compliant, “1,589 (72.8%) of those domains claim legitimate interest” |
| which CMP says it wrote the string | which CMP wrote it, and often not even a CMP: on two of the four live sites above the CMP ID belongs to the publisher |
| a country code the CMP chose, which the spec allows to be either the publisher's establishment or the legislative country of reference | the publisher's country. Three of four live strings reported the crawler's country instead |
| this site's record | any other site's record. Service-specific scope has been the only valid scope since September 2021 |
The gap between the left column and the right is the whole subject. A compliance claim built on a decoded string is a claim about recording, which is narrow and mechanically checkable — which is exactly why [3Smith, Michael; Torres-Agüero, Antonio; Grossman, Riley; Sen, Pritam; Chen, Yi; Borcea, Cristian (2024): "A Study of GDPR Compliance under the Transparency and Consent Framework", in: Proceedings of the ACM Web Conference. (DOI)] reports violations on only “117 crawls to 48 distinct domains … 1.3% of all crawls and 2.2% of all domains” while a broader banner-compliance audit of the same framework finds a majority — [2Matte, Célestin; Bielova, Nataliia; Santos, Cristiana Teixeira (2020): "Do Cookie Banners Respect my Choice? Measuring Legal Compliance of Banners from IAB Europe's Transparency and Consent Framework", in: Proceedings of the IEEE Symposium on Security and Privacy. (DOI)] found “at least one suspected violation in 304 out of 560 websites (54%)” it hand-checked. Neither number is wrong. They answer different questions, and a paper that does not say which one it asked will be asked in review.
corriere.it case above has an empty purpose-consent array and 932 vendor-consent bits.localStorage, GET parameters, POST bodies and response bodies can all disagree. If you only instrument the API you are measuring the CMP's claim, not the traffic.PurposeOneTreatment-adjacent zeros. A 0 in Purpose 1 consent can mean “the jurisdiction does not require it”, not “the user refused”.__tcfapi and never called back inside twelve seconds. Record the timeout as a distinct outcome; do not fold it into “no TCF”.getTCData. It was deprecated in TCF v2.2 in May 2023 in favour of addEventListener, and the three commands a CMP must support are now ping, addEventListener and removeEventListener. It still works: on the four live sites above that answered anything, getTCData returned a TC string on all four — but on corriere.it it did so with the callback's success flag set to false, so a crawler that checks success before reading tcString loses the site. A CMP is also within spec to drop the command entirely, and the failure mode is a quietly growing “no TCF” bucket.gdprApplies is the publisher's determination, and CMPs commonly derive it from geo-IP. See Crawling location.__tcfapi, no cookie: IABTCF_* keys in SharedPreferences. [5Koch, Simon; Altpeter, Benjamin; Johns, Martin (2023): "The OK Is Not Enough: A Large Scale Study of Consent Dialogs in Smartphone Applications", in: Proceedings of the USENIX Security Symposium. (Link)] found “TCF-related settings in 146 (4.0%) apps” of 3,654 analysed — a much thinner population than the web.
The extraction schema has no “decoded a TC string” field, so the candidate population here is defined by full text: papers whose text contains at least one of Transparency and Consent Framework, __tcfapi, euconsent, TC String or IAB Europe. The bare acronym TCF is deliberately excluded from that union — it has other expansions in a security corpus. Two thresholds, because one mention in related work is not a measurement:
| Population | Papers | Share of the corpus5) |
|---|---|---|
| TCF-MENTION — ≥1 core wording | 77 | 1.3% of the 5,859 papers with an extraction record |
| TCF-CANDIDATE — ≥5 core wordings | 19 | 0.3% |
A mention threshold is a candidate set, not an answer — and here it is wrong more often than it is right. All 19 candidates were read against their own full text and classified by what a figure in the paper actually depends on:
| Verdict | Papers | Meaning |
|---|---|---|
| works with the string | 4 | captures, decodes or compares TC strings, or reads the IABTCF_* keys in an app |
| detects only | 5 | uses TCF presence as a signal — probing __cmp/__tcfapi, counting CMPs, reading which consent cookies appear — but never reads a string's contents |
| background only | 10 | the framework appears in the introduction, related work or reference list. No figure depends on it |
So the ≥5 threshold has a precision of 4/19 (21%) for “works with a TC string” and 9/19 (47%) for “does anything with the TCF at all”. Four of the audited candidates decode a TC string: [2Matte, Célestin; Bielova, Nataliia; Santos, Cristiana Teixeira (2020): "Do Cookie Banners Respect my Choice? Measuring Legal Compliance of Banners from IAB Europe's Transparency and Consent Framework", in: Proceedings of the IEEE Symposium on Security and Privacy. (DOI)], [3Smith, Michael; Torres-Agüero, Antonio; Grossman, Riley; Sen, Pritam; Chen, Yi; Borcea, Cristian (2024): "A Study of GDPR Compliance under the Transparency and Consent Framework", in: Proceedings of the ACM Web Conference. (DOI)], [1Kancherla, Gayatri Priyadarsini; Bielova, Nataliia; Santos, Cristiana; Bichhawat, Abhishek (2025): "Johnny Can't Revoke Consent Either: Measuring Compliance of Consent Revocation on the Web", in: Proceedings on Privacy Enhancing Technologies. (DOI)] and [4Morel, Victor; Santos, Cristiana; Carlsson, Pontus; Ahlinder, Joel; Duvignau, Romaric (2026): "The TCF doesn't really A(A)ID - Automatic Privacy Analysis and Legal Compliance of TCF-based Android Applications", Proceedings on Privacy Enhancing Technologies 2026(3). (DOI)]. Read that as a floor, not a census — the 58 papers that mention the framework fewer than five times were not read, and a paper could decode strings in a two-sentence methods paragraph and never clear the threshold. What the audit does establish is that the threshold's precision is poor, so every figure below is scoped to the audited tiers rather than to the 19. The audit, its evidence and one reclassification it forced are on the provenance page; the script is scripts/tcf_core_audit.mjs.
The concentration is extreme, and it is a fact about venues rather than about the field:
| Venue | Papers in corpus | TCF-MENTION | Share of that venue | ≥5 candidates | Audited: works or detects |
|---|---|---|---|---|---|
| PETS | 510 | 30 | 5.9% | 11 | 5 |
| USENIX Sec | 1,410 | 14 | 1.0% | 4 | 2 |
| TheWebConf | 843 | 11 | 1.3% | 2 | 1 |
| CCS | 990 | 8 | 0.8% | 1 | 0 |
| IEEE S&P | 767 | 7 | 0.9% | 1 | 1 |
| IMC | 638 | 4 | 0.6% | 0 | 0 |
| NDSS | 701 | 3 | 0.4% | 0 | 0 |
More than half of the papers that do anything with the TCF are at PETS — 11 of the 19 candidates and 5 of the audited 9, though only 30 of the 77 that merely mention it. If you are planning a TCF paper, that is where the reviewers who know the format are, and it is also where the related work you must not duplicate lives. Note also what is absent: CHI, SOUPS, EuroS&P, ACSAC and AsiaCCS are not in this corpus at all, and a good deal of consent research is published there.
By year, first appearance is 2019 — a year after the framework's first public version and one after the GDPR became applicable:
| Period | 2010–2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 |
|---|---|---|---|---|---|---|---|---|---|
| Corpus papers | 1,534 | 402 | 404 | 379 | 546 | 719 | 690 | 770 | 415 |
| TCF-MENTION | 16) | 3 | 5 | 6 | 13 | 14 | 17 | 13 | 5 |
| ≥5 candidates | 0 | 1 | 2 | 1 | 3 | 3 | 5 | 3 | 1 |
2025 is thin at the edges and 2026 is provisional — CCS 2026 and IMC 2026 have not been held, and IEEE S&P 2026 and TheWebConf 2026 are under-selected because selection screens on abstracts that are not yet in OpenAlex. Do not read the 2024→2026 shape as a decline. See the corpus page.
Population and banner action as the extraction recorded them. (no crawl) means the paper has no crawl configuration — an app study or a console review.
| Year | Venue | Tier | Population | Banner action | Paper |
|---|---|---|---|---|---|
| 2020 | IEEE S&P | works with string | 28,257 domains | accept-and-reject | [2Matte, Célestin; Bielova, Nataliia; Santos, Cristiana Teixeira (2020): "Do Cookie Banners Respect my Choice? Measuring Legal Compliance of Banners from IAB Europe's Transparency and Consent Framework", in: Proceedings of the IEEE Symposium on Security and Privacy. (DOI)] |
| 2021 | PETS | detects only | 100,000 websites | no-interaction | [6Hils, Maximilian; Woods, Daniel W.; Böhme, Rainer (2021): "Privacy Preference Signals: Past, Present and Future", in: Proceedings on Privacy Enhancing Technologies. (DOI)] |
| 2022 | PETS | detects only | 7 CMP consoles | (no crawl) | [7Toth, Michael; Bielova, Nataliia; Roca, Vincent (2022): "On dark patterns and manipulation of website publishers by CMPs", Proceedings on Privacy Enhancing Technologies 2022(3). (DOI)] |
| 2023 | USENIX Sec | detects only | 3,654 apps analysed7) | (no crawl) | [5Koch, Simon; Altpeter, Benjamin; Johns, Martin (2023): "The OK Is Not Enough: A Large Scale Study of Consent Dialogs in Smartphone Applications", in: Proceedings of the USENIX Security Symposium. (Link)] |
| 2024 | TheWebConf | works with string | 2,230 websites | reject-all | [3Smith, Michael; Torres-Agüero, Antonio; Grossman, Riley; Sen, Pritam; Chen, Yi; Borcea, Cristian (2024): "A Study of GDPR Compliance under the Transparency and Consent Framework", in: Proceedings of the ACM Web Conference. (DOI)] |
| 2024 | USENIX Sec | detects only | 97,090 websites | accept-and-reject | [10Bouhoula, Ahmed; Kubicek, Karel; Zac, Amit; Cotrini, Carlos; Basin, David (2024): "Automated Large-Scale Analysis of Cookie Notice Compliance", in: Proceedings of the USENIX Security Symposium. (Link)] |
| 2024 | PETS | detects only | 100,000 websites | accept-and-reject | [8Liu, Zengrui; Iqbal, Umar; Saxena, Nitesh (2024): "Opted Out, Yet Tracked: Are Regulations Enough to Protect Your Privacy?", in: Proceedings on Privacy Enhancing Technologies. (DOI)] |
| 2025 | PETS | works with string | 200 domains | accept-and-reject | [1Kancherla, Gayatri Priyadarsini; Bielova, Nataliia; Santos, Cristiana; Bichhawat, Abhishek (2025): "Johnny Can't Revoke Consent Either: Measuring Compliance of Consent Revocation on the Web", in: Proceedings on Privacy Enhancing Technologies. (DOI)] |
| 2026 | PETS | works with string | 4,482 apps downloaded8) | no-interaction | [4Morel, Victor; Santos, Cristiana; Carlsson, Pontus; Ahlinder, Joel; Duvignau, Romaric (2026): "The TCF doesn't really A(A)ID - Automatic Privacy Analysis and Legal Compliance of TCF-based Android Applications", Proceedings on Privacy Enhancing Technologies 2026(3). (DOI)] |
The ten background-only candidates are named, with the reason each was excluded, on the provenance page. Several are excellent consent papers — [11Bollinger, Dino; Kubicek, Karel; Cotrini, Carlos; Basin, David (2022): "Automating Cookie Consent and GDPR Violation Detection", in: 31st USENIX Security Symposium (USENIX Security 22), pp. 2893-2910. USENIX Association, Boston, MA. (Link)], [12Utz, Christine; Degeling, Martin; Fahl, Sascha; Schaub, Florian; Holz, Thorsten (2019): "(Un)informed Consent: Studying GDPR Consent Notices in the Field", in: Proceedings of the ACM SIGSAC Conference on Computer and Communications Security. (DOI)], [13Rasaii, Ali; Dao, Ha; Feldmann, Anja; Javid, Mohammadmahdi; Gasser, Oliver; Gosain, Devashish (2025): "Intractable Cookie Crumbs: Unveiling the Nexus of Stateful Banner Interaction and Tracking Cookies", in: Proceedings on Privacy Enhancing Technologies, pp. 429-445. (DOI)], [14Demir, Nurullah; Urban, Tobias; Pohlmann, Norbert; Wressnegger, Christian (2024): "A Large-Scale Study of Cookie Banner Interaction Tools and their Impact on Users' Privacy", in: Proceedings on Privacy Enhancing Technologies, pp. 5-20. (DOI)], [15Aziz, Muhammad Abu Bakar; Wilson, Christo (2024): "Johnny Still Can't Opt-out: Assessing the IAB CCPA Compliance Framework", in: Proceedings on Privacy Enhancing Technologies. (DOI)], [16Tang, Brian; Bui, Duc; Shin, Kang G. (2025): "Navigating Cookie Consent Violations Across the Globe", in: Proceedings of the USENIX Security Symposium. (Link)], [17Zimmeck, Sebastian; Wang, Oliver; Alicki, Kuba; Wang, Jocelyn; Eng, Sophie (2023): "Usability and Enforceability of Global Privacy Control", Proceedings on Privacy Enhancing Technologies 2023(2). (DOI)], [18Utz, Christine; Amft, Sabrina; Degeling, Martin; Holz, Thorsten; Fahl, Sascha; Schaub, Florian (2023): "Privacy Rarely Considered: Exploring Considerations in the Adoption of Third-Party Services by Websites", Proceedings on Privacy Enhancing Technologies 2023(1):5-28. (DOI)], [19Kumar, Vinayshekhar Bannihatti; Iyengar, Roger; Nisal, Namita; Feng, Yuanyuan; Habib, Hana; Story, Peter; Cherivirala, Sushain; Hagan, Margaret; Cranor, Lorrie Faith; Wilson, Shomir; Schaub, Florian; Sadeh, Norman M. (2020): "Finding a Choice in a Haystack: Automatic Extraction of Opt-Out Statements from Privacy Policy Text", in: Proceedings of the ACM Web Conference. (DOI)], [9Tahaei, Mohammad; Ramokapane, Kopo M.; Li, Tianshi; Hong, Jason I.; Rashid, Awais (2022): "Charting App Developers' Journey Through Privacy Regulation Features in Ad Networks", in: Proceedings on Privacy Enhancing Technologies. (DOI)] — they simply do not read a TC string. If your related-work section cites them for a TCF result, check what they actually measured.
Three things to take from the table. The populations are small: of the seven that ran a crawl the stated populations are 200, 2,230, 4,482, 28,257, 97,090, 100,000 and 100,000 sites or apps — between two hundred and a hundred thousand, never millions, because TCF sites are a minority of a toplist and you have to find them before you can study them. The banner action is the treatment, and only 4 of those 7 ran both an accept and a reject arm, which for a TCF study is close to mandatory: a single-arm crawl cannot tell “the CMP recorded my refusal” from “the CMP recorded nothing”. And reporting is thin even here — 7 of 7 state a banner action, but only 5 of 7 say whether the crawl was stateful, 8 of 9 state a vantage location and 7 of 9 version their population list.
Every figure below was read back against the paper's own full text and the denominator checked there, because the extraction's metric field names the unit and not always the population.
| Finding | Figure | Denominator | When | Source |
|---|---|---|---|---|
| Sites with a TCF banner | 6.2% (1,426) | 22,949 reachable EU-TLD sites | Sept 2019 | [2Matte, Célestin; Bielova, Nataliia; Santos, Cristiana Teixeira (2020): "Do Cookie Banners Respect my Choice? Measuring Legal Compliance of Banners from IAB Europe's Transparency and Consent Framework", in: Proceedings of the IEEE Symposium on Security and Privacy. (DOI)] |
| TCF implementations in a toplist | 7,582 | Tranco top 100k (13% of the top 5k, 7% of the top 100k) | Feb 2021 | [6Hils, Maximilian; Woods, Daniel W.; Böhme, Rainer (2021): "Privacy Preference Signals: Past, Present and Future", in: Proceedings on Privacy Enhancing Technologies. (DOI)] |
| Android apps implementing TCF | 12.85% (576) | 4,482 downloaded apps | 2025 | [4Morel, Victor; Santos, Cristiana; Carlsson, Pontus; Ahlinder, Joel; Duvignau, Romaric (2026): "The TCF doesn't really A(A)ID - Automatic Privacy Analysis and Legal Compliance of TCF-based Android Applications", Proceedings on Privacy Enhancing Technologies 2026(3). (DOI)] |
Apps setting any IABTCF_ property | 4.0% (146) | 3,654 analysed apps | 2022 | [5Koch, Simon; Altpeter, Benjamin; Johns, Martin (2023): "The OK Is Not Enough: A Large Scale Study of Consent Dialogs in Smartphone Applications", in: Proceedings of the USENIX Security Symposium. (Link)] |
| Positive consent stored before any choice | 9.9% (141) | 1,426 TCF sites | Sept 2019 | [2Matte, Célestin; Bielova, Nataliia; Santos, Cristiana Teixeira (2020): "Do Cookie Banners Respect my Choice? Measuring Legal Compliance of Banners from IAB Europe's Transparency and Consent Framework", in: Proceedings of the IEEE Symposium on Security and Privacy. (DOI)] |
| Positive consent stored after refusal | 5.3% (27) | 508 TCF sites where refusal was possible | Sept 2019 | [2Matte, Célestin; Bielova, Nataliia; Santos, Cristiana Teixeira (2020): "Do Cookie Banners Respect my Choice? Measuring Legal Compliance of Banners from IAB Europe's Transparency and Consent Framework", in: Proceedings of the IEEE Symposium on Security and Privacy. (DOI)] |
| Shared-cookie consent reuse across CMPs9) | 4.3% (62) | 1,426 TCF sites | Sept 2019 | [2Matte, Célestin; Bielova, Nataliia; Santos, Cristiana Teixeira (2020): "Do Cookie Banners Respect my Choice? Measuring Legal Compliance of Banners from IAB Europe's Transparency and Consent Framework", in: Proceedings of the IEEE Symposium on Security and Privacy. (DOI)] |
| TC-string recording violations | 2.2% of domains, 1.3% of crawls | 2,230 domains / 8,929 crawls | May–June 2023 | [3Smith, Michael; Torres-Agüero, Antonio; Grossman, Riley; Sen, Pritam; Chen, Yi; Borcea, Cristian (2024): "A Study of GDPR Compliance under the Transparency and Consent Framework", in: Proceedings of the ACM Web Conference. (DOI)] |
| Compliant domains still claiming legitimate interest | 72.8% (1,589) | 2,182 domains without a violation | May–June 2023 | [3Smith, Michael; Torres-Agüero, Antonio; Grossman, Riley; Sen, Pritam; Chen, Yi; Borcea, Cristian (2024): "A Study of GDPR Compliance under the Transparency and Consent Framework", in: Proceedings of the ACM Web Conference. (DOI)] |
| Strings that decode but are not TC strings | 62 | all strings found in the 2,230-domain crawl | May–June 2023 | [3Smith, Michael; Torres-Agüero, Antonio; Grossman, Riley; Sen, Pritam; Chen, Yi; Borcea, Cristian (2024): "A Study of GDPR Compliance under the Transparency and Consent Framework", in: Proceedings of the ACM Web Conference. (DOI)] |
| Tracking cookies set where the TC string was empty | 0.58 per domain, on 30.8% of them | 605 domains with an empty TC string | May–June 2023 | [3Smith, Michael; Torres-Agüero, Antonio; Grossman, Riley; Sen, Pritam; Chen, Yi; Borcea, Cristian (2024): "A Study of GDPR Compliance under the Transparency and Consent Framework", in: Proceedings of the ACM Web Conference. (DOI)] |
| TC string stored in a first-party cookie | 89.6% (122) | 136 TCF sites supporting revocation | 2024–2025 | [1Kancherla, Gayatri Priyadarsini; Bielova, Nataliia; Santos, Cristiana; Bichhawat, Abhishek (2025): "Johnny Can't Revoke Consent Either: Measuring Compliance of Consent Revocation on the Web", in: Proceedings on Privacy Enhancing Technologies. (DOI)] |
Positive consent via __tcfapi after revocation | 12.5% (17) | 136 TCF sites supporting revocation | 2024–2025 | [1Kancherla, Gayatri Priyadarsini; Bielova, Nataliia; Santos, Cristiana; Bichhawat, Abhishek (2025): "Johnny Can't Revoke Consent Either: Measuring Compliance of Consent Revocation on the Web", in: Proceedings on Privacy Enhancing Technologies. (DOI)] |
| Third parties told of acceptance, not of revocation | 74.2% (101)10) | 136 TCF sites supporting revocation | 2024–2025 | [1Kancherla, Gayatri Priyadarsini; Bielova, Nataliia; Santos, Cristiana; Bichhawat, Abhishek (2025): "Johnny Can't Revoke Consent Either: Measuring Compliance of Consent Revocation on the Web", in: Proceedings on Privacy Enhancing Technologies. (DOI)] |
| Apps storing a choice only when it is accept | 2.6% (15) | 576 TCF apps | 2025 | [4Morel, Victor; Santos, Cristiana; Carlsson, Pontus; Ahlinder, Joel; Duvignau, Romaric (2026): "The TCF doesn't really A(A)ID - Automatic Privacy Analysis and Legal Compliance of TCF-based Android Applications", Proceedings on Privacy Enhancing Technologies 2026(3). (DOI)] |
| Apps sending the advertising ID during banner interaction, before consent | 55.3% (284) | 513 apps in the active-stage traffic analysis | 2025 | [4Morel, Victor; Santos, Cristiana; Carlsson, Pontus; Ahlinder, Joel; Duvignau, Romaric (2026): "The TCF doesn't really A(A)ID - Automatic Privacy Analysis and Legal Compliance of TCF-based Android Applications", Proceedings on Privacy Enhancing Technologies 2026(3). (DOI)] |
| Vendors on the GVL, by default, in one CMP's console | 751 companies | — (end of May 2021) | May 2021 | [7Toth, Michael; Bielova, Nataliia; Roca, Vincent (2022): "On dark patterns and manipulation of website publishers by CMPs", Proceedings on Privacy Enhancing Technologies 2022(3). (DOI)] |
TCF-MENTION and TCF-CANDIDATE come from a regex over paper.cols.txt with hyphenation joined and whitespace collapsed, not from any schema field. The regex and both counts are in scripts/tcf_fulltext_probe.mjs.TCF-MENTION (77) is used only where the question is “who mentions it”, never “who measures it”. The audit is scripts/tcf_core_audit.mjs and its evidence output is on the provenance page.paper.cols.txt splices a “future studies could…” sentence into the middle of the one that matters. In paper.norm.txt the sentence reads that the authors reconstruct prior work's website selection “using a combination of the Consent-O-Matic CMP detection module and IAB Europe's Transparency & Consent Framework's API”. It is detects only. Read a second rendering before excluding a paper.ATP returned 26 of which 23 were other expansions of the acronym. The published number, 3, comes from reading every match in context by hand. Every rejected match is printed in scripts/tcf_ac_probe-output.txt.scripts/tcf_quotecheck.mjs: 36 of 36 located, over 10 papers. Seven initially failed and were replaced with shorter contiguous spans after inspection — column-splicing in the PDF rendering, not misquotation. The list grew from 30 to 36 during review, which is itself worth knowing: a quote checker only checks the quotes you put in it.population.n recorded for [5Koch, Simon; Altpeter, Benjamin; Johns, Martin (2023): "The OK Is Not Enough: A Large Scale Study of Consent Dialogs in Smartphone Applications", in: Proceedings of the USENIX Security Symposium. (Link)] is 3,006; the 4.0% figure's denominator is the 3,654 apps the paper says it analysed. Read the denominator in the paper, not in the schema.scripts/tcf_external_checks.sh; the values on this page are that script's output on 2026-08-26 and will drift.Whatever else your methods section says, a TCF result needs these. The list is assembled from the decisions the four TC-string papers in this corpus had to explain in their own methods sections, plus the places where this page found two defensible readings of the same string. It is a checklist, not a measured reporting gap: nobody has surveyed how often each item is omitted.
localStorage, GET, POST, response bodies, app preferences — and which you did not.gdprApplies distribution rather than an assumption about it.__tcfapi — timeout length, and whether a timeout is its own outcome or folded into “no TCF”.PublisherCC actually set? Three of four strings in an eight-site probe reported the crawler's country rather than the publisher's establishment. The spec permits both readings, so the question is empirical: crawl the same TCF sites from several countries and see whether the field moves with the vantage point, with the publisher, or with neither. That is an anecdote here; the multi-vantage version of it is a paper, and it decides whether PublisherCC can be used to build a publisher-jurisdiction variable at all.scripts/tcf_external_checks.sh. @iabtcf/core has 91 published versions ending at 1.5.6; @iabtechlabtcf/core has 16, from 1.5.7 to 1.5.21. Neither dist-tags.latest is marked deprecated.github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework, TCFv2/ directory, and support.google.com/admanager/answer/9681920. Both fetched and quoted from on 2026-08-26.paper.cols.txt — the extraction failed on ten. Shares joined to the extraction use 5,859; the regex probes run over 5,869 and say so where they appear.population.n = 3006 for this paper; its own text says “We were able to analyze 3654 apps”, and 3,654 is the denominator behind its 4.0% figure. The paper's number is used.population.n = 5067, the number of apps scraped from the Play Store; 585 failed to download, and 4,482 is the denominator behind the paper's 12.85% figure.consensu.org cookie were deprecated in 2021.