PHPackages                             azerion/iab-tcf-v2 - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. azerion/iab-tcf-v2

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

azerion/iab-tcf-v2
==================

IAB TCF v2.x consent string decoder and encoder for PHP.

v1.0.0(1mo ago)02Apache-2.0PHPPHP ^8.3CI passing

Since May 29Pushed 1w agoCompare

[ Source](https://github.com/azerion/php-iab-tcf-v2)[ Packagist](https://packagist.org/packages/azerion/iab-tcf-v2)[ Docs](https://github.com/azerion/php-iab-tcf-v2)[ RSS](/packages/azerion-iab-tcf-v2/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (3)Versions (4)Used By (0)

azerion/iab-tcf-v2
==================

[](#azerioniab-tcf-v2)

[![CI](https://github.com/azerion/php-iab-tcf-v2/actions/workflows/ci.yml/badge.svg)](https://github.com/azerion/php-iab-tcf-v2/actions/workflows/ci.yml)[![License: Apache 2.0](https://camo.githubusercontent.com/5b60841bea9e11d9d0b0950d690c9bc554e06385634056a7d5d62a15d1a4eabe/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4170616368655f322e302d626c75652e737667)](LICENSE)

A clean, dependency-free PHP library for **decoding and encoding** [IAB TCF v2.x](https://iabeurope.eu/iab-europe-transparency-consent-framework-policies/) consent strings (v2.0, v2.1, v2.2, v2.3).

- PHP **8.3+**, immutable value objects, fully typed, PHPStan level max.
- **All TCF v2.x policy versions** accepted. `version` must be `2`; `tcfPolicyVersion` is read as-is.
- **No GVL support** — this library is purely a string encoder/decoder. Bring your own Global Vendor List if you need it.
- Public API is just three types: `TCString`, `TCModel`, and the `PublisherTC` / `PublisherRestriction` value objects.

Installation
------------

[](#installation)

```
composer require azerion/iab-tcf-v2
```

Decode
------

[](#decode)

```
use Azerion\IabTcf\V2\TCString;
use Azerion\IabTcf\V2\TcfException;

try {
    $model = TCString::decode($_COOKIE['euconsent-v2']);
} catch (TcfException $e) {
    // Malformed string, invalid bit layout, etc.
    error_log("TCF decode failed: {$e->getMessage()}");
    return;
}

if (in_array(1, $model->purposesConsent, true)) {
    // User consented to Purpose 1 ("Store and/or access information on a device")
}

if (in_array(755, $model->vendorsConsent, true)) {
    // User consented to vendor 755 (Google)
}
```

Encode
------

[](#encode)

```
use Azerion\IabTcf\V2\TCModel;
use Azerion\IabTcf\V2\TCString;

$model = new TCModel(
    cmpId: 42,
    cmpVersion: 1,
    consentLanguage: 'EN',
    vendorListVersion: 200,
    isServiceSpecific: true,
    purposesConsent: [1, 2, 3],
    vendorsConsent: [1, 755, 1024],
    publisherCC: 'NL',
    disclosedVendors: [1, 755, 1024],
);

$consentString = TCString::encode($model);
// e.g. "CQ...A.YA...A"
```

Field validation runs in the `TCModel` constructor — IDs out of range, invalid language codes, or `version !== 2` will throw `TcfException` immediately.

Field reference
---------------

[](#field-reference)

The library's property names match the spec field names converted to camelCase.

Spec field`TCModel` propertyTypeVersion`version``int` (always 2)Created`created``DateTimeImmutable`LastUpdated`lastUpdated``DateTimeImmutable`CmpId`cmpId``int` (0..4095)CmpVersion`cmpVersion``int` (0..4095)ConsentScreen`consentScreen``int` (0..63)ConsentLanguage`consentLanguage``string` (ISO 639-1, e.g. `EN`)VendorListVersion`vendorListVersion``int` (0..4095)TcfPolicyVersion`tcfPolicyVersion``int` (2 = v2.0, 3 = v2.1, 4 = v2.2, 5 = v2.3)IsServiceSpecific`isServiceSpecific``bool`UseNonStandardStacks`useNonStandardStacks``bool` (a.k.a. `UseNonStandardTexts` in v2.3 docs)SpecialFeatureOptIns`specialFeatureOptIns``list` (1..12)PurposesConsent`purposesConsent``list` (1..24)PurposesLITransparency`purposesLITransparency``list` (1..24)PurposeOneTreatment`purposeOneTreatment``bool`PublisherCC`publisherCC``string` (ISO 3166-1 alpha-2)VendorsConsent`vendorsConsent``list`VendorsLegitimateInterest`vendorsLegitimateInterest``list`PublisherRestrictions`publisherRestrictions``list`DisclosedVendors (segment)`disclosedVendors``list` (mandatory in v2.3, optional in v2.0-2.2)AllowedVendors (segment)`allowedVendors``?list` (null = absent)PublisherTC (segment)`publisherTC``?PublisherTC`### `PublisherRestriction`

[](#publisherrestriction)

```
final readonly class PublisherRestriction
{
    public int $purposeId;                       // 1..24
    public RestrictionType $restrictionType;     // NotAllowed | RequireConsent | RequireLegitimateInterest
    public array $vendorIds;                     // list
}
```

### `PublisherTC`

[](#publishertc)

```
final readonly class PublisherTC
{
    public array $pubPurposesConsent;             // list, ids 1..24
    public array $pubPurposesLITransparency;      // list, ids 1..24
    public int $numCustomPurposes;                // 0..63
    public array $customPurposesConsent;          // list, ids 1..numCustomPurposes
    public array $customPurposesLITransparency;   // list, ids 1..numCustomPurposes
}
```

Design notes
------------

[](#design-notes)

- **Re-encoding is not guaranteed to be bit-identical** to the input string. The encoder always picks the smallest representation (bitfield vs. range) per vendor segment, which may differ from the choice the original CMP made. Decoding then re-encoding will produce an equivalent *model*, not necessarily an equivalent *string*.
- **`maxVendorId` and `isRangeEncoding` are never on the model.** They are computed at encode time from the data.
- **Lenient decode, strict encode.** The decoder accepts whatever well-formed bits it sees; the encoder validates aggressively via the `TCModel` constructor.
- **No GVL.** Decoding does not require a Global Vendor List. If you need to look up vendor names or display purposes, fetch the GVL yourself from `https://vendor-list.consensu.org/v3/vendor-list.json` and join on the IDs.
- **Spec scope.** All TCF v2.x policy versions are supported (v2.0 through v2.3). TCF v1.x is **not** supported — `version !== 2` will throw on decode.
- **The `useNonStandardStacks` field** is the original IAB spec name. The v2.3 documentation renamed it to `UseNonStandardTexts`, but the bit position and semantics are identical.

Versioning
----------

[](#versioning)

Semantic versioning. Until `1.0.0`, expect minor versions to contain breaking changes.

License
-------

[](#license)

[Apache-2.0](LICENSE) © Azerion.

Spec references
---------------

[](#spec-references)

- [IAB Tech Lab — Consent string and vendor list formats v2](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20Consent%20string%20and%20vendor%20list%20formats%20v2.md)
- [IAB Europe — TCF v2.3 announcement](https://iabeurope.eu/all-you-need-to-know-about-the-transition-to-tcf-v2-3/)
- [iabtcf-es](https://github.com/InteractiveAdvertisingBureau/iabtcf-es) — the reference TypeScript implementation this library is structurally modelled after.

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance94

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 86.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

56d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/3883477?v=4)[Ale Bles](/maintainers/AleBles)[@AleBles](https://github.com/AleBles)

---

Top Contributors

[![AleBles](https://avatars.githubusercontent.com/u/3883477?v=4)](https://github.com/AleBles "AleBles (13 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (2 commits)")

---

Tags

gdprconsentiabconsent stringTCFtcf-v2

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/azerion-iab-tcf-v2/health.svg)

```
[![Health](https://phpackages.com/badges/azerion-iab-tcf-v2/health.svg)](https://phpackages.com/packages/azerion-iab-tcf-v2)
```

###  Alternatives

[statikbe/laravel-cookie-consent

Cookie consent modal for EU

219426.2k](/packages/statikbe-laravel-cookie-consent)[codingfreaks/cf-cookiemanager

Manage cookies, scripts, and GDPR compliance on your Typo3 website with CodingFreaks Typo3 Cookie Manager. Customize cookie banners, streamline workflow, and enhance user experience. Ensure GDPR compliance and take control of cookie management with our Typo3 cookie management extension. Visit the official Typo3 Documentation page to learn more.

1830.7k](/packages/codingfreaks-cf-cookiemanager)[bramdeleeuw/cookieconsent

GDPR compliant cookie bar and consent checker

1511.7k2](/packages/bramdeleeuw-cookieconsent)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
