TCF 2.3 Disclosed Vendors Segment: What It Contains and How to Read It From a TC String

Contents
The disclosed vendors segment of a TC string reports which vendors the Consent Management Platform (CMP) says were disclosed in its interface. The transition to TCF 2.3 made this previously optional segment mandatory for newly generated strings. Disclosure is neither consent nor independent proof that the banner was displayed correctly.
The Core always comes first. Segment types identify the remaining parts, so Disclosed Vendors does not have to occupy the second position. An optional PublisherTC segment may appear before or after it. This article covers the structure made mandatory with 2.3; the current specification also contains later changes.

The ambiguity addressed by the change
The change particularly concerns vendors declaring Special Purposes alongside Purposes based on legitimate interest. Previously, a zero in the vendor legitimate-interest section could mean either missing disclosure or an exercised objection. Separate disclosure information distinguishes those cases. It does not grant blanket permission for every purpose declared by a vendor.
The segment is the CMP’s statement about disclosure. An incorrect CMP can also set an incorrect value. Verification of the interface, vendor information, stored choices and transmitted signals remains necessary. Making the field mandatory does not automatically prevent false disclosure claims.
Structure: bit field or range list
Additional segments begin with three type bits. Disclosed Vendors has type 1, binary 001; PublisherTC has type 3. The Core does not start with a separate three-bit type field. Its first field is the six-bit encoding version, currently 2. That number is not the framework version “2.3”.
SegmentType 3 bits 001 = DisclosedVendors
MaxVendorId (M) 16 bits
IsRangeEncoding 1 bit 0 = BitField, 1 = Range
BitField: M bits, IDs 1..M
Range: NumEntries (12 bits), then entries:
IsARange 1 bit
StartOrOnlyVendorId 16 bits
EndVendorId 16 bits (only for a range)
BitField: 20 + M bits
Range: 32 + 17*S + 33*R bitsMaxVendorId is the upper ID boundary represented in the segment, not the number of disclosed vendors. The first bit in the bit field represents ID 1. A set bit signals disclosure; an unset bit provides no such disclosure signal. Range endpoints are inclusive, while a single ID has no end field.
In the formula, S counts single-ID entries and R counts actual ranges. The totals include the segment header but exclude padding and text encoding. The specification recommends the smaller representation. However, a scattered set does not automatically favour a bit field: {1, 1200} takes 1,220 bits as a bit field but only 66 bits as two single-ID entries. Dense sets can favour the bit field instead.
The deadline and Google error 1.4
TCF 2.3 was released on 19 June 2025. The transition ended at the end of February 2026; Google’s current integration guidance specifies 1 March 2026 as the requirement date for newly generated strings. Older stored strings do not become universally invalid retroactively. The applicable transition rules and other validity requirements still matter.
Google describes code 1.4 for a missing or unprocessable disclosed vendors segment, or for Google not being disclosed. Google Advertising Products has vendor ID 755. A disclosure bit replaces neither other required signals nor actual disclosure. Adding a missing Google bit without the corresponding disclosure is therefore not a valid repair.
Google’s announcement states that affected requests may receive limited ads or be dropped. That does not imply a fixed revenue impact. Current help pages place TCF error reporting in the Policy center; the issue is not necessarily silent or impossible to diagnose.
Reading the actual string
A complete string without dots contains no additional segment. Conversely, dots alone do not demonstrate a correct disclosed vendors segment. Type, successful decoding and content matter. An unknown or obsolete additional type must not simply be interpreted as PublisherTC.
The following local JavaScript module uses @iabtechlabtcf/core, tested with version 1.5.22. After installation of that package version in a local test project, the function accepts the complete TC string obtained from the actual integration. It reads data without changing CMP storage or choices.
import { TCString } from "@iabtechlabtcf/core";
export function inspectDisclosure(tcString) {
if (typeof tcString !== "string" ||
!/^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)*$/.test(tcString)) {
throw new Error("Invalid segment syntax");
}
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
const segments = tcString.split(".");
if (alphabet.indexOf(segments[0][0]) !== 2) {
throw new Error("Expected encoding version 2");
}
const types = segments.slice(1).map(s => alphabet.indexOf(s[0]) >> 3);
if (types.some(type => type !== 1 && type !== 3) ||
new Set(types).size !== types.length) {
throw new Error("Unsupported or duplicate segment type");
}
const model = TCString.decode(tcString);
const present = types.includes(1);
return {
segmentPresent: present,
disclosedVendorIds: present ? [...model.vendorsDisclosed.values()].sort((a, b) => a - b) : null,
googleDisclosed: present ? model.vendorsDisclosed.has(755) : null,
encodingVersion: model.version,
policyVersion: model.policyVersion
};
}segmentPresent distinguishes a missing disclosure segment from a present segment without the relevant ID. Here, null means a missing segment, not a confirmed rejection. disclosedVendorIds lists the IDs encoded as disclosed; names come from the Global Vendor List corresponding to the string.
The code checks some structural errors and decodes the content. Its result is not a complete TCF, legal-basis or interface assessment. An outdated policy value can also be decoded. Verification includes fresh and stored choices, the CMP version actually loaded and the string received downstream.
Questions and answers
Does a CMP have to ask again after updating?
Not solely because of this transition. IAB guidance permits existing strings to be supplemented from previously recorded disclosure information without changing lastUpdated. Without those historical records, vendors must not be invented as having been shown. The new string is then created when choices are subsequently renewed or changed. A current software version alone does not establish migration of every stored value.
Can string length become a problem?
Yes, depending on storage and recipient limits. The complete text length across all segments and the actual transport matter. A smaller bit representation reduces length without eliminating every limit. A sample demonstrates only the tested case; large vendor lists and other configurations need separate tests.
Does successful decoding prove a correct interface?
No. The string records the generated signal. Comparison with displayed information, choices and actual onward transmission is separate. The CMP dashboard, embedded code and stored string may be at different update stages.
Sources
- IAB Europe: Transition to TCF v2.3
- Google Ad Manager: Publisher integration with the IAB Europe TCF
- Google AdSense: Transition to IAB TCF v2.3
- Google AdSense: Publisher integration and transition deadline
- Google AdSense: TCF implementation errors and code 1.4
- IAB Tech Lab: TC string and vendor list format
- IAB Tech Lab: Core encoder and decoder library