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 question | Read 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.
| Version | Format | Objects | Enumerated lists | Table columns |
|---|---|---|---|---|
| 2.0, 2.1, 2.2 | Section 3.3 (bid request object is 3.3.1) | Section 6 of the same PDF | Field, Scope, Type, Default, Description | |
| 2.3, 2.3.1, 2.4, 2.5 | Section 3.2 for the request, 4.2 for the response | Section 5 of the same PDF | Attribute, Type, Description | |
| 2.6 dated releases | Markdown on GitHub | Section 3.2 for the request, 4.2 for the response | AdCOM 1.0 | Attribute, Type, Description |
| 3.0 | Markdown on GitHub | Transport objects only; media and context come from AdCOM | AdCOM 1.0, plus the no-bid and loss lists | Attribute, 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.
| Attribute | Type cell | How to read it |
|---|---|---|
imp | object array; required | At least one entry, or the request breaks the protocol. |
site | object; recommended | The protocol works without it; buyers expect it for web inventory. |
at | integer; default 2 | Absent means second price plus. A first-price exchange must send 1. |
tmax | integer | No default. Absent means the timeout agreed at integration applies. |
imp.secure | integer | Absent means unknown; the description adds that plain HTTP can be assumed. |
imp.banner | object | Required only when the impression is offered as a banner. |
bid.api | integer; DEPRECATED | Still 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:
imp.video.plcmt: a field with an AdCOM list and a deprecated predecessor.device.devicetype: a field whose values come from List: Device Types.regs.gpp_sid: a field that first appears in a dated release.seatbid.bid.mtype: a response field.
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
- Find out which version or dated release your partner runs.
- Open that version's object table and read the Type cell first: type, qualifier, default.
- If the description names a list, read the values in AdCOM, or in section 5 or 6 of an older PDF.
- If the question is about behavior or timing, check the implementation guide.
- If the key sits under
ext, go to the partner's documentation. - 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.