Intermediate
20 min

Rental Arbitrage Feasibility Analysis

Calculate whether a rental arbitrage deal is profitable. Estimate STR revenue, factor in expenses, run sensitivity analyses, and screen multiple properties to find the best opportunities.

1

Estimate STR Revenue

Use GET /calculator/estimate with the target property address to get projected annual revenue at multiple percentiles. The p25 estimate is your conservative scenario, p50 is average, and p75 represents top-performer potential. Always plan financials using the p25 or p50 number.

Python

import requests

API_KEY = "your_api_key_here"
BASE_URL = "https://api.airroi.com/v1"

# Estimate STR revenue for a target property
address = "123 Main St, Nashville, TN 37203"
response = requests.get(
    f"{BASE_URL}/calculator/estimate",
    headers={"X-API-KEY": API_KEY},
    params={
        "address": address,
        "bedrooms": 2,
        "baths": 1,
        "guests": 4,
        "currency": "usd"
    }
)

estimate = response.json()

print(f"Revenue Estimate for: {address}")
print(f"\nAnnual Revenue Projections:")
print(f"  Conservative (p25): {estimate['revenue']['p25']:,.0f}")
print(f"  Average (p50):      {estimate['revenue']['p50']:,.0f}")
print(f"  Optimistic (p75):   {estimate['revenue']['p75']:,.0f}")
print(f"\nOccupancy: {estimate['occupancy']['avg']:.1%}")
print(f"Average Daily Rate: {estimate['average_daily_rate']['avg']:,.0f}")

2

Input Long-Term Rent Cost

Enter the monthly long-term rent for the property you are considering. Get this number from Zillow, Apartments.com, Realtor.com, or directly from the landlord. Annualize by multiplying by 12. This is your primary fixed cost.

Python

# Input long-term rent cost
# Sources: Zillow, Apartments.com, Realtor.com, local listings
monthly_rent = 2000  # dollars per month

annual_rent = monthly_rent * 12
print(f"Monthly rent: {monthly_rent:,}")
print(f"Annual rent cost: {annual_rent:,}")

3

Calculate Gross Margin

Subtract annual rent from projected STR revenue to get the gross margin. Calculate this at each percentile to understand the range of outcomes. If the gross margin is negative at p25, the deal carries significant risk.

Python

# Calculate gross margin at each revenue percentile
annual_rent = monthly_rent * 12

revenue_p25 = estimate["revenue"]["p25"]
revenue_p50 = estimate["revenue"]["p50"]
revenue_p75 = estimate["revenue"]["p75"]

gross_margin_p25 = revenue_p25 - annual_rent
gross_margin_p50 = revenue_p50 - annual_rent
gross_margin_p75 = revenue_p75 - annual_rent

print("=== Gross Margin Analysis ===")
print(f"Annual Rent: {annual_rent:,}")
print(f"")
print(f"{'Scenario':<15} {'STR Revenue':>12} {'Gross Margin':>14} {'Margin %':>10}")
print(f"{'-'*51}")
print(f"{'Conservative':<15} {revenue_p25:>11,} {gross_margin_p25:>13,} {gross_margin_p25/revenue_p25:>9.1%}")
print(f"{'Average':<15} {revenue_p50:>11,} {gross_margin_p50:>13,} {gross_margin_p50/revenue_p50:>9.1%}")
print(f"{'Optimistic':<15} {revenue_p75:>11,} {gross_margin_p75:>13,} {gross_margin_p75/revenue_p75:>9.1%}")

if gross_margin_p25 < 0:
    print("\n*** WARNING: Conservative scenario shows a LOSS. High risk. ***")

4

Factor Operating Expenses

Account for all operating costs: utilities ($200-400/month), cleaning ($100-150 per turnover at roughly 6-7 turnovers per month), supplies ($50/month), STR insurance ($100/month), and Airbnb platform fees (3% host-only or 14-16% if using split fee). Total operating expenses typically run 30-40% of gross revenue.

Python

# Factor in operating expenses
def calculate_expenses(annual_revenue, monthly_rent):
    """Calculate total operating expenses for rental arbitrage."""
    expenses = {}

    # Fixed monthly costs
    expenses["utilities"] = 300 * 12        # $200-400/mo
    expenses["supplies"] = 50 * 12          # consumables
    expenses["insurance"] = 100 * 12        # STR insurance

    # Variable costs
    occupancy_rate = 0.65
    avg_stay_nights = 3
    nights_per_month = 30 * occupancy_rate
    turnovers_per_month = nights_per_month / avg_stay_nights
    expenses["cleaning"] = 125 * turnovers_per_month * 12  # $100-150/turn

    # Platform fees (Airbnb host-only fee is ~3%, split fee ~14-16% guest side)
    expenses["platform_fees"] = annual_revenue * 0.03

    # Total
    total = sum(expenses.values())
    expenses["total"] = total
    expenses["pct_of_revenue"] = total / annual_revenue if annual_revenue > 0 else 0

    return expenses

# Calculate at p50 scenario
expenses = calculate_expenses(revenue_p50, monthly_rent)

print("=== Operating Expenses (Annual) ===")
for key, val in expenses.items():
    if key == "pct_of_revenue":
        print(f"  {key:<20} {val:.1%}")
    elif key == "total":
        print(f"  {'TOTAL':<20} {val:,.0f}")
    else:
        print(f"  {key:<20} {val:,.0f}")

# Net profit
net_profit = revenue_p50 - annual_rent - expenses["total"]
print(f"\n=== Net Profit (p50 Scenario) ===")
print(f"  STR Revenue:       {revenue_p50:,.0f}")
print(f"  Annual Rent:      -{annual_rent:,.0f}")
print(f"  Operating Costs:  -{expenses['total']:,.0f}")
print(f"  {'Net Profit:':>19} {net_profit:,.0f}")

5

Sensitivity Analysis

Build a matrix showing net profit at different revenue percentiles (p25, p50, p75) against different rent levels ($1,500, $2,000, $2,500, $3,000). This reveals the break-even point: the maximum rent you can pay while still being profitable. Always ensure the deal works at the conservative p25 estimate.

Python

# Sensitivity analysis: revenue scenarios vs rent levels
rent_levels = [1500, 2000, 2500, 3000]
revenue_scenarios = {
    "Conservative (p25)": revenue_p25,
    "Average (p50)": revenue_p50,
    "Optimistic (p75)": revenue_p75,
}

print("=== Sensitivity Analysis: Net Annual Profit ===")
print(f"{'Rent/mo':<12}", end="")
for scenario_name in revenue_scenarios:
    print(f"{scenario_name:>22}", end="")
print()
print("-" * 78)

for rent in rent_levels:
    annual_rent_cost = rent * 12
    print(f"{rent:,}/mo     ", end="")
    for scenario_name, rev in revenue_scenarios.items():
        expenses = calculate_expenses(rev, rent)
        net = rev - annual_rent_cost - expenses["total"]
        color = "" if net >= 0 else "("
        end_color = "" if net >= 0 else ")"
        print(f"  {color}{abs(net):>16,}{end_color}", end="")
    print()

# Find break-even rent
print("\n=== Break-Even Analysis ===")
for scenario_name, rev in revenue_scenarios.items():
    # Net = Revenue - (Rent * 12) - Expenses = 0
    # Expenses depend on revenue, not rent
    expenses = calculate_expenses(rev, 0)
    max_annual_rent = rev - expenses["total"]
    max_monthly_rent = max_annual_rent / 12
    print(f"  {scenario_name}: max rent {max_monthly_rent:,.0f}/mo to break even")

6

Screen Multiple Properties

Loop over multiple property addresses, calculate net margin for each, and rank by profitability. This batch analysis approach lets you quickly screen 10-20 properties and identify the top candidates for deeper due diligence before committing to a lease.

Python

# Screen multiple properties and rank by profitability
properties = [
    {"address": "123 Main St, Nashville, TN 37203", "bedrooms": 2, "baths": 1, "guests": 4, "rent": 2000},
    {"address": "456 Broadway, Nashville, TN 37203", "bedrooms": 1, "baths": 1, "guests": 2, "rent": 1600},
    {"address": "789 Music Row, Nashville, TN 37203", "bedrooms": 3, "baths": 2, "guests": 6, "rent": 2800},
    {"address": "321 Gulch Ave, Nashville, TN 37203", "bedrooms": 2, "baths": 2, "guests": 5, "rent": 2200},
    {"address": "555 East Side Dr, Nashville, TN 37206", "bedrooms": 2, "baths": 1, "guests": 4, "rent": 1800},
]

results = []
for prop in properties:
    response = requests.get(
        f"{BASE_URL}/calculator/estimate",
        headers={"X-API-KEY": API_KEY},
        params={
            "address": prop["address"],
            "bedrooms": prop["bedrooms"],
            "baths": prop["baths"],
            "guests": prop["guests"],
            "currency": "usd"
        }
    )
    est = response.json()

    annual_rent = prop["rent"] * 12
    rev_p50 = est["revenue"]["p50"]
    expenses = calculate_expenses(rev_p50, prop["rent"])
    net_profit = rev_p50 - annual_rent - expenses["total"]
    net_margin = net_profit / rev_p50 if rev_p50 > 0 else 0

    results.append({
        "address": prop["address"],
        "rent": prop["rent"],
        "revenue_p50": rev_p50,
        "net_profit": net_profit,
        "net_margin": net_margin,
    })

# Sort by net profit descending
results.sort(key=lambda x: x["net_profit"], reverse=True)

print("=== Property Screening Results (Ranked by Net Profit) ===\n")
for i, r in enumerate(results, 1):
    status = "PROFITABLE" if r["net_profit"] > 0 else "LOSS"
    print(f"{i}. {r['address']}")
    print(f"   Rent: {r['rent']:,}/mo | Revenue: {r['revenue_p50']:,}/yr | "
          f"Net: {r['net_profit']:,}/yr | Margin: {r['net_margin']:.1%} | {status}")
    print()

Continue Learning

Keep exploring the AirROI API with these related tutorials.

Frequently Asked Questions

Rental arbitrage is the practice of leasing a property on a long-term lease and then subletting it as a short-term rental on platforms like Airbnb. The profit comes from the difference between your long-term rent cost and the short-term rental revenue you generate, minus operating expenses.

The AirROI revenue estimator uses data from comparable properties in the same area to project revenue at multiple percentiles (p25, p50, p75). The p25 estimate represents a conservative scenario, while p75 represents top-performer potential. Most operators should plan using the p25-p50 range for financial projections.

Key expenses include utilities ($200-400/month), cleaning fees ($100-150 per turnover), supplies and consumables ($50/month), short-term rental insurance ($100/month), and platform fees (3-15% of gross revenue). Total operating costs typically run 30-40% of gross revenue.

Legality depends on your lease agreement (must allow subletting), local short-term rental regulations (permits, zoning, occupancy limits), and HOA rules if applicable. Always verify all three before committing to a lease. Many cities require STR permits and impose occupancy limits or minimum stay requirements.

A healthy net margin (after all expenses) is typically 20-30% of gross STR revenue. If your net margin falls below 15% at the p50 revenue estimate, the deal may be too risky. Always ensure profitability at the p25 (conservative) revenue scenario as a safety buffer.

We recommend screening at least 10-20 potential properties in your target area to understand the local economics. This tutorial shows how to batch-analyze multiple addresses in a single script. Compare net margins across properties and focus on the top 3-5 candidates for deeper due diligence.

Ready to Build?

Get your API key and start making calls in minutes.
made with