1
Search for any city using the /markets/search endpoint. The response includes the full_name, country, region, and locality fields that you need to construct the market object used in all subsequent calls.
Python
import requests
API_KEY = "your_api_key"
BASE_URL = "https://api.airroi.com/v1"
headers = {"X-API-KEY": API_KEY}
# Search for a market
response = requests.get(
f"{BASE_URL}/markets/search?query=nashville",
headers=headers
)
results = response.json()
market = results[0]
print(f"Market: {market['full_name']}")
print(f"Country: {market['country']}")
print(f"Region: {market['region']}")
print(f"Locality: {market['locality']}")
print(f"Active listings: {market['active_listings_count']:,}")
# Save the market object for subsequent calls
market_obj = {
"country": market["country"],
"region": market["region"],
"locality": market["locality"]
}2
Call /markets/metrics/occupancy with your market object and num_months: 12 to get monthly occupancy data. Each month includes the market average (avg) and percentiles (p25, p50, p75, p90) so you can see how occupancy is distributed across all listings.
Python
# Pull 12 months of occupancy data with percentiles
payload = {
"market": market_obj,
"num_months": 12
}
response = requests.post(
f"{BASE_URL}/markets/metrics/occupancy",
json=payload,
headers={**headers, "Content-Type": "application/json"}
)
occupancy_data = response.json()
print(f"{'Month':<12} {'Avg':>6} {'p25':>6} {'p50':>6} {'p75':>6} {'p90':>6}")
print("-" * 48)
for month in occupancy_data:
print(f"{month['date']:<12} "
f"{month['avg']:>5.0%} "
f"{month['p25']:>5.0%} "
f"{month['p50']:>5.0%} "
f"{month['p75']:>5.0%} "
f"{month['p90']:>5.0%}")3
Compare the market-wide average occupancy against p90 (top 10% performers). The spread between them reveals how much room there is to outperform. A large spread means top hosts are doing something materially different — better pricing, more reviews, professional photography, or superior amenities.
Python
# Compare average vs top performers
import statistics
avg_occupancies = [m["avg"] for m in occupancy_data]
p90_occupancies = [m["p90"] for m in occupancy_data]
overall_avg = statistics.mean(avg_occupancies)
overall_p90 = statistics.mean(p90_occupancies)
spread = overall_p90 - overall_avg
print(f"Market average occupancy: {overall_avg:.0%}")
print(f"Top 10% (p90) occupancy: {overall_p90:.0%}")
print(f"Spread: {spread:.0%}")
print()
if spread > 0.25:
print("Large spread — top performers significantly outpace the average.")
print("This suggests room for optimization if you can match")
print("what the top 10% are doing (better listing, pricing, reviews).")
elif spread > 0.15:
print("Moderate spread — top hosts do noticeably better.")
print("Focus on pricing strategy and listing quality to move up.")
else:
print("Narrow spread — the market is fairly uniform.")
print("Occupancy is less about skill and more about market conditions.")4
Add a filter parameter with bedrooms: { eq: 2 } to see how property size affects occupancy. Compare 1-bedroom, 2-bedroom, and 3-bedroom properties to understand which segment has the strongest demand in your target market.
Python
# Filter by bedrooms to see how property size affects occupancy
bedroom_counts = [1, 2, 3]
bedroom_data = {}
for br in bedroom_counts:
payload = {
"market": market_obj,
"filter": {"bedrooms": {"eq": br}},
"num_months": 12
}
response = requests.post(
f"{BASE_URL}/markets/metrics/occupancy",
json=payload,
headers={**headers, "Content-Type": "application/json"}
)
bedroom_data[br] = response.json()
# Compare annual average occupancy by bedroom count
print(f"{'Bedrooms':<10} {'Avg Occ':>8} {'p50 Occ':>8} {'p90 Occ':>8}")
print("-" * 36)
for br, data in bedroom_data.items():
avg = statistics.mean([m["avg"] for m in data])
p50 = statistics.mean([m["p50"] for m in data])
p90 = statistics.mean([m["p90"] for m in data])
print(f"{br} BR{'':<6} {avg:>7.0%} {p50:>7.0%} {p90:>7.0%}")5
Compare cities with stable year-round occupancy against highly seasonal markets. Calculate the coefficient of variation (standard deviation / mean) as a stability metric. A CV below 0.15 indicates a stable market, while above 0.30 signals high seasonality where you should plan for income gaps.
Python
# Compare seasonal stability across markets
import statistics
cities_to_compare = [
{"query": "austin", "label": "Austin (year-round)"},
{"query": "park city", "label": "Park City (seasonal)"},
]
for city_info in cities_to_compare:
# Search market
search = requests.get(
f"{BASE_URL}/markets/search?query={city_info['query']}",
headers=headers
).json()
if not search:
continue
m = search[0]
payload = {
"market": {
"country": m["country"],
"region": m["region"],
"locality": m["locality"]
},
"num_months": 12
}
data = requests.post(
f"{BASE_URL}/markets/metrics/occupancy",
json=payload,
headers={**headers, "Content-Type": "application/json"}
).json()
monthly_avg = [d["avg"] for d in data]
mean_occ = statistics.mean(monthly_avg)
std_occ = statistics.stdev(monthly_avg)
cv = std_occ / mean_occ # Coefficient of variation
print(f"{city_info['label']}:")
print(f" Mean occupancy: {mean_occ:.0%}")
print(f" Std deviation: {std_occ:.0%}")
print(f" CV (stability): {cv:.2f}")
print(f" Verdict: {'Stable' if cv < 0.15 else 'Seasonal' if cv < 0.30 else 'Highly seasonal'}")
print()6
If you have an active listing, pull its occupancy via /listings/metrics/all and compare it month by month against the market percentiles. See exactly where you rank: below p25 (underperforming), between p25 and p75 (average), above p75 (strong), or above p90 (exceptional).
Python
# Benchmark your listing against market percentiles
listing_id = "your_listing_id" # Your Airbnb listing's AirROI ID
response = requests.get(
f"{BASE_URL}/listings/metrics/all?id={listing_id}&num_months=24",
headers=headers
)
listing_metrics = response.json()
# Compare listing occupancy vs market percentiles
print(f"{'Month':<12} {'Your Occ':>8} {'Mkt Avg':>8} {'Mkt p75':>8} {'Mkt p90':>8} {'Rank':>14}")
print("-" * 56)
for listing_month in listing_metrics[-12:]:
date = listing_month["date"]
my_occ = listing_month["occupancy"]
# Find matching market month
market_month = next(
(m for m in occupancy_data if m["date"] == date), None
)
if not market_month:
continue
# Determine rank
if my_occ >= market_month["p90"]:
rank = "Exceptional"
elif my_occ >= market_month["p75"]:
rank = "Strong"
elif my_occ >= market_month["p25"]:
rank = "Average"
else:
rank = "Below avg"
print(f"{date:<12} {my_occ:>7.0%} {market_month['avg']:>7.0%} "
f"{market_month['p75']:>7.0%} {market_month['p90']:>7.0%} "
f"{rank:>14}")Keep exploring the AirROI API with these related tutorials.
Average Airbnb occupancy rates vary significantly by city, season, and property type. National averages typically fall between 50-65%, but top-performing markets like Nashville, Austin, and Miami often see 70-80%+ average occupancy. Use the AirROI API to pull exact, current figures for any specific market.
Percentiles show how occupancy is distributed across all listings in a market. p25 means 25% of listings have this occupancy or lower (bottom quartile). p50 is the median. p75 means only 25% of listings perform better. p90 represents the top 10% of performers. The spread between p25 and p90 shows how much the best hosts outperform the average.
Typically, 1-bedroom and 2-bedroom properties have the highest occupancy rates because they serve the largest traveler segment (couples and small families). 4+ bedroom properties often have lower occupancy but higher nightly rates and total revenue. Use the bedroom filter to compare how occupancy shifts by property size in your target market.
A good occupancy rate depends on your market and strategy. Generally, above the market p50 (median) is solid, above p75 is strong, and above p90 is exceptional. However, some hosts intentionally target lower occupancy with higher rates to maximize revenue per guest while reducing wear and tear.
Calculate the coefficient of variation (standard deviation / mean) of monthly occupancy over 12 months. A CV below 0.15 indicates a stable, year-round market (like Austin or Miami). A CV above 0.30 indicates high seasonality (like ski resorts or beach towns). This tutorial shows you exactly how to calculate this.
The /markets/metrics/occupancy endpoint supports filtering by bedrooms, bathrooms, and other property attributes. For more advanced filtering by amenities or property type, use the /listings/search/market endpoint with filters and then aggregate the occupancy data from individual listings.
Market-level occupancy metrics are updated monthly. The data reflects actual booking patterns observed across all active listings in the market. For the most recent month, data becomes available shortly after the month closes.
Stay ahead of the curve
Join our newsletter for exclusive insights and updates. No spam ever.