Open-source conformance tooling for digital advertising specifications.

Digital advertising fails without throwing: a tag that bills and renders nothing, identifiers in a pixel nobody reviewed, a payload that cannot be told from fraud, an agent that transacts with nothing checking it. IAB Tech Lab and AAO specifications cover some of that. The rest is outside the PDF. The work here is open-source tools and measurements for those failures, including the places the documents do not reach.

38,971 installs7 distribution channelsApache 2.0, free forever
Where the tools sit
OPENRTB BID REQUESTSSPRTBlint source on GitHubRTBlintDSPVAST AD TAGDSPVASTlint source on GitHubVASTlintPlayerPIXEL / CAPIAd opsPixellint source on GitHubPixellintVendor

Every arrow is a boundary between two companies. RTBlint and VASTlint sit on the payload as it crosses. Pixellint sits on the measurement artifact before it fires. Each box links to the source that does it.

The failures

They never throw, which is why they persist.

The specifications exist and are public. What is missing is a check at the moment a payload crosses between two companies. Some of that check is in the IAB Tech Lab and AAO documents. A lot of it is not. That gap is where revenue leaks, where user data travels unreviewed, where fraud becomes indistinguishable from error, and where autonomous systems now transact with nothing verifying them. Every tool here is free, auditable, cites the document behind each finding, and is built to run inside that gap.

Revenue integrity

A tag that fails renders nothing and still bills. The rules that catch it are the unglamorous ones: a missing impression element, a duplicate one that double-counts, a media file on plain HTTP that secure inventory blocks, quartile tracking nobody wired so measurement receives no signal at all.

VAST-2.0-inline-impressionVAST-2.0-duplicate-impressionVAST-2.0-linear-tracking-quartiles

User data and privacy

Tracking URLs are where identifiers actually travel, and they are the least reviewed artifact in the chain. Pixellint flags raw email addresses sent where the vendor requires SHA-256 hashing, credentials embedded in a URL, macros fired unexpanded to a third party, and any tracker still riding plaintext HTTP.

vendor.meta.pii.unhashed_emailcore.url.userinfo_deprecatedcore.macro.unexpanded_in_fired_url

Verifiability and fraud

A malformed payload and a fraudulent one look identical to everything downstream, because both are unverifiable. These tools do not detect fraud. They remove the ambiguity fraud hides in, by checking that the verification resources meant to catch it are present, correctly declared, and reachable.

VAST-4.1-verification-vendorVAST-4.1-verification-no-resourceVAST-4.1-js-resource-https

Agentic accountability

Buying is moving to agents on both sides of the transaction, with no human reading a validator UI in between. Every tool ships an MCP server so an agent can check its own output deterministically, and VASTlint implements AdCP 3.0 governance so a pipeline can declare and enforce content standards rather than assume them.

get_adcp_capabilitiescalibrate_contentvalidate_content_delivery

Each chip is a real rule or tool id you can look up in the catalog. Nothing on this page describes something that is not shipping.

Research

The measurements behind the tools.

Five preprints. Four ask what the documents leave open: how much of OpenRTB any validator can enforce, what header-bidding traffic actually sends, whether structural VAST validation is cheap enough for a live bid path, and how much of IAB privacy signaling a receiver can check. The fifth measures the CTV verification architecture that makes fraud cheap to run. Datasets and code are published with them.

Preprint, ResearchGate · August 2026

Why CTV Ad Fraud Keeps Working

91.5% of pricing-relevant claims a buyer receives about a CTV server-side impression are self-declared, against 70.0% for the same claims on web display; no scored OpenRTB field on either path is attested

Preprint, ResearchGate · August 2026

Measuring OpenRTB Dialects in Client-Side Header Bidding

42.0% of bid requests on a random header-bidding sample are flagged on type, enumerated-value, or required-field checks, 95% CI [36.0, 47.2]; major publishers sit at 40.4% [35.8, 45.0]; the intervals overlap

Preprint, ResearchGate · July 2026

How Machine-Checkable Is OpenRTB?

417 normative sentences extracted from OpenRTB 2.6-202606 and 3.0, screened to 288 conformance statements and hand-coded into four enforceability classes

Preprint, ResearchGate · April 2026

VAST XML Validation at Bid-Time Scale

A 17 KB CTV tag validates in 350 microseconds, 0.35% of a 100 ms bid window; a 44 KB tag in 2.1 ms, inside a typical creative-selection budget

The tools

One check per failure. Watch what it stops.

Each panel is a different artifact. Bid JSON, a wrapper chain into a CTV slot, a network request that has not fired yet. Without a check the failure is silent. With the validator it has a rule id.

RTBlint · Bid
v0.5.0

The auction is lost. Nobody is told.

A bid request with a protobuf boolean where the OpenRTB JSON snapshot wants 0 or 1 does not throw. The DSP drops it. Fill from that request is gone. RTBlint grades the payload against the spec revision the partner is on, before it enters the auction.

bid_request.jsonOpenRTB 2.6-202606
auctionimp[0] · CTV video
Bids received
0not sent
Time in auction
120 ms · timed outnever entered
Winning CPM
nonenone
DSP log
no error · no bidrequest not forwarded
Without a check
Dropped at the DSP. No error on either side.
No findingNothing threw. The DSP log looks like a request that never existed.
VASTlint · Creative
v0.9.1

The slot billed. Nothing played.

A wrapper chain that dies on an HTTP media file still counts an impression. The player reports nothing useful. VASTlint walks the chain at intake, names the hop, and the deterministic HTTPS fixes apply in one pass, before the tag is trafficked.

  1. 0IntakeVASTlintidleVAST-2.0-mediafile-https
  2. 1Wrapperdsp.example/vast.xmlresolvednot fetched
  3. 2Wrapperadn.example/redirresolvednot fetched
  4. 3InlineMediaFile http://cdn.example/ad.mp4HTTP · blocked by playernever reached
Impression billedNot trafficked
CTV slot · 1920×1080
Without a check
Blank slot. Impression already billed.
No findingThe player billed the impression. The screen stayed black.
Pixellint · Measurement
Early

The pixel returned 200. The conversion did not.

A misspelled event name or a raw email in a tracker looks healthy in the network panel. Pixellint checks the URL against the vendor's own docs before it fires, while the tag is still in ad ops, not after attribution has already failed.

Networkthis request · before the player
GETfacebook.com/trgif200blocked184 msnot sent
0
200 ms
QueryValueVendor contract
id14288931ok
evPurchaseok
emunhashedsent in the clearmust be SHA-256
HTTP200 OKnever left ad ops
Conversions00 · not fired
Without a check
HTTP 200. Conversion missing. Identifier sent in the clear.
No findingThe vendor accepted the request. Attribution did not.
Use it in the browser

VASTlint and RTBlint run in the browser.

No install, no account, no key. Paste a payload and it grades against the same engine the CLI and the MCP server run. Pixellint is CLI and local MCP while it is early.

Adoption

Published, installed, and in use.

Every figure below was read from a public registry API and can be checked against the same endpoint today. None of it is estimated, projected, or rounded up.

38,971
package installs across every published channel, as of 2026-08-26
Packages published
18
Distribution channels
7
Cost to use
$0
npmdownloads
15,556
crates.iodownloads
9,307
RubyGemsdownloads
3,859
PyPIdownloads
3,538
Docker Hubimage pulls
3,435
GitHub releasesbinary downloads
2,760
VS Code Marketplaceinstalls
516
08,00016,000
Show the per-package numbers
ChannelPackageCount
npmvastlint13,220
npmrtblint-core1,857
npmpixellint479
RubyGemsvastlint3,859
crates.iovastlint-core5,913
crates.iovastlint-cli1,392
crates.iortblint-core548
crates.iortblint285
crates.iortblint-mcp282
crates.iopixellint-core401
crates.iopixellint241
crates.iopixellint-mcp245
Docker Hubaleksuix/vastlint3,435
GitHub releasesvastlint2,474
GitHub releasespixellint1
GitHub releasesvastlint-erlang285
PyPIvastlint3,538
VS Code Marketplacealeksuix.vastlint516
Total38,971

How these are counted. Read straight from each registry’s public API on 2026-08-26. Nothing is estimated or projected. crates.io and RubyGems report lifetime downloads. npm has no lifetime endpoint, so that figure sums the daily range API from each package’s first publish date. PyPI uses the without_mirrors series, which excludes mirror traffic and is the smaller of the two figures available. Registries count machines, not people, so treat this as reach, not headcount.

AI and agents

A check the agent can call in its own loop.

An agent that assembles a campaign needs a deterministic verdict, not a screenshot of a validator UI. Every tool here ships an MCP server for that. 20 callable tools, structured JSON, no account.

AI agentClaude · Cursor · CI botMCPJSON-RPCtool callRTBlint source on GitHubRTBlint3 tools · BidVASTlint source on GitHubVASTlint14 tools · CreativePixellint source on GitHubPixellint3 tools · Measurement

Findings come back as structured JSON: a stable rule id, a severity, the line it came from, and fix guidance. An agent can act on that. It cannot act on a screenshot of a validator UI. Each server links to its source.

{
  "mcpServers": {
    "vastlint":   { "type": "http", "url": "https://vastlint.org/mcp" },
    "rtblint":    { "type": "http", "url": "https://rtblint.org/mcp" },
    "pixellint":  { "command": "pixellint-mcp" }
  }
}
Standards

What the bodies publish, and what they do not.

IAB Tech Lab and AAO specifications define part of the bid, the tag, and the pixel. Implementing those documents closely is one job. Measuring the failures they do not name is the other.

IAB Tech Lab specifications

The specs that define how a bid, a creative, and a measurement event are structured. Every rule in the catalog names the document it came from.

  • OpenRTB 2.0 through 3.0, including eight dated 2.6 snapshots
  • VAST 2.0 through 4.4, plus VMAP, DAAST, and SIMID
  • OMID verification checks and VPAID deprecation detection

Agentic advertising and AdCP

The Ad Context Protocol defines how agents negotiate and transact advertising. Validation is the part that keeps an autonomous pipeline honest.

  • AdCP 3.0 capability discovery over MCP
  • Content standards governance with pre-flight calibration
  • Idempotent tool calls with replay protection

Contributing back upstream.

Implementing a specification closely enough to validate it surfaces the places where the specification itself is wrong, ambiguous, or untested. Those findings go back to the people who maintain it, as patches to the specs and their reference implementations.

Sets the technical standards the open advertising supply chain runs on, including OpenRTB, VAST, VMAP, and the agentic bidding framework.
Participant in the Advanced TV Working Group, and an active contributor to the reference implementations and testing tools on GitHub.
See the contributions on GitHub
Maintains the Ad Context Protocol, which defines how AI agents discover each other's capabilities and transact advertising.
Certified AdCP Practitioner and Governance Specialist, and an active contributor to the protocol specification on GitHub.
See the contributions on GitHub
How it is built

The same three commitments in every tool.

Every rule cites a source

A finding names the spec section, the XSD, the RFC, or the documented revenue impact behind it. If a rule cannot cite something, it does not ship. That is what makes a result arguable with a partner instead of just an opinion.

One engine, every runtime

A single Rust core compiles to a CLI, a WASM module, a native library, and language bindings. Your CI, your browser, your BEAM service, and your agent all get identical verdicts, because they run identical code.

Free, and staying that way

Apache 2.0, with a written commitment: no paid tier that hides rules, no cloud version that requires an account, no rate limits, no telemetry without opt-in. Validation infrastructure only works if everyone can run it.