Guides

How to validate an OpenRTB bid request

Paste the request into the bid request tester or run rtblint validate request.json. Either way you get the same findings: parse errors, missing required fields, type mismatches, unknown or moved fields, and enum values the spec does not document. This guide walks through both paths and shows how to read the output.

What validation catches

An OpenRTB bid request is one JSON object, and most of the ways it goes wrong are mechanical. A validator checks the payload against a tracked snapshot of the spec and reports, in rough order of severity:

  • Malformed JSON. The payload does not parse, or parses to something other than a single object at the root. Nothing else can be checked until this is fixed.
  • Missing required fields. OpenRTB 2.6 requires id (the request ID) and imp with at least one Imp object. Each Imp in turn needs its own id.
  • Type mismatches. at is an integer (auction type, default 2), not the string "2". tmax is an integer of milliseconds. imp[].bidfloor is a float.
  • Unknown fields. A key the selected version does not define, usually a typo like bidflor or an exchange-specific field placed outside ext.
  • Deprecated and moved paths. imp.video.placement was deprecated in favor of plcmt in the 2.6-202303 update, and regs.ext.gdpr became regs.gdpr in 2.6. See placement vs plcmt for the first case.
  • Out-of-range enum values. Since 2.6 the enumerated lists live in AdCOM 1.0. at allows 1, 2, or exchange-specific values of 500 and above; a bare 9 is invalid. The enums reference collects the lists that matter for requests.

Validate in the browser

  1. Open the bid request tester. It is the rtblint Rust core compiled to WebAssembly, so validation runs entirely client-side and the payload never leaves your browser.
  2. Paste the bid request JSON, or start from the built-in sample.
  3. Pick the spec snapshot to validate against. The default is the latest tracked 2.6 release (2.6-202505); older snapshots exist because behavior changed between them, as the version reference documents.
  4. Read the findings list. Errors mean the request violates the spec; warnings mean it parses but carries something deprecated or inadvisable.

Validate with the CLI

The same core ships as a Rust CLI:

cargo install rtblint

# validate a file
rtblint validate request.json

# validate from a pipe
cat request.json | rtblint validate --stdin

# pin a spec snapshot
rtblint validate request.json --version 2.6-202505

# machine-readable output
rtblint validate request.json --format json

The exit code is 0 when the request is valid (warnings allowed), 1 when it has errors, and 2 on usage or I/O problems, so it drops straight into scripts. See OpenRTB validation in CI for a GitHub Actions setup and the CLI docs for the library API.

Reading a finding

Every finding has three load-bearing parts:

  • Rule ID, such as openrtb.field.moved: a stable name for the class of problem, suitable for grepping or gating. The rule catalog lists them all.
  • JSON path, such as imp[0].video.placement: exactly where in the payload the problem sits.
  • Severity: error (spec violation) or warning (legal but deprecated or risky).

A worked example

This request has three problems that show up constantly in the wild:

{
  "id": "req-83f1",
  "at": "2",
  "imp": [
    {
      "id": "1",
      "video": { "mimes": ["video/mp4"], "placement": 1 }
    }
  ],
  "regs": { "ext": { "gdpr": 1 } }
}

rtblint reports, against 2.6-202505:

FAILED (OpenRTB 2.6-202505): 2 error(s), 1 warning(s).
- [error] at: at expects integer but received string.
  (openrtb.type.mismatch)
- [warning] imp[0].video.placement: imp.video.placement is
  deprecated in OpenRTB 2.6-202505. (openrtb.field.deprecated)
- [error] regs.ext.gdpr: regs.ext.gdpr moved in OpenRTB
  2.6-202505; use regs.gdpr. (openrtb.field.moved)

The fixes: send "at": 2 as an integer, replace placement with plcmt, and move the GDPR flag to regs.gdpr. Requests like this often still get parsed by lenient bidders, which is exactly why the mistakes survive: they fail selectively, on the partners that enforce types, and those partners simply stop bidding.

FAQ

What makes an OpenRTB bid request invalid?

Anything that breaks the published spec: JSON that does not parse, a root that is not a single object, a missing required field (id, or the imp array with at least one Imp object), a wrong type such as at sent as a string, a field at a path the selected version does not define, or a value outside a documented enum such as at = 9.

Can I validate a bid request without uploading it anywhere?

Yes. The rtblint tester runs the validator as WebAssembly in your browser. The payload is parsed client-side and never leaves the page, so production requests with user data are safe to paste.

Which OpenRTB versions can I validate against?

Rule depth is richest on the OpenRTB 2.6 snapshots (2.6-202204 through 2.6-202505). Object catalogs for undefined-field and type checks cover 2.0 through 3.0.

Validate it

Paste a request into the bid request tester to see these checks run live, client-side. For repeatable checks, cargo install rtblint and wire rtblint validate into your pipeline. The full list of what runs is in what rtblint checks.