OpenRTB Bid Request Anatomy

The bid request is the heart of programmatic advertising. It's the JSON that every SSP sends to every DSP, thousands of times per second. Understanding its structure means understanding how RTB really works.

🔍 Analyze a bid request 📋 View structure

What it is, and why it matters

In a real-time programmatic auction (RTB), everything starts with a bid request. When a user loads a web page, the publisher's SSP (Supply-Side Platform) has less than 100 milliseconds to assemble a JSON object describing the available inventory and send it to dozens of DSPs simultaneously. Each DSP reads that JSON, decides whether it wants to bid and at what price, and responds with a bid response. All of this happens before the page finishes rendering.

The standard that defines the structure of this JSON is called OpenRTB, maintained by the IAB Tech Lab. Version 2.5 is still the most widely deployed in production; 2.6 is gaining traction, especially for native supply chain support and new privacy regulations.

Why read this article? If you're in ad ops, trafficking, integrating a DSP as a developer, or managing adtech projects, the bid request is the reference document that explains why a campaign isn't delivering, why a DSP isn't bidding, and how GDPR consent flows through the programmatic chain.

The overall structure

An OpenRTB 2.x bid request is a JSON object with a few root fields and nested objects. The spec distinguishes required, recommended, and optional fields. In practice, SSPs send far more than the minimum — that's what enables DSPs to target precisely.

Top-level structure — OpenRTB 2.5JSON
"id": "e3d9a3f2-7b1c-4e2a...",  // unique identifier for this request
"at": 1,                         // auction type: 1=first price, 2=second price
"tmax": 350,                     // max response time in ms
"cur": ["EUR"],                  // accepted currencies
"imp": [...],                    // array of available impressions
"site": {...},                   // publisher context (OR "app")
"device": {...},                 // user's device
"user": {...},                   // user data + consent
"regs": {...},                   // regulatory framework (GDPR, CCPA, GPP)
"source": {...},                 // inventory origin + schain
"ext": {...}                     // SSP proprietary extensions
ObjectRequired?Role
imp[]Yes (min. 1)Description of the ad slot being sold
site OR appYes (one of the two)Publisher context — website or mobile app
idYesUnique request identifier (for log reconciliation)
deviceRecommendedDevice, OS, IP, geolocation
userRecommendedUser identity, TCF consent, EIDs
regsRecommendedRegulatory flags (GDPR, COPPA, US Privacy)
atOptionalAuction type (default = 2, second price)
tmaxOptionalTimeout in ms (no default — the DSP applies its own)

The imp object — the heart of the auction

The imp (impression) object describes exactly what the SSP is selling. A bid request can contain multiple impressions (for example, all ad slots on a page), but in practice most requests contain only one.

imp object — banner + PMP dealJSON
{
  "id": "1",
  "banner": {
    "format": [
      {"w":300,"h":250},
      {"w":320,"h":50}
    ],
    "pos": 1,    // 1 = above the fold
    "api": [3, 5]  // MRAID-1 and MRAID-2 supported
  },
  "bidfloor": 1.80,       // floor CPM in EUR
  "bidfloorcur": "EUR",
  "secure": 1,            // HTTPS required for the creative
  "tagid": "slot_hp_sidebar",
  "pmp": {
    "private_auction": 0, // 0 = open + deals, 1 = deals only
    "deals": [{
      "id": "DEAL-PREMIUM-007",
      "bidfloor": 4.50,     // deal-specific floor
      "at": 1,              // first price for this deal
      "wseat": ["dsp-seat-42"] // authorized buyer
    }]
  }
}

Impression formats

The imp object contains not multiple but exactly one format sub-object at a time — banner, video, audio, or native. Video-focused DSPs filter out requests without a video object as soon as they receive them, before even reading the other fields.

FormatKey fieldsNotes
bannerformat[], pos, apiMultiple sizes possible in format
videoprotocols[], minduration, maxduration, placementprotocols lists supported VAST standards
audioprotocols[], minduration, maxdurationBased on DAAST — rarely used outside podcast/radio
nativerequest (JSON in a string)IAB Native 1.2 spec encoded as a JSON string

Bidfloor and PMP deals

The bidfloor is the minimum CPM the SSP will accept. Any bid below it is automatically rejected. If bidfloorcur is absent, the assumed currency is USD — a frequent source of confusion when the DSP bids in EUR.

The pmp (Private Marketplace) object defines negotiated deals between a publisher and a specific buyer. When private_auction = 1, only buyers listed in the deals can participate. When it equals 0, deals coexist with the open auction — an authorized buyer can bid on the deal (floor at €4.50) or in the open auction (floor at €1.80).

Device and User — targeting and privacy

These are the two objects DSPs scrutinize most closely when making a buying decision. They're also the most sensitive from a GDPR perspective.

The device object

It describes the device displaying the ad. The ifa (Identifier for Advertising) field is the IDFA on iOS or the GAID on Android — the mobile advertising identifier that enables retargeting and conversion measurement. Since iOS 14.5, collecting it requires explicit user consent via ATT.

IP address and GDPR compliance The IP address (device.ip) is personal data under GDPR. Many SSPs truncate it to 3 octets before sending (92.184.xxx.0) or hash it. DSPs that use the IP for geographic inference must ensure the processing is covered by the TCF consent string.

The user object and the TCF consent string

This is where user consent flows. The user.consent field contains the TCF 2.x consent string encoded in Base64url — a string that summarizes the user's choices on the publisher's cookie banner.

user object with TCF and Extended IDsJSON
{
  "id": "u_8f3a2e1d9c7b",        // exchange-specific ID
  "buyeruid": "dsp_uid_4499xk",  // mapped ID on the DSP side (cookie sync)
  "consent": "CPziCYAP...",       // TCF 2.x consent string
  "eids": [
    {
      "source": "uidapi.com",     // UID 2.0 (The Trade Desk)
      "uids": [{ "id": "AgAAAAVacu7...", "atype": 3 }]
    },
    {
      "source": "liveramp.com",   // RampID
      "uids": [{ "id": "XY7mRIqaqBz...", "atype": 3 }]
    }
  ]
}

Extended IDs (eids) are the industry's response to the end of third-party cookies. They carry standardized alternative identifiers — UID 2.0, LiveRamp's RampID, ID5, PubCommonID — directly in the bid request, without relying on cookies.

The regs object — law in JSON

This is the regulatory field. A DSP that doesn't read it correctly risks processing data without a legal basis — a major legal exposure in Europe.

regs object — GDPR + CCPA + GPPJSON
{
  "gdpr": 1,            // 1 = subject to GDPR
  "ext": {
    "us_privacy": "1---", // CCPA string (1=applicable, ---=no opt-out)
    "gpp": "DBAA",         // Global Privacy Platform string
    "gpp_sid": [2]         // applicable GPP section (2=California CPRA)
  }
}
GDPR = 1 without consent string = problem If regs.gdpr = 1 and user.consent is absent, the DSP cannot determine which purposes were consented to. Most GDPR-compliant DSPs won't bid in that case, or will bid contextually only without using user data. This is a frequent cause of low fill rates on European traffic.

Supply Chain — tracing inventory origin

The schain (Supply Chain Object) is one of the major advances in OpenRTB 2.6. It lists every intermediary that touched the inventory between the publisher and the DSP — much like a cargo manifest tracing a shipment's route.

schain — 2 nodes (intermediate SSP + publisher)JSON
{
  "ver": "1.0",
  "complete": 1,         // 1 = complete chain from A to Z
  "nodes": [
    {
      "asi": "exchange-premium.com",  // SSP domain
      "sid": "pub-4829",             // publisher ID on this SSP
      "rid": "req-e3d9",             // request ID
      "hp": 1                        // 1 = authorized to sell this inventory
    },
    {
      "asi": "monsiteactu.fr",
      "sid": "site_001",
      "hp": 1
    }
  ]
}

The complete = 1 field is crucial: it indicates the chain is complete from the direct seller to the DSP. A complete = 0 means there may be undeclared intermediaries — a red flag for brand safety and ad fraud prevention.

The 6 most common bid request errors

ErrorImpactFix
GDPR=1 without user.consentDSP doesn't bid or bids without targetingEnsure the CMP passes the consent string before the bid request
bidfloor without bidfloorcurCurrency ambiguity, potential underbiddingAlways specify bidfloorcur
tmax too short (<150ms)DSP-side timeouts, low fill rate300–500ms is the standard range for most SSPs
site AND app both presentUndefined behavior on the DSP sideOnly one of the two objects, depending on context
IFA sent without LMT=0GDPR / ATT riskCheck device.lmt before using the IFA
schain.complete=0Brand-safety DSPs block the inventoryDeclare all intermediaries or work directly with the publisher

Analyze your bid request

Paste your OpenRTB JSON to visualize every annotated field, detect errors, and decode the TCF consent string.

Open the tool →

Frequently asked questions

What's the difference between OpenRTB 2.5 and 2.6?

OpenRTB 2.6 natively integrates the schain object (which was an extension in 2.5), adds better support for new privacy regulations (GPP), and improves dooh objects for out-of-home programmatic. 2.5 remains the most widely deployed version in production.

How do I know if my bid request is GDPR-compliant?

Three checks: regs.gdpr must equal 1 for European traffic, user.consent must contain a valid TCF 2.x consent string, and the consent string must include the purposes required for the processing you perform. Use the Flownect TCF Decoder to verify consented purposes.

What does at=1 (first price) change for DSPs?

In a first-price auction, the winner pays exactly their bid — not second price + 0.01. DSPs must adapt their bidding strategy: bid the true perceived value rather than bidding high to "win easily." The shift to first price has generally reduced average CPMs as DSPs calibrated their bids downward.

What does the "ext" field mean in a bid request?

The ext field is a proprietary extension zone — each SSP can add its own fields not defined in the standard spec. You'll typically find the Prebid version used, additional targeting metadata, or traffic quality indicators. These fields aren't standardized and vary from one SSP to another.