How to read the OpenRTB specification

OpenRTB is a set of documents, and most confusion comes from reading the wrong one. The current 2.6 spec is a Markdown file with dated releases, versions 2.0 to 2.5 are PDFs, 3.0 is a separate specification, the enumerated lists live in AdCOM, and the usage guidance sits in an implementation guide. This page explains which document answers which question and how to read the object tables once you are there.

Which document answers which question

Start from the question, not the version number. Each kind of question has one authoritative place to look.

Your questionRead this
What does a field mean in current 2.6?2.6.md in the openrtb2.x repository, at the dated release your partner runs
Which integer values can a 2.6 field take?The list named in the field's description, in AdCOM 1.0
How should a field be used in practice?The implementation guide, numbered as section 7 of 2.6
What does an nbr or loss reason code mean?The two lists in the OpenRTB 3.0 document, which 2.6 points to
What did a release add or deprecate?The openrtb2.x releases page, which holds the change notes from 2.6-202303 onward
What does a partner on 2.5 or earlier send?That version's PDF, linked from IAB Tech Lab's OpenRTB page
What does an exchange-specific field mean?The exchange's own documentation, since ext is undefined by the spec

Branches, release tags, protobuf files, and community extensions are all mapped in where is the OpenRTB spec.

How each version is laid out

The layout changed twice, so a section number that is right for one version is wrong for another. Cite objects by name and give the version with every citation.

VersionFormatObjectsEnumerated listsTable columns
2.0, 2.1, 2.2PDFSection 3.3 (bid request object is 3.3.1)Section 6 of the same PDFField, Scope, Type, Default, Description
2.3, 2.3.1, 2.4, 2.5PDFSection 3.2 for the request, 4.2 for the responseSection 5 of the same PDFAttribute, Type, Description
2.6 dated releasesMarkdown on GitHubSection 3.2 for the request, 4.2 for the responseAdCOM 1.0Attribute, Type, Description
3.0Markdown on GitHubTransport objects only; media and context come from AdCOMAdCOM 1.0, plus the no-bid and loss listsAttribute, Type, Definition

In 2.0 to 2.2 the scope and the default had their own columns. From 2.3 on, both moved into the Type cell, so a single cell reads integer; default 2 or string; required. The PDFs of 2.0 to 2.3.1 open with an integration checklist of questions to settle with each partner. 2.6 dropped the checklist but still advises both sides to agree which fields the seller sends and which the buyer needs.

The 2.6 Markdown is easier to search, but read its cross-references with care. Some prose points at the wrong section number, for example macros cited as 4.5 while the macro table is section 4.4. When a reference looks wrong, navigate by the object or heading name. OpenRTB 3.0 is a different protocol, not a newer 2.x, and the 2.6 vs 3.0 guide explains the split.

Reading an object table

Every object is one table: attribute name, a Type cell that carries the type plus its qualifiers, and a description. These rows from the 2.6 tables cover most of what you will meet.

AttributeType cellHow to read it
impobject array; requiredAt least one entry, or the request breaks the protocol.
siteobject; recommendedThe protocol works without it; buyers expect it for web inventory.
atinteger; default 2Absent means second price plus. A first-price exchange must send 1.
tmaxintegerNo default. Absent means the timeout agreed at integration applies.
imp.secureintegerAbsent means unknown; the description adds that plain HTTP can be assumed.
imp.bannerobjectRequired only when the impression is offered as a banner.
bid.apiinteger; DEPRECATEDStill defined, but replaced by bid.apis.

Required, recommended, and optional

Required means the transaction is technically impossible without the attribute. The list is short: id, imp, imp.id, at least one media object per impression, imp.video.mimes inside video, imp.native.request inside native, and on the response side BidResponse.id plus each bid's id, impid, and price. Required attributes sit at the top of each table.

Recommended comes next and means customary. The spec is careful to say this records a market norm, not advice to share any particular data. In practice, a request without the recommended objects is valid and still gets few bids. Everything without a qualifier is optional. Some rows carry a condition in the description instead, such as the media objects on Imp, which are required only for the formats on offer.

Defaults and absence

Leaving a field out has a defined meaning. If the Type cell names a default, an absent field equals that default: test 0, at 2, imp.bidfloor 0, imp.bidfloorcur USD, imp.instl 0, cattax 1, and BidResponse.cur USD. If there is no default, absence means unknown. Two habits follow. Never send null or an empty placeholder to mean unknown. And check the defaults you inherit by staying silent, because a seller that runs first-price auctions and omits at has told every bidder the opposite.

Types

Flags in 2.x are integers, 0 or 1, not JSON booleans. Prices are floats expressed as CPM, and the spec suggests integer or decimal arithmetic when handling currency. When a description names a list, the field takes integers from that list. One string field needs special care: imp.native.request holds a JSON document encoded as a string, not a nested object.

Deprecated, removed, and moved

A deprecated attribute stays in the table with DEPRECATED in its Type cell, and partners may keep sending it for years. A removed attribute vanishes from the tables of later versions, as the banner size ranges wmax and hmax did in 2.6. A moved attribute appears at its new path, and the change log marks it as formerly carried in ext: regs.gdpr, user.consent, and source.schain are the common cases. The 2.5 vs 2.6 guide lists them all.

The ext object

Any object may carry an ext object, and the spec leaves its contents undefined. The exchange that uses an extension is responsible for documenting it, so an unfamiliar key under ext sends you to that exchange's documentation, not to the spec. IAB Tech Lab hosts widely used extensions on GitHub, and several of them later became core fields.

Reading the AdCOM lists

Since 2.6, OpenRTB has no enumerated lists section of its own. A field description names a list, and the values live in AdCOM 1.0 under a heading of the form List: Device Types. Each list is a two-column table of value and definition. For device.devicetype, value 3 is Connected TV and 7 is Set Top Box. Many lists reserve 500 and above for vendor-specific values.

AdCOM lists grow without a new OpenRTB version, and the spec requires both sides to handle values they do not recognize without failing. Two traps are common. First, a list name in 2.5 does not always map to an AdCOM list: the 2.5 Video Placement Types list and the AdCOM list behind imp.video.plcmt define different categories, as the placement vs plcmt guide shows. Second, the no-bid and loss reason lists are not in AdCOM at all; they live in the 3.0 document. Every AdCOM list is browsable on the enumerated lists pages, for example device types.

Dated 2.6 releases

Since 2.6-202211 the version number changes only for breaking changes. Everything additive ships as a dated release of 2.6, tagged 2.6-YYYYMM. The spec describes a roughly monthly cadence; in practice releases have landed a few times a year. The tracked releases are 2.6-202204, 2.6-202210, 2.6-202211, 2.6-202303, 2.6-202309, 2.6-202402, 2.6-202409, 2.6-202501, 2.6-202505, and 2.6-202606.

This matters when you read a field. regs.gpp and regs.gpp_sid first appear in 2.6-202211, while acat and imp.video.durfloors arrive in 2.6-202309. A partner that says it runs 2.6 may be on any of these. The x-openrtb-version header will not tell you which, because it carries only the major and minor number. Ask for the release date, or infer it from the fields the partner actually sends.

The policy also sets expectations for both sides: send new fields and values when you support them, and tolerate ones you do not know. A parser that rejects an unknown field is out of step with the spec. Per-release notes are on the versions index, and the version diff tool lists what was added, deprecated, moved, or removed between any two releases.

The implementation guide

The object tables say what a field is. The implementation guide says how to use it. In the 2.6 repository it is a separate file, implementation.md, numbered as section 7. Its fourteen topics are no-bid signaling, impression expiration, PMP and direct deals, skippability, regulatory resources, pod bidding for video and audio, network and channel examples, counting billable events, digital out-of-home, updated video signals, floors, ID match methods, genres with gtax, and extended content identifiers.

Read it when the table cannot settle a question about behavior. When should burl fire? How long may an impression lag its auction? How do pod fields combine? Which plcmt value fits a muted autoplay player? The answers are in the guide, with worked examples. The PDFs from 2.2 to 2.5 kept similar notes in their own section 7.

Looking up a field in the RTBlint field reference

A field can be named two ways. The spec uses object names, such as Video.plcmt. Payloads use paths, such as imp.video.plcmt. The field reference accepts both and files each field under its object, at /docs/openrtb/fields/<object>/<field>/ in lower case. A few entry points:

Each field page gives the type, default, and required status, the first version that defines it, any deprecation or move, the AdCOM list if one applies, and the spec section. It also shows availability across every tracked version, a minimal JSON example, and the validation rules that fire on it. One object can sit at several paths: Geo appears at both device.geo and user.geo, and Content under site, app, and dooh. The field page covers every path at once.

A routine for any field question

  1. Find out which version or dated release your partner runs.
  2. Open that version's object table and read the Type cell first: type, qualifier, default.
  3. If the description names a list, read the values in AdCOM, or in section 5 or 6 of an older PDF.
  4. If the question is about behavior or timing, check the implementation guide.
  5. If the key sits under ext, go to the partner's documentation.
  6. Confirm against a real payload, since documents lag traffic.

For the last step, paste the payload into the tester with the matching release selected; it reports fields that the chosen release does not define, along with deprecated and moved paths.

Questions people ask

Where is the official OpenRTB 2.6 specification?

In IAB Tech Lab's openrtb2.x repository on GitHub, as the Markdown file 2.6.md. Each dated release is tagged 2.6-YYYYMM. The enumerated lists that 2.6 refers to live in the AdCOM repository, the implementation notes live in implementation.md in openrtb2.x, and versions 2.0 to 2.5 are PDFs linked from IAB Tech Lab's OpenRTB page.

What does recommended mean in the OpenRTB spec?

A recommended attribute is not required for the protocol to work, but including it is the market norm, and partners may refuse to transact without it. site, app, device, and user on the bid request are recommended, as are source.tid and source.schain. Required attributes are only those whose absence would break the protocol, such as BidRequest.id and imp.

What does it mean when an OpenRTB field is omitted?

Absence has a formal meaning. If the object table gives a default, an omitted field equals that default: at is 2, imp.bidfloor is 0, imp.bidfloorcur is USD. If there is no default, an omitted field means unknown. That is why senders should leave a field out rather than send null or a placeholder value.