Airbnb Occupancy Rate & Revenue Data by City - STR Market avatar

Airbnb Occupancy Rate & Revenue Data by City - STR Market

Pricing

$50.00 / 1,000 market rolled ups

Go to Apify Store
Airbnb Occupancy Rate & Revenue Data by City - STR Market

Airbnb Occupancy Rate & Revenue Data by City - STR Market

Airbnb occupancy rate data by city: estimated occupied nights, nightly prices, revenue and monthly availability. Compare short-term rental markets for investment research; export JSON or CSV and request optional US address estimates.

Pricing

$50.00 / 1,000 market rolled ups

Rating

0.0

(0)

Developer

SR

SR

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

18 days ago

Last modified

Share

Airbnb Occupancy Rate & Revenue Data by City

Compare Airbnb occupancy rate data by city, including estimated occupied nights, nightly rates and revenue. This short-term rental market data Actor returns one market rollup per city for investors, lenders, analysts and hosts assessing rental markets before committing money.

Each row carries the published snapshot of a market (listing count, nightly rate, occupancy days, availability, reviews and revenue, each as a distribution with its denominator), the room, bedroom and neighbourhood mix, and a month-by-month booked-share curve derived from calendar availability. Add a US address to request an optional live revenue estimate for that address, side by side with the snapshot. Availability of the estimate depends on the calculator; the measured example below records a blocked estimate. The snapshot and live figures stay separate and are never averaged into one figure.

The output contains aggregates, source attribution and snapshot dates. It does not contain individual listing records. A published snapshot is a dated observation of a market, not a forecast of what one particular property will earn. The source index collected on 6 October 2026 resolves to 120 supported markets in 35 countries, including Amsterdam, Lisbon and US cities.

What the Airbnb occupancy rate data contains

  • One dataset row per market. Sizing twenty cities is twenty rows, and you pay only for the rows that carry figures.
  • Occupancy as a distribution. occupancy_days_l365d gives the source's estimate of occupied days over the last year per listing as count, median, mean, 25th and 75th percentile, and availability_365 gives the open days over the coming year in the same form.
  • Booked share by month. seasonality.months reports listed days, available share and booked share per calendar month, aggregated over every listing's calendar. It answers how calendar availability varies through the year. Unavailable nights may include host-blocked dates, so this curve alone does not establish how many nights were sold.
  • Nightly rate as a distribution, not one number pretending to be the market.
  • Revenue with named denominators. The median is the headline; three means sit beside the count each was taken over, so no figure can be quoted without its denominator.
  • Room mix, bedroom mix (studio to 7 plus) and the ten largest neighbourhoods.
  • Live estimate for a US address (optional): average daily rate, occupancy percentage, revpan, monthly revenue and seasonalised annual revenue, each with 25th and 75th percentile bands, a twelve-month revenue curve and the number of comparables behind it.
  • Dates and attribution on every row, plus a coverage block that says which parts of the row returned figures.

Input

markets is required. Give a list of market names, such as the Amsterdam input below. An element like Lisbon, Portugal stays one market when placed in a list. A plain string is also understood, but commas, semicolons and newlines split it into separate names. Repeated market names are preserved in the output. A unique partial name can resolve a published city; ambiguous partial names do not select an arbitrary market.

FieldJSON typeRequiredDefault when omittedWhat it does
marketsArray of strings, or stringYes–Markets to roll up. City name, or city, country to disambiguate. Null list entries are ignored; other entry types follow Python str().
addressAny JSON valueNoEmpty addressA US street address for the live estimate. Asked once per run, however many markets you list. Values follow Python str(value or "").
include_snapshotBoolean, number, string or nullNotrueRoll up the published market snapshot. Values follow Python bool().
include_seasonalityBoolean, number, string or nullNotrueMonth-by-month booked share from the published calendar. Values follow Python bool().
include_liveBoolean, number, string or nullNotrueLive estimate for the address; skipped when no address is given. Values follow Python bool().
min_bedroomsNumber, string, boolean or nullNo1Lower bedroom bound for the live estimate's comparables. Values follow Python int().
max_bedroomsNumber, string, boolean or nullNo5Upper bedroom bound for the live estimate's comparables. Values follow Python int().
max_marketsNumber, string, boolean or nullNo5Upper bound on markets per run, clamped to 1–20. Values follow Python int() with fallback 5.

The original numeric forms keep working: decimals are truncated toward zero, integer strings such as "7" are accepted, and an empty or non-numeric bedroom bound omits that bound from the estimate request. Inclusion options accept 1/0 like Python bool(); only a missing field keeps the default of true. Non-string market list entries and a non-string address follow Python str() (true becomes True, empty and null entries are dropped). JSON does not keep Python's int/float distinction, so a whole number written as 2.0 becomes the integer text "2", not "2.0". Start with one city and the default options, then raise max_markets when comparing several markets. The default of five still limits the number of rows if you supply a longer list without changing this field.

Explicit null values

An omitted option uses the default above. An explicit JSON null keeps its existing meaning: address is empty; include_snapshot, include_seasonality and include_live are disabled; min_bedrooms and max_bedrooms omit their respective bounds from the estimate request; and max_markets uses five. This matters for API clients that send nulls for unused form fields. In the recorded Amsterdam run with all seven optional fields set to null, the Actor returned one diagnostic row with empty snapshot, seasonality and live objects, zero coverage and the no_data error. That row contained no figures and was free. To obtain the default snapshot and calendar, omit the inclusion options or set them to true.

A disabled block is an empty object, and its coverage value is zero. An unpublished market still produces a row explaining that the market is not published.

Without an address the live block reports skipped and no address given. The live estimate is requested once for the address and is repeated alongside each market row. It does not replace any market snapshot. If the calculator refuses the request, the row keeps a blocked live status while the snapshot and seasonality figures remain usable. No live figures are inferred from a blocked response.

This input was run on 6 October 2026 and produced the output shown below:

{
"markets": [
"Amsterdam"
],
"address": "200 E 6th St, Austin, TX 78701",
"min_bedrooms": 1,
"max_bedrooms": 5
}

Output: Airbnb occupancy rate and revenue per market

The following is the complete measured Amsterdam row from that run. as_of is the collection date; snapshot_as_of is the date published in the source snapshot. These dates answer different questions. The additional fetched_at timestamp, source, platform and snapshot_date fields allow the row to be joined to a common rental-market dataset without renaming the existing fields. market_index preserves the requested position.

{
"source": "str-market-sample",
"platform": "airbnb",
"fetched_at": "2026-10-06T05:43:06.224Z",
"market": "Amsterdam",
"market_index": 0,
"as_of": "2026-10-06",
"snapshot_index": {
"grain": "market",
"listing_count": 10369,
"room_mix": {
"Private room": 1833,
"Entire home/apt": 8489,
"Hotel room": 26,
"Shared room": 21
},
"bedroom_mix": {
"1": 5250,
"2": 2540,
"3": 1057,
"4": 316,
"5": 40,
"6": 4,
"studio_or_0": 1154,
"7_plus": 8
},
"neighbourhood_mix": {
"De Baarsjes - Oud-West": 1818,
"De Pijp - Rivierenbuurt": 1195,
"Centrum-West": 1191,
"Centrum-Oost": 921,
"Westerpark": 717,
"Zuid": 694,
"Oud-Oost": 664,
"Bos en Lommer": 546,
"Oud-Noord": 474,
"Oostelijk Havengebied - Indische Buurt": 411
},
"price": {
"count": 6377,
"median": 291,
"mean": 346.62,
"p25": 206.28,
"p75": 411
},
"occupancy_days_l365d": {
"count": 10369,
"median": 16,
"mean": 48.31,
"p25": 0,
"p75": 48
},
"availability_365": {
"count": 10369,
"median": 25,
"mean": 93.7,
"p25": 0,
"p75": 172
},
"reviews_ltm": {
"count": 10369,
"median": 2,
"mean": 8.58,
"p25": 0,
"p75": 6
},
"revenue_l365d": {
"count": 6377,
"median": 9496,
"mean_with_figure": 18296.92,
"mean_with_figure_count": 6377,
"mean_nonzero": 23349.9,
"mean_nonzero_count": 4997,
"mean_all_listings_missing_as_zero": 11252.720497637187,
"mean_all_listings_count": 10369,
"filter": "median over listings carrying a revenue figure; every mean named with its denominator"
},
"status": "ok",
"snapshot": "2026-06-15",
"market": "Amsterdam",
"country": "the-netherlands"
},
"seasonality": {
"grain": "market",
"months": {
"2026-06": {
"days_listed": 128962,
"available_share": 0.2072,
"booked_share": 0.7928
},
"2026-07": {
"days_listed": 324415,
"available_share": 0.2508,
"booked_share": 0.7492
},
"2026-08": {
"days_listed": 324415,
"available_share": 0.2604,
"booked_share": 0.7396
},
"2026-09": {
"days_listed": 313950,
"available_share": 0.2589,
"booked_share": 0.7411
},
"2026-10": {
"days_listed": 324415,
"available_share": 0.2506,
"booked_share": 0.7494
},
"2026-11": {
"days_listed": 313950,
"available_share": 0.296,
"booked_share": 0.704
},
"2026-12": {
"days_listed": 324415,
"available_share": 0.2824,
"booked_share": 0.7176
},
"2027-01": {
"days_listed": 324415,
"available_share": 0.2934,
"booked_share": 0.7066
},
"2027-02": {
"days_listed": 293020,
"available_share": 0.3014,
"booked_share": 0.6986
},
"2027-03": {
"days_listed": 324415,
"available_share": 0.2651,
"booked_share": 0.7349
},
"2027-04": {
"days_listed": 313950,
"available_share": 0.2353,
"booked_share": 0.7647
},
"2027-05": {
"days_listed": 324415,
"available_share": 0.2392,
"booked_share": 0.7608
},
"2027-06": {
"days_listed": 184988,
"available_share": 0.206,
"booked_share": 0.794
}
},
"day_count": 3819725,
"status": "ok",
"snapshot": "2026-06-15"
},
"live_index": {
"grain": "market",
"status": "blocked",
"error": "access limited"
},
"indexes_are_never_averaged": true,
"field_grain": {
"snapshot_index": "market",
"seasonality": "market",
"live_index": "market"
},
"data_coverage": {
"snapshot": 1,
"seasonality": 1,
"live": 0
},
"missing_blocks": [
"live"
],
"attribution": {
"snapshot": "Market snapshot data by Inside Airbnb, licensed CC BY 4.0",
"snapshot_url": "https://insideairbnb.com/data-assumptions/",
"live": "Live estimate figures as published by the calculator at rabbu.com"
},
"has_figures": true,
"snapshot_as_of": "2026-06-15",
"snapshot_date": "2026-06-15"
}

price, occupancy_days_l365d, availability_365 and reviews_ltm each report the number of observed figures and, where present, the median, mean and percentile bands. Missing source values are excluded from those distributions. Room and bedroom counts include every listing, while the neighbourhood mix shows the ten largest named groups.

The revenue block names every denominator explicitly. median describes listings with a revenue figure. mean_with_figure uses those same listings; mean_nonzero uses only positive values. mean_all_listings_missing_as_zero includes all listings with missing revenue treated as zero. In Amsterdam those three means are 18,297, 23,350 and 11,253: three different questions with three different answers. Their separate counts let you choose the question your analysis actually needs.

seasonality.months reports listed days, available share and booked share for each calendar month. Booked share is derived from the source availability flag. It is an occupancy proxy, not proof that every unavailable night was sold; the source explains this distinction in Inside Airbnb's data assumptions. data_coverage records whether snapshot, seasonality and live blocks returned figures. missing_blocks lists the absent blocks, and has_figures records whether the row contains any usable figures at all.

When the live calculator answers, live_index has status: "ok". Its existing field names and JSON types are:

Fields inside live_indexJSON type and meaning
grain, status, errorStrings describing the block and any unavailable result
address, country, region, localityStrings or null, as returned for the requested address
comparable_countInteger or null; the number of comparable properties
bedrooms_requestedObject with numeric or null min and max
adr_average, adr_p25, adr_p75Numbers for the average daily rate and percentile bands
occupancy_pct_average, occupancy_pct_p25, occupancy_pct_p75Numbers for occupancy percentage and percentile bands
revpan_average, revpan_p25, revpan_p75Numbers for revenue per available night and percentile bands
monthly_revenue_average, monthly_revenue_p25, monthly_revenue_p75Numbers for monthly revenue and percentile bands
seasonalized_annual_revenue_average, seasonalized_annual_revenue_p25, seasonalized_annual_revenue_p75Numbers for seasonalised annual revenue and percentile bands
seasonalized_monthly_revenue_average, historic_monthly_revenue_average, historic_revpan_averageNumbers for the accompanying seasonal and historic figures
seasonalized_revenue_by_month, historic_revenue_by_monthArrays containing the monthly curves

Unavailable estimates do not acquire these numeric fields. The block keeps its status and reason, as in the measured row above; disabled blocks remain empty objects.

At row level, market, as_of, source, platform and fetched_at are strings; market_index is an integer. The snapshot, seasonality, live, grain, coverage and attribution blocks remain objects. missing_blocks is an array of strings, while indexes_are_never_averaged and has_figures are booleans. snapshot_as_of and snapshot_date are optional strings and are absent when no snapshot date is available.

Dataset rows are written to the default dataset. The OUTPUT key-value record keeps itemCount, marketCount, errorCount, chargeEvent, markets, dataCoverage and indexesNeverAveraged. The row's data_coverage contains integer flags, zero or one for each block. OUTPUT.dataCoverage adds those flags across the delivered markets, so a run with two snapshot results reports snapshot: 2. It is a count of covered markets, rather than a percentage or an additional charge. itemCount and errorCount are integers; marketCount counts rows with figures, markets is a string array, chargeEvent is a string and indexesNeverAveraged is a boolean.

Where a market has no figures, errors contains the old no_data code and an explanatory message. Empty market input retains the validation failure and the bad_input code; unexpected failures retain internal_error. Each error record has string code and message fields. An unavailable optional estimate can coexist with a successful market row. Download the dataset as JSON, CSV or Excel, keeping the nested blocks intact when their full statistics are needed.

Use cases

Rental arbitrage before a lease signature. An operator has a target city and a rent number. The rollup gives the nightly rate distribution, the occupancy days and the revenue median with its denominator; the seasonality curve shows the slow months the rent still has to cover.

Lenders and insurers pricing short-let risk. Market grain is what a credit paper needs: how many listings, what mix, what the revenue distribution looks like and which months pay.

Investors comparing cities. Up to twenty markets in one run, one row each, with the same fields for every city. Sort by median occupancy days or booked share and the shortlist writes itself.

Hosts and property managers benchmarking. Compare your own calendar with the Airbnb occupancy rate by month for your city, and your nightly rate with the 25th and 75th percentile of the market. Keep the calendar's unavailable-night proxy separate from your own confirmed bookings when comparing occupancy.

Researchers and journalists. Room mix and neighbourhood mix show how much of a city's inventory is whole homes, and where it concentrates, with the snapshot date and the licence attribution already on the row.

How it compares to other short-term rental data

Choose according to the question and the unit of data you need. These are different ways to collect rental data, rather than interchangeable estimates of the same thing.

ActorInput and resultWhen to use it
This ActorCity names; dated market distributions, monthly calendar shares and source attributionComparing published market snapshots with explicit revenue denominators
Airbnb ScraperLocation and travel dates; individual stays with prices, ratings and coordinatesCollecting accommodation search results for specific dates
Airbnb Occupancy ScraperListing IDs or search areas; occupancy and availability from forward calendarsInvestigating individual listing calendars and booking pace
Airbnb Revenue CalculatorCity-level revenue and occupancy estimates, ADR, RevPAR and available nightsRequesting calculator-style rental estimates

The alternatives' current Store descriptions were checked on 6 October 2026. Their billing units and data collection dates differ, so compare the required output and current pricing before choosing. This Actor's snapshot is dated public market data. Its optional address estimate is kept in a separate live_index block and may be unavailable; it does not provide a longer historical series or a confirmed booking ledger.

Pricing

The price remains $0.05 for each delivered market row containing figures, using the market event: $50 per 1,000 markets. There is no start fee. Diagnostic rows without any figures are delivered for visibility and are free. A blocked optional live block does not add an event or remove the useful snapshot figures. A market with a useful snapshot is charged once, even when its seasonality block also contains figures.

Users without a paid Apify plan receive at most ten rows per run. The cap applies to delivered rows, including diagnostic rows, and only delivered rows with figures are charged. max_markets keeps its default of five (or one when the value coerces to zero); the free-tier cap does not raise that limit to ten. Paid users can request up to twenty markets. All three existing inclusion options remain available. If charging reaches the run's configured charge limit, Apify records the resulting delivery and charge information in the run output.

Frequently asked questions

Do null input options use the defaults?

Only max_markets: null uses its default of five. A null inclusion option disables that block, a null address leaves the address empty, and a null bedroom bound leaves that bound unspecified. Omit options when you want their defaults. A row whose three blocks contain no figures remains free, including the recorded all-null Amsterdam case.

What is the Airbnb occupancy rate in my city?

Run the Actor with the city name. occupancy_days_l365d gives the estimated occupied days per listing over the last year (median, mean and percentiles) and seasonality.months gives the booked share per month. In the Amsterdam row above the median listing had an estimated 16 occupied days in the last year, while the calendar shows a booked share between 70 and 79 percent per month: the first is the source's estimate from reviewed stays, the second counts every night that is not open for booking.

Is the revenue figure a prediction for my property?

No. The snapshot describes the published market and its source estimates. A property's results depend on location, amenities, pricing and availability. Read the snapshot date and the denominator before using any number in a comparison.

Why can the three revenue means differ?

They include different groups of listings. One excludes missing figures, one additionally excludes zero figures, and one counts missing figures as zero across all listings. The row supplies each count so that none of those means is presented without context.

What happens when the live calculator is unavailable?

The live block records its status and explanation. Snapshot and calendar results remain independent. The measured example above shows the blocked form rather than a fabricated estimate. A row with no useful figures anywhere remains free.

Which cities are covered?

The collected source index resolves to 120 supported markets in 35 countries on 6 October 2026. Coverage changes when new snapshots are published. The live estimate covers US addresses only. A market without a usable snapshot returns a diagnostic row; it is free when no block on that row supplies figures.

Can I compare different snapshot dates?

Yes, but the dates and available source columns may differ. The Actor keeps the published snapshot date on each row and labels all three blocks at market grain. Keep dates and coverage alongside your comparisons, and retain the source attribution when using the data.

Do I get per-listing rows?

No. This Actor returns market aggregates with attribution and the snapshot date. For individual listing rows with prices per date, use the Airbnb Scraper.