Inside Airbnb Data Explained: What the Snapshots Contain

On this page

Problem statement

Inside Airbnb is the most widely used open source for short-term rental research, cited in city policy debates, academic papers and journalism. It is not Airbnb's data. It is a scrape of Airbnb's public website, taken on particular dates, enriched with Inside Airbnb's own calculations and estimates. Knowing what each file and field is, and what it is not, decides which conclusions the data can support.

This page explains the structure of an Inside Airbnb release using the Washington, D.C. snapshot of 24 June 2026. It covers what each file contains, which fields are scraped and which are derived, how fresh the scrape is, and which questions the data answers well and badly.

Quick answer

A release is a set of files for one city and one scrape date. Look at what the listings file holds:

print(f"listings: {len(L):,} rows, {L.shape[1]} columns; scraped {L.last_scraped.min()} to {L.last_scraped.max()}")
derived = [c for c in L.columns if c.startswith(("calculated_", "estimated_")) or c in ("neighbourhood_cleansed", "reviews_per_month")]
print(f"columns derived by Inside Airbnb rather than scraped: {derived}")
print(f"source values: {L.source.value_counts().to_dict()}")
listings: 6,945 rows, 90 columns; scraped 2026-06-24 to 2026-07-03
columns derived by Inside Airbnb rather than scraped: ['neighbourhood_cleansed', 'estimated_occupancy_l365d', 'estimated_revenue_l365d', 'calculated_host_listings_count', 'calculated_host_listings_count_entire_homes', 'calculated_host_listings_count_private_rooms', 'calculated_host_listings_count_shared_rooms', 'reviews_per_month']
source values: {'city scrape': 6175, 'previous scrape': 770}

The listings file has 6,945 rows and 90 columns, scraped between 24 June and 3 July 2026. Eight columns are Inside Airbnb's own calculations, and 770 rows have the source "previous scrape": listings carried over from an earlier scrape rather than found in this one.

The files in an Inside Airbnb release. one release, one scrape datelistings.csv.gz90 columns, one row per listing6,945 rows, 4.0 MBcalendar.csv.gzlisting x future night2,553,540 rowsreviews.csv.gzone row per reviewdates and textneighbourhoods.geojsoncity boundaries39 polygonsWashington, D.C., 24 June 2026 spatialworkflow.io
One release is one scrape of one city.

The files, scraped fields and gaps, information age

1. The files in a release

for name, url in FILES.items():
    p = cached(f"data/{name}", url)
    print(f"{name:>24}: {p.stat().st_size / 1e6:6.1f} MB")
print(f"calendar rows: {len(C):,}, one per listing and future night")
         listings.csv.gz:    4.0 MB
         calendar.csv.gz:    6.1 MB
  neighbourhoods.geojson:    0.4 MB
calendar rows: 2,553,540, one per listing and future night

The release is small: 4.0 MB of listings, 6.1 MB of calendar and 0.4 MB of boundaries. The calendar has 2,553,540 rows, one per listing and night for the year ahead.

Bars of the share of listings with a value for the emptiest and some partly filled columns Bars of the share of listings with a value for the emptiest and some partly filled columns
39 of 90 columns are complete and 13 are empty in this release.

2. Scraped fields and their gaps

cols = ["price", "bedrooms", "bathrooms", "review_scores_rating", "host_response_rate", "license", "neighbourhood", "description"]
print({c: f"{L[c].notna().mean():.0%}" for c in cols})
{'price': '90%', 'bedrooms': '83%', 'bathrooms': '84%', 'review_scores_rating': '80%', 'host_response_rate': '0%', 'license': '79%', 'neighbourhood': '0%', 'description': '98%'}

Most descriptive fields are filled for 80% or more of listings. host_response_rate and the free-text neighbourhood are empty in this release, which is why analyses use neighbourhood_cleansed.

3. How old the information is

Fields such as reviews describe the past; availability describes the future; price describes the dates quoted:

lr = pd.to_datetime(L.last_review)
print(f"listings with a review in the last 12 months: {(L.number_of_reviews_ltm > 0).mean():.0%}; last review before 2025: {(lr < '2025-01-01').mean():.0%}; never reviewed: {L.number_of_reviews.eq(0).mean():.0%}")
print(f"price quote check-in dates: {L.price_quote_checkin_date.min()} to {L.price_quote_checkin_date.max()}")
listings with a review in the last 12 months: 66%; last review before 2025: 10%; never reviewed: 20%
price quote check-in dates: 2026-06-24 to 2027-07-01

Two thirds of listings were reviewed in the past year, 20% have never been reviewed and 10% were last reviewed before 2025. Price quotes are for check-in dates from the scrape day to a year ahead.

What the estimates assume

The data used on this page

The Inside Airbnb release for Washington, D.C. dated 24 June 2026: listings, calendar and neighbourhood files, under a Creative Commons Attribution 4.0 licence. Inside Airbnb is independent of Airbnb.

from pathlib import Path

import pandas as pd
import requests

Path("data").mkdir(exist_ok=True)
BASE = "https://data.insideairbnb.com/united-states/dc/washington-dc/2026-06-24"
FILES = {"listings.csv.gz": f"{BASE}/data/listings.csv.gz", "calendar.csv.gz": f"{BASE}/data/calendar.csv.gz",
         "neighbourhoods.geojson": f"{BASE}/visualisations/neighbourhoods.geojson"}
def cached(path, url):
    p = Path(path)
    if not p.exists():
        r = requests.get(url, timeout=600); r.raise_for_status(); p.write_bytes(r.content)
    return p
L = pd.read_csv(cached("data/listings.csv.gz", FILES["listings.csv.gz"]))
C = pd.read_csv(cached("data/calendar.csv.gz", FILES["calendar.csv.gz"]), usecols=["listing_id", "date"])
print(f"release {BASE.rsplit('/', 1)[-1]}")
release 2026-06-24

Every figure on this page comes from the release dated 24 June 2026.

Example 1: what the estimates assume

Inside Airbnb's occupancy estimate uses reviews in the past year. Compare it with the review counts it is built from:

e = L[["number_of_reviews_ltm", "estimated_occupancy_l365d", "minimum_nights"]].dropna()
print(f"listings with zero reviews in the past year: {(e.number_of_reviews_ltm == 0).mean():.0%}; of those, estimated at zero nights: {(e.loc[e.number_of_reviews_ltm == 0, 'estimated_occupancy_l365d'] == 0).mean():.0%}")
print(f"highest estimate: {e.estimated_occupancy_l365d.max():.0f} nights; correlation of estimate with reviews: {e.number_of_reviews_ltm.corr(e.estimated_occupancy_l365d):.2f}")
listings with zero reviews in the past year: 34%; of those, estimated at zero nights: 100%
highest estimate: 255 nights; correlation of estimate with reviews: 0.80

Every listing with no review in the past year gets an occupancy estimate of zero, and the estimate correlates 0.80 with the review count. The estimate is largely a transformation of reviews, so it says little about listings booked by guests who do not review.

Scatter of estimated occupied nights against reviews in the past year Scatter of estimated occupied nights against reviews in the past year
The estimate tracks reviews, correlation 0.80, and caps at 255 nights.

What a visitor could see, recorded quarterly

Scraped and derived fields in Inside Airbnb listings. scraped or derivedfieldoriginnoteprice, bedrooms, licencescraped79-90% filledneighbourhood_cleansedderivedpoint in polygoncalculated_host_listings_countderivedcounted in snapshotestimated_occupancy_l365dderivedfrom reviews, cap 255sourcescraped770 "previous scrape"8 of 90 columns are Inside Airbnb calculationshost_response_rate and neighbourhood are empty spatialworkflow.io
Eight columns are Inside Airbnb calculations.

Inside Airbnb visits Airbnb's public pages for each city it covers, usually about once a quarter, and records what any visitor could see: each active listing's details, its availability calendar and its reviews. A release bundles the results for one scrape date. There is a detailed listings file, with 90 columns in this release, a calendar with one row per listing and future night, a reviews file, and neighbourhood boundaries from the city, plus summary versions for quick maps. Some fields are Inside Airbnb's own work rather than Airbnb's: the cleaned neighbourhood assignment, host listing counts calculated from the snapshot, reviews per month, and model-based estimates of occupancy and revenue derived from reviews.

That makes the data good for some questions and weak for others. It answers well where listings are, what kinds of property they are, how prices compare between areas, and how concentrated hosting is. It answers less well how much listings earn or how many nights are booked, which rest on estimates, exactly where a unit is, since locations are blurred, and what happened between snapshots, since listings that appear and disappear between scrapes are missed. Every figure should carry the snapshot date, and comparisons over time should use several snapshots of the same city.

Archives, method changes and coverage

Questions Inside Airbnb data answers well and badly. good for, weak foranswers well✓where listings are✓prices between areas✓host concentrationanswers weakly✓nights booked, revenue✓exact locations✓change between scrapesEstimate correlates 0.80 with review counts spatialworkflow.io
Estimates and locations are the weak points.
  • Archives: Inside Airbnb keeps recent releases online and older ones on request; record the release date you used.
  • Methods change: occupancy assumptions and columns change between releases; check the data dictionary for each.
  • Coverage: hotels and serviced apartments that list on Airbnb appear alongside home-sharing hosts.
  • Licence: CC BY 4.0; credit Inside Airbnb and note that data is scraped from Airbnb's public site.

FAQ

What is Inside Airbnb?

An independent project that scrapes Airbnb's public listings for hundreds of cities and publishes the data, with maps and estimates, for free.

Is Inside Airbnb data official Airbnb data?

No; it is scraped from the public website and enriched with Inside Airbnb's own calculations.

How often is Inside Airbnb data updated?

Usually about quarterly for each city; each release is a snapshot of one scrape date.

How accurate are Inside Airbnb's occupancy estimates?

They are models based on reviews and assumptions about review rates and stay lengths; treat them as rough estimates.