Airbnb Occupancy Rate & Revenue Data by City - STR Market
Pricing
$50.00 / 1,000 market rolled ups
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
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
18 days ago
Last modified
Categories
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_l365dgives the source's estimate of occupied days over the last year per listing as count, median, mean, 25th and 75th percentile, andavailability_365gives the open days over the coming year in the same form. - Booked share by month.
seasonality.monthsreports 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.
| Field | JSON type | Required | Default when omitted | What it does |
|---|---|---|---|---|
markets | Array of strings, or string | Yes | – | Markets to roll up. City name, or city, country to disambiguate. Null list entries are ignored; other entry types follow Python str(). |
address | Any JSON value | No | Empty address | A US street address for the live estimate. Asked once per run, however many markets you list. Values follow Python str(value or ""). |
include_snapshot | Boolean, number, string or null | No | true | Roll up the published market snapshot. Values follow Python bool(). |
include_seasonality | Boolean, number, string or null | No | true | Month-by-month booked share from the published calendar. Values follow Python bool(). |
include_live | Boolean, number, string or null | No | true | Live estimate for the address; skipped when no address is given. Values follow Python bool(). |
min_bedrooms | Number, string, boolean or null | No | 1 | Lower bedroom bound for the live estimate's comparables. Values follow Python int(). |
max_bedrooms | Number, string, boolean or null | No | 5 | Upper bedroom bound for the live estimate's comparables. Values follow Python int(). |
max_markets | Number, string, boolean or null | No | 5 | Upper 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_index | JSON type and meaning |
|---|---|
grain, status, error | Strings describing the block and any unavailable result |
address, country, region, locality | Strings or null, as returned for the requested address |
comparable_count | Integer or null; the number of comparable properties |
bedrooms_requested | Object with numeric or null min and max |
adr_average, adr_p25, adr_p75 | Numbers for the average daily rate and percentile bands |
occupancy_pct_average, occupancy_pct_p25, occupancy_pct_p75 | Numbers for occupancy percentage and percentile bands |
revpan_average, revpan_p25, revpan_p75 | Numbers for revenue per available night and percentile bands |
monthly_revenue_average, monthly_revenue_p25, monthly_revenue_p75 | Numbers for monthly revenue and percentile bands |
seasonalized_annual_revenue_average, seasonalized_annual_revenue_p25, seasonalized_annual_revenue_p75 | Numbers for seasonalised annual revenue and percentile bands |
seasonalized_monthly_revenue_average, historic_monthly_revenue_average, historic_revpan_average | Numbers for the accompanying seasonal and historic figures |
seasonalized_revenue_by_month, historic_revenue_by_month | Arrays 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.
| Actor | Input and result | When to use it |
|---|---|---|
| This Actor | City names; dated market distributions, monthly calendar shares and source attribution | Comparing published market snapshots with explicit revenue denominators |
| Airbnb Scraper | Location and travel dates; individual stays with prices, ratings and coordinates | Collecting accommodation search results for specific dates |
| Airbnb Occupancy Scraper | Listing IDs or search areas; occupancy and availability from forward calendars | Investigating individual listing calendars and booking pace |
| Airbnb Revenue Calculator | City-level revenue and occupancy estimates, ADR, RevPAR and available nights | Requesting 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.
Related Actors
- Airbnb Scraper for individual listings, prices and ratings by date.
- Cost of Living for the cost side of a market next to its rental revenue.
- Zillow Scraper and Apartments Scraper for long-let rents beside short-let revenue.