Provenance layer
Methodology: 2026 Airbnb Pricing Benchmark
Published by Revande. Measurement window 2026-01-01 to 2026-09-05. Compiled 2026-09-06.
This page states how the benchmark was measured, what it supports, and what it does not. It is the provenance layer for the dataset at /data/airbnb-pricing-benchmark-2026-lead-time.csv and /data/airbnb-pricing-benchmark-2026-lead-time.json, and for the article that interprets them. Every published figure is reproduced from stored counts by the code that emits the dataset, so this page and the dataset cannot disagree without the build failing.
0. What this page does not contain
Absolute counts are withheld throughout: how many listings were measured, how many reservations and nights they represent, how many price observations were captured, and how any of those split by channel, currency, or market. Those numbers describe the size and composition of a managed portfolio rather than the behaviour being reported. Every claim below is a ratio, a proportion, or a stated method, and none of them depends on the withheld figures.
1. What was measured
Two independent series, drawn from the same listings, and the combination is the finding.
Supply side. What a listing's own price does as a stay date approaches, captured repeatedly for the same stay date over a rolling forward window of roughly two months.
Demand side. When guests actually book, from confirmed reservations each carrying a true lead time in days.
A lead time is the whole number of days between the moment a price was captured (supply) or a reservation was created (demand) and the arrival date. Observations are grouped into eight buckets: 0 to 3, 4 to 7, 8 to 14, 15 to 21, 22 to 35, 36 to 60, 61 to 90, and 90 or more days before arrival.
2. The currency normalization rule
This is the single most important construction on this page, because without it the benchmark would measure exchange rates rather than pricing behavior.
A price is never used in its own units. Every observation is divided by the mean of all observations for that same (listing, stay date) pair:
index(listing, stay_date, captured_at) = price / mean(price over all captures of that listing and stay date)
The published index for a bucket is the mean of those ratios. The result is dimensionless. A listing priced in a currency worth a fraction of a cent and a listing priced in dollars contribute identically, because each is measured only against its own average. No currency can dominate a mean, and no conversion rate enters the calculation, so no conversion rate can move the result.
The portfolio is genuinely multi currency. Restricting to a single currency after normalization is a cohort matching decision (section 3), not a numerical necessity.
3. The cohort, and why it is matched
The price series and the booking series are drawn from overlapping sets, and the overlap is deliberate. Listings enter the priced cohort only if they also appear in the booking series and share its currency, so the priced cohort is a strict subset of the booked cohort. The two cohorts are different sizes, which is why a column drawn from one is never read as if it came from the other.
Why matching matters, stated against the record. An earlier draft of this benchmark used a small sample selected by internal code. That sample shared no membership with the booking series at all. It reported a smooth monotonic decay beginning around 35 days out and reaching a final three day discount of 8.1 percent. Rebuilding the same measurement on the matched cohort overturned it. The final three day discount is deeper, 10.6 percent, and the smooth decay does not exist: everything from 4 to 90 days out sits within 2 percent of baseline. The superseded 8.1 percent figure is preserved here rather than deleted, because a methodology that hides its own refutation is a marketing document.
4. The baseline
The 90 or more days bucket is the denominator. Its index is 1.0034 and its deviation from itself is defined as 0.00 percent by construction. Every other bucket is reported as a percentage deviation from it. That bucket holds roughly three quarters of all observations, because a rolling capture window sees far-out dates for far longer than it sees near-in ones.
5. The index by bucket
| Days before arrival | Share of observations | Index | vs baseline | Between portfolio spread |
|---|---|---|---|---|
| 0-3 | 1.11% | 0.8970 | -10.60% | 3.0pp |
| 4-7 | 1.11% | 0.9620 | -4.12% | 6.4pp |
| 8-14 | 1.95% | 1.0103 | +0.69% | 5.4pp |
| 15-21 | 1.95% | 0.9992 | -0.42% | 2.3pp |
| 22-35 | 3.89% | 0.9926 | -1.07% | 1.0pp |
| 36-60 | 6.95% | 0.9839 | -1.94% | 1.1pp |
| 61-90 | 8.34% | 1.0032 | -0.01% | 1.6pp |
| 90+ | 74.70% | 1.0034 | baseline | 0.5pp |
6. The publication gate: between portfolio spread
The priced cohort was queried in three independent groups, each drawn from a different part of the managed portfolio. The three groups are never summed before the index is computed, because the disagreement between them is itself a published result.
For each bucket, the spread is the widest gap between any two groups' indices, in percentage points. The gate is simple and it is enforced by an automated test rather than by editorial judgment:
Where the between portfolio spread exceeds the pooled effect it would describe, no market wide shape may be claimed for that bucket.
Applied to this dataset:
- The 0 to 3 day bucket passes. All three groups land at 0.8958, 0.9097, and 0.8794, every one below 0.92. The spread is 3.0 percentage points against an effect of 10.6 percent, so the effect is roughly three times the disagreement.
- The 4 to 7 and 8 to 14 buckets fail. Their spreads are 6.4 and 5.4 percentage points against effects of 4.1 percent and 0.7 percent. The groups disagree by more than the thing they would be describing, so nothing is claimed there.
7. What the benchmark supports
Exactly two claims survive this construction.
C1. Prices are cut in the final 72 hours, and the cut is universal. The 0 to 3 day bucket sits 10.6 percent below the 90 or more day baseline, and every group shows it independently.
C2. There is no claimable market wide price shape between 4 and 90 days out. Every bucket past the first week is within 2 percent of baseline, and in the two buckets nearest the first week the between group disagreement exceeds the effect. The discount is a cliff in the final three days, not a slope that starts weeks out.
Alongside them, from the demand series: 29.02 percent of 2026 reservations arrive inside that same 72 hour window, 41.46 percent within a week, and those are the shortest stays in the dataset at 2.44 nights against 4.77 nights at 90 or more days out. The window is 29.02 percent of bookings but only 21.69 percent of nights, so counting reservations overstates its weight by roughly one third.
8. Limitations
Limitation 1. Near-in buckets carry a selection effect. The 0 to 3 day bucket holds about 1.11 percent of observations against roughly 74.70 percent in the baseline bucket, a ratio of about 1 to 67. This is structural, not a sampling choice: a rolling window of about two months can only observe a stay date at 3 days out if that stay date fell inside the window, while it observes far-out dates on almost every day it runs. Near-in buckets are therefore drawn from a narrower set of stay dates than the baseline. The 0 to 3 result is reported because it reproduces independently in all three groups, which a sampling artifact would not be expected to do, not because the selection effect is absent.
Limitation 2. The mid range is unclaimable, and more data may not fix it. Between 4 and 90 days out the between group spread reaches 6.4 percentage points against effects under 4.2 percent. Widening the cohort would tighten the intervals, but the groups currently disagree about direction as well as size, so a market wide mid range curve is not merely unproven here, it is contradicted by the disagreement.
Limitation 3. The priced cohort is a fraction of the eligible one. The price index was computed on a subset of the listings that were eligible for it, because the aggregate query path has a hard size limit per request and each additional group costs a sequential round trip. Coverage was stopped on a convergence criterion rather than exhaustion: C1 already holds in every group, and C2 is a statement about disagreement that additional groups would have to overturn rather than confirm. It is nonetheless an assumption that widening would not change either claim, and it is labeled as one.
Limitation 4. Channel price differences are not computable from this data and are not published. Part of the portfolio is distributed to more than one booking channel, which appears at first to allow a channel by channel price comparison. It does not. The price records carry a unique index on (listing, stay date, capture time) with no channel dimension, so a listing on four channels is one price pushed to four places, recorded once. The co-located listing groups that might have substituted for a natural experiment all differ in bedroom count or property name, meaning they are separate units in one building rather than one unit on several channels. This limitation is stated because the metric was requested and because a plausible looking number could have been produced from the same tables by anyone who did not check the unique index.
Limitation 5. This is one portfolio, not a census of Airbnb. Every listing here is professionally managed and priced through a revenue management system. Nothing in this dataset describes an unmanaged listing, and the results should not be read as a market average.
Limitation 6. Correlation only. The benchmark reports what prices did and when bookings arrived. It does not establish that the discount caused the bookings or that the bookings caused the discount. Both series are observational and no intervention was made.
9. Data handling
No per listing price, listing identifier, account identifier, internal code, or property name appears in any published file, and no absolute count of listings, reservations, nights, or observations is published. Every published figure is a ratio or an average. This is verified before release by automated checks that scan every published surface for identifier columns and for any number bound to a countable noun, and fail the build on a match.
10. Reproducibility and verification
The dataset is emitted from stored counts and sums, never from stored percentages, so a later group can be added without silently restating a published share. Every published figure is recomputed from those counts at build time, and the published files carry only the ratio columns.
Automated tests guard the published claims. Four of them exist specifically to prevent this page from overstating its dataset: one asserts the final three day discount holds in every group independently, one asserts the mid range spread still exceeds its own effect, one asserts that no bucket past the first week deviates by more than 3 percent, and one asserts the discount is concentrated rather than gradual. A test that previously asserted a smooth decay was deleted when the matched cohort refuted it, and the reason is recorded in the test file rather than in a commit message.
External sources cited in the accompanying article are re-verified against their live documents on every run. A quotation that cannot be found character for character in the source document, after normalizing curly punctuation and whitespace, is dropped rather than downgraded. Stored verification booleans are never trusted, because a stored boolean keeps reporting verified after the source has changed its wording, moved, or gone behind a paywall.
11. Known operational hazards recorded during collection
Recorded here because they affected what could be measured and because a reader reproducing this work will meet them.
- The aggregate query path fails above a hard request size, so every aggregate was chunked and run sequentially. Only mergeable aggregates (counts and sums) were chunked; medians were not, because a median of medians is not a median.
- A restricted read returns HTTP 200 with an empty array rather than an error. An empty successful response and a correct empty result are indistinguishable at the transport layer, so every collection step was confirmed by row count at the source rather than by status code.