Airbnb Availability & Rate Scraper avatar

Airbnb Availability & Rate Scraper

Pricing

$19.99/month + usage

Go to Apify Store
Airbnb Availability & Rate Scraper

Airbnb Availability & Rate Scraper

Monitor Airbnb occupancy and availability across listings or cities. Retrieve booked nights, seasonal trends, and pricing signals. Designed for researchers, investors, and revenue teams needing trusted data.

Pricing

$19.99/month + usage

Rating

0.0

(0)

Developer

SimpleAPI

SimpleAPI

Maintained by Community

Actor stats

0

Bookmarked

12

Total users

0

Monthly active users

12 days ago

Last modified

Share

๐Ÿ“… Airbnb Availability & Rate Scraper

Scrape the forward-looking availability calendar of Airbnb listings and the real per-day fields Airbnb's own calendar returns โ€” check-in / check-out eligibility, the bookable flag, minimum / maximum nights, and the nightly price when it is present. From those real values it derives an honest unavailableRate and, only from real calendar prices, ADR / estimated revenue / RevPAR.

This actor is deliberately honest about what the data is and is not. Read the two notes below before using it.

โš ๏ธ Honesty notes (read these)

  • This is availability, not occupancy. Airbnb's calendar tells you whether a night is available. An unavailable night can be either genuinely booked or blocked by the host โ€” the public calendar cannot distinguish the two. We therefore report unavailableRate = unavailable days รท counted days, clearly labeled "includes host-blocked days; not a booking/occupancy rate." We never call unavailable nights "booked" and never emit an "occupancy rate."
  • Money fields come only from real prices. adr, estimatedRevenue and revpar are computed exclusively from nightly prices that appear in the calendar payload. When a listing exposes no calendar prices, these fields are null โ€” never a regional average, a search-page price, or an interpolated guess. estimatedRevenue / revpar additionally assume every unavailable night is a paid booking, which is an upper bound (it includes host-blocked nights); they are labeled as such.
  • Forward-only. PdpAvailabilityCalendar returns future availability. Past dates are clamped to today. There is no historical calendar available from this endpoint.

How it works

  1. curl_cffi Chrome TLS impersonation. Airbnb sits behind Akamai / PerimeterX. Plain requests/aiohttp are blocked at the TLS (JA3) layer before reaching the app. This actor uses curl_cffi with impersonate="chrome" so requests replay a real Chrome handshake.
  2. Soft-block guard + proxy escalation. An airlock / challenge / empty shell is detected and reported as a block (the run keys on the presence of the expected bootstrap container, not on loose tokens), and the actor retries on a fresh residential proxy IP.
  3. Dynamic persisted-query discovery. The GraphQL persisted-query hash is found by scanning the room page and its JS bundles for the hash next to PdpAvailabilityCalendar โ€” no hardcoded bundle name that breaks on every Airbnb deploy.
  4. Harvest + derive. Every already-in-payload day field is emitted; derived metrics are computed with the honesty rules above.

Input

FieldTypeNotes
listingsarray (required)Room URLs or bare IDs, one per line.
startDatedateAbsolute (2026-08-01) or relative (7 days, 1 month). Empty = today. Past โ†’ clamped to today.
endDatedateAbsolute or relative. Empty = start + 30 days. Up to ~12 months ahead.
billingModeenumper_listing (default, 1 charge/listing) or per_day.
includeDaysbooleanEmit per-day child rows (default true).
includeListingDetailsbooleanBest-effort title/type/capacity/beds/baths/coords (default false).
includeHostProfilebooleanBest-effort superhost/name/response rate (default false).
proxyConfigurationproxyDefault residential (recommended; datacenter is usually blocked).
{
"listings": ["https://www.airbnb.com/rooms/35329051"],
"startDate": "2026-08-01",
"endDate": "2026-10-31",
"billingMode": "per_listing",
"includeDays": true,
"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}

Output

Two row types share the dataset and are distinguished by type / isChild.

Parent โ€” type: "listing" (one per target):

{
"type": "listing", "isChild": false,
"roomId": "35329051", "listingUrl": "https://www.airbnb.com/rooms/35329051",
"windowStart": "2026-08-01", "windowEnd": "2026-10-31",
"totalDays": 92, "availableDays": 40, "unavailableDays": 52,
"unavailableRate": 0.5652,
"adr": 128.5, "priceCoverage": "40/92", "pricedDays": 40,
"estimatedRevenue": 6682.0, "revpar": 72.63,
"minPrice": 110.0, "maxPrice": 210.0,
"currency": "USD", "scrapedAt": "2026-07-03T12:00:00Z"
}

Child โ€” type: "day" (one per calendar day, mirrored to a per-run days-<runId> dataset):

{
"type": "day", "isChild": true, "parentId": "35329051", "roomId": "35329051",
"date": "2026-08-01", "dayOfWeek": "Saturday", "isWeekend": true,
"available": false, "availableForCheckin": false, "availableForCheckout": true,
"bookable": false, "minNights": 2, "maxNights": 365,
"price": null, "currency": null, "scrapedAt": "2026-07-03T12:00:00Z"
}

price is a real number or null (never 0). unavailableRate, adr, estimatedRevenue, revpar are null when the underlying data is absent.

Billing

Pay-per-event. per_listing (default) charges one listing_result per listing. per_day charges one day_result per calendar-day row (~30 for a month, ~365 for a year). Day rows are always produced; billingMode only controls what is billed. See .actor/pay_per_event.json.

Keywords

airbnb scraper, airbnb availability, airbnb calendar, airbnb rates, nightly price, adr, revpar, short-term rental data, str analytics, vacation rental availability, airbnb api, booking calendar, occupancy alternative, curl_cffi, akamai bypass.

Compliance

Only publicly visible calendar data is accessed. Ensure your use complies with Airbnb's Terms of Service and applicable law.