Airbnb Occupancy Scraper with Minimum Nights Calendar avatar

Airbnb Occupancy Scraper with Minimum Nights Calendar

Pricing

Pay per usage

Go to Apify Store
Airbnb Occupancy Scraper with Minimum Nights Calendar

Airbnb Occupancy Scraper with Minimum Nights Calendar

Automate Airbnb occupancy tracking with structured output of calendars, pricing, booked nights, and listing activity. Great for competitive research, forecasting, and portfolio optimization.

Pricing

Pay per usage

Rating

0.0

(0)

Developer

Scrapier

Scrapier

Maintained by Community

Actor stats

0

Bookmarked

4

Total users

1

Monthly active users

a day ago

Last modified

Share

Airbnb Occupancy Scraper — Per-Day Minimum-Nights Calendar

Airbnb Occupancy Scraper with Minimum Nights Calendar reads Airbnb's own availability-calendar endpoint and returns two result types per listing: a per-listing summary row and one row per calendar date, each carrying the minimum-nights, maximum-nights, and check-in/check-out rules Airbnb applies to that specific day. Every response is structured JSON, ready to pass directly to an LLM, index into a vector store, or feed a monitoring pipeline. Point it at a set of room URLs or IDs and get a day-by-day booking-rule ledger back — not just an open/blocked flag.

What is Airbnb Occupancy Scraper with Minimum Nights Calendar?

It is a query-driven Actor that takes one or more Airbnb listing URLs or numeric room IDs and pulls the same PdpAvailabilityCalendar data Airbnb's own site uses to render a listing's booking calendar — then keeps the per-date minimum-nights requirement that a plain availability/occupancy view discards. No Airbnb account or login is required: the Actor reads a listing's public room page to obtain the request credentials it needs, the same way a visitor's browser would. Each run returns:

  • A per-date row with available, bookable, minNights, maxNights, availableForCheckin, and availableForCheckout
  • A per-listing summary row with availabilityRate, availableDays, blockedDays, and nextAvailableDate
  • Accepts full listing URLs or bare room IDs in the same input list
  • A configurable calendar window (startMonth, startYear, monthsAhead, up to 12 months per request)
  • Server-side filters for day status (all / available / blocked) and a minimum-nights-at-most threshold
  • Automatic proxy escalation from datacenter to residential proxies when Airbnb blocks a request

What data can you get with Airbnb Occupancy Scraper with Minimum Nights Calendar?

The Actor writes two row types to the same dataset — a per-listing summary and one row per calendar date — distinguished by the rowType field.

Result TypeExtracted FieldsPrimary Use Case
Summary row (rowType: "summary")roomId, room_id, rowType, isChild, parentRoomId, totalDays, availableDays, blockedDays, availabilityRate, nextAvailableDate, minNightsMin, minNightsMax, windowStart, windowEnd, roomUrl, scrapedAtFast per-listing occupancy and minimum-stay snapshot
Day row (rowType: "day")roomId, room_id, rowType, isChild, parentRoomId, date, dayOfWeek, isWeekend, available, bookable, minNights, maxNights, availableForCheckin, availableForCheckout, roomUrl, scrapedAtPer-date booking-rule detail and minimum-stay filtering

Each row is charged as one row_result event, whether it is a summary row or a day row.

Per-date minimum-nights calendar

Most Airbnb availability scrapers stop at whether a date is open or blocked. This Actor keeps the booking-rule fields that Airbnb's own calendar response already contains for every date — minNights, maxNights, availableForCheckin, and availableForCheckout — pulled from the same request, so no extra per-date call is made. That means you can tell the difference between a date that's blocked and a date that's technically open but requires, say, a 5-night minimum stay that makes it unbookable for a short trip. The minNightsAtMost input filters day rows down to only the dates that meet a maximum minimum-stay threshold you set, and the summary row's minNightsMin / minNightsMax give the full minimum-stay range across the window in one glance:

{
"date": "2026-09-12",
"available": true,
"bookable": true,
"minNights": 3,
"maxNights": 28,
"availableForCheckin": true,
"availableForCheckout": false
}

Per-listing availability rollup

Alongside the day-by-day detail, each listing gets one summary row computed over the full requested window before any day-level filter is applied — so availabilityRate always reflects the true calendar, not a filtered subset. It's the fastest way to compare occupancy across a set of listings without paging through hundreds of date rows: availabilityRate, availableDays, blockedDays, and nextAvailableDate in a single record per room.

Why not build this yourself?

Airbnb has no public, official API for third-party access to listing calendars — the PdpAvailabilityCalendar request this Actor uses is Airbnb's internal web API, fronted by a rotating persisted-query operation ID and a per-session API key embedded in the room page's bootstrap data. Building and maintaining this yourself means reverse-engineering the current operation ID from Airbnb's JS bundles, extracting the API key from layout-init on every session, and handling the proxy and retry logic Airbnb's anti-bot layer forces on repeated requests. This Actor already does the credential extraction, the request shape, and the datacenter-to-residential proxy fallback, so you get calendar data as clean rows instead of maintaining a scraper against a moving internal endpoint.

How to scrape Airbnb with Airbnb Occupancy Scraper with Minimum Nights Calendar?

  1. Open the Actor's page in Apify Store and click Try for free (or Run) to load the input form.
  2. Enter one or more listings in listings — this is the only required field. Paste full room URLs (https://www.airbnb.com/rooms/35329051) or bare numeric room IDs (35329051).
  3. Set the calendar window with startMonth, startYear, and monthsAhead (1–12 months), and optionally narrow the output with dayStatus and minNightsAtMost.
  4. Click Start to run the Actor.
  5. Open the Dataset tab once the run finishes and export the results as JSON, CSV, Excel, or another supported format.

Example input for a single listing:

{
"listings": ["https://www.airbnb.com/rooms/35329051"],
"startMonth": 9,
"startYear": 2026,
"monthsAhead": 3,
"minNightsAtMost": 3,
"dayStatus": "available"
}

How to run multiple queries in one job

Add more entries to the listings array — each accepted URL or room ID gets its own summary row plus one day row per calendar date, all written to the same dataset in a single run. Listings are processed one at a time in the order given, so a run's total time scales with how many listings are in the list; the Actor does not document a separate concurrency setting for listings within one run.

⬇️ Input

The Actor takes one required field — listings — plus optional controls for the calendar window, day-level filters, and output shaping.

ParameterRequiredTypeDescriptionExample Value
listingsYesarrayOne or more Airbnb listing URLs or numeric room IDs["https://www.airbnb.com/rooms/35329051"]
startMonthNointegerFirst calendar month to read booking rules from (1–12). Default 129
startYearNointegerYear of the start month. Default 20262026
monthsAheadNointegerConsecutive months to keep from the start month (1–12). Default 123
minNightsAtMostNointegerOnly emit dates whose minimum-nights requirement is at most this value. 0 = off. Default 03
dayStatusNostringWhich days to emit: all, available, or blocked. Default allavailable
includeStayRulesNobooleanInclude minNights, maxNights, availableForCheckin, availableForCheckout on day rows. Default truetrue
includeSummaryNobooleanEmit one summary row per listing. Default truetrue
proxyConfigurationNoobjectApify Proxy settings; RESIDENTIAL recommended for Airbnb{"useApifyProxy": true}
{
"listings": ["35329051", "769824007018240779"],
"startMonth": 12,
"startYear": 2026,
"monthsAhead": 6,
"minNightsAtMost": 2,
"dayStatus": "all",
"includeStayRules": true,
"includeSummary": true,
"proxyConfiguration": { "useApifyProxy": true }
}

Pitfall: minNightsAtMost filters day rows by each date's minNights value even if includeStayRules is turned off — the filter still runs internally, but the minNights field that explains why a date was kept won't appear on the row. Leave includeStayRules on if you're using the minimum-nights filter and want to see the number that drove it. Dates where Airbnb doesn't report a minimum-nights value are excluded whenever the filter is active.

⬆️ Output

Results are written to the Actor's dataset as typed, consistent JSON rows — one summary row and one row per calendar date for every listing you submit — and can be exported as JSON, CSV, Excel, XML, RSS, or HTML directly from the dataset.

Scraped results

[
{
"roomId": "35329051",
"room_id": "35329051",
"rowType": "summary",
"isChild": false,
"parentRoomId": null,
"totalDays": 90,
"availableDays": 61,
"blockedDays": 29,
"availabilityRate": 0.6778,
"nextAvailableDate": "2026-09-03",
"minNightsMin": 2,
"minNightsMax": 5,
"windowStart": "2026-09-01",
"windowEnd": "2026-11-29",
"roomUrl": "https://www.airbnb.com/rooms/35329051",
"scrapedAt": "2026-07-25T14:02:11Z"
},
{
"roomId": "35329051",
"room_id": "35329051",
"rowType": "day",
"isChild": true,
"parentRoomId": "35329051",
"date": "2026-09-03",
"dayOfWeek": "Thursday",
"isWeekend": false,
"available": true,
"bookable": true,
"minNights": 2,
"maxNights": 28,
"availableForCheckin": true,
"availableForCheckout": true,
"roomUrl": "https://www.airbnb.com/rooms/35329051",
"scrapedAt": "2026-07-25T14:02:11Z"
},
{
"roomId": "35329051",
"room_id": "35329051",
"rowType": "day",
"isChild": true,
"parentRoomId": "35329051",
"date": "2026-09-04",
"dayOfWeek": "Friday",
"isWeekend": false,
"available": true,
"bookable": false,
"minNights": 5,
"maxNights": 28,
"availableForCheckin": true,
"availableForCheckout": false,
"roomUrl": "https://www.airbnb.com/rooms/35329051",
"scrapedAt": "2026-07-25T14:02:11Z"
},
{
"roomId": "35329051",
"room_id": "35329051",
"rowType": "day",
"isChild": true,
"parentRoomId": "35329051",
"date": "2026-09-05",
"dayOfWeek": "Saturday",
"isWeekend": true,
"available": false,
"bookable": false,
"minNights": null,
"maxNights": null,
"availableForCheckin": false,
"availableForCheckout": false,
"roomUrl": "https://www.airbnb.com/rooms/35329051",
"scrapedAt": "2026-07-25T14:02:11Z"
}
]

How can I use the data extracted with Airbnb Occupancy Scraper with Minimum Nights Calendar?

  • Revenue and occupancy managers: pull minNights, maxNights, and availabilityRate across your own listings or a comp set to check whether minimum-stay rules are leaving bookable-but-unbooked short gaps on the calendar, then adjust stay restrictions around low-demand dates.
  • Investment and market analysts: compare availabilityRate, nextAvailableDate, and the minNightsMin/minNightsMax range across candidate properties before acquisition, to see how aggressively current hosts are gating short stays.
  • AI engineers and LLM developers: have an agent call the Actor with a room ID, receive the day-row JSON, and ground a pricing or booking-assistant response in the listing's actual current minimum-stay and availability rules instead of a stale training-data assumption.
  • Market researchers: track how minimum-nights policies shift across a metro's listings by season — e.g., whether short-term-rental-heavy neighborhoods tighten minimum stays around peak weekends.

How do you monitor Airbnb occupancy and minimum-stay changes over time?

Occupancy monitoring means running the same set of listings on a schedule and diffing the results against the prior run to catch what changed, rather than reading one snapshot in isolation. Because each run recomputes the summary row fresh, the fields that matter to diff are availabilityRate, availableDays, blockedDays, nextAvailableDate, minNightsMin, and minNightsMax on the summary row, plus minNights and available on individual day rows if you need date-level granularity.

A typical workflow: schedule a run across your tracked room IDs → store each run's dataset → compare the new summary row against the last one per roomId → alert when availabilityRate moves more than you expect, when nextAvailableDate jumps forward (a booking landed), or when minNightsMin/minNightsMax changes (a host tightened or loosened stay rules). A rising minNightsMin on dates that were previously open at 1–2 nights is a direct signal of a host reacting to demand.

Because day rows share roomId and date, you can also join a new run's day-level minNights against the prior run's day row for the same date, which surfaces the exact dates where a host changed a stay rule rather than only a directional shift in the rollup.

This Actor itself doesn't schedule runs — use Apify's Scheduler to trigger it on a recurring interval and read each run's dataset from your own storage or via the Apify API.

Integrate Airbnb Occupancy Scraper with Minimum Nights Calendar and automate your workflow

Airbnb Occupancy Scraper with Minimum Nights Calendar works with any language or tool that can send an HTTP request.

REST API with Python

import requests
TOKEN = "your_apify_token"
ACTOR = "scrapier~airbnb-occupancy-minimum-nights-calendar-scraper"
run = requests.post(
f"https://api.apify.com/v2/acts/{ACTOR}/run-sync-get-dataset-items",
params={"token": TOKEN},
json={"listings": ["35329051"], "monthsAhead": 3},
)
rows = run.json()
day_rows = [r for r in rows if r["rowType"] == "day"]
print(day_rows[0]["minNights"], day_rows[0]["available"])

MCP for query-grounded AI agents

Any Apify Actor, including this one, is reachable through Apify's MCP server, which exposes Actors as callable tools for MCP-compatible clients such as Claude Desktop and Cursor. Register it by pointing an MCP client at Apify's MCP server endpoint and passing this Actor's ID; the agent then receives a room ID from the user, calls the tool, and grounds its answer in the returned availability and minimum-nights JSON instead of guessing.

Scheduled monitoring and delivery

Use Apify's built-in Scheduler to trigger runs on a recurring interval, and read results from the Dataset API or export them as JSON/CSV after each run. The Actor has no separate webhook-delivery feature of its own; polling the dataset after a scheduled run is the supported pattern.

Scraping publicly accessible Airbnb listing data — the same availability calendar any visitor's browser loads — is generally permissible; this Actor returns only what the listing's public calendar page already exposes, and extracts no host or guest personal information. The data here is business/product data (booking rules and availability for a rental unit), not personal data, so the relevant framing is Airbnb's Terms of Service and database-rights considerations rather than GDPR/CCPA. Scraping for internal occupancy monitoring and analysis carries a different risk profile than bulk scraping for AI-training datasets or republishing Airbnb's data as your own product. Consult your legal team for commercial use cases involving bulk data storage or redistribution.

Frequently asked questions

Does this scraper require an Airbnb account or login?

No. It reads a listing's public room page to obtain the request credentials Airbnb's own site uses, the same way a visitor's browser would — no Airbnb login, session, or cookies are needed.

What listing formats does the listings field accept?

Full Airbnb room URLs (https://www.airbnb.com/rooms/35329051) and bare numeric room IDs (35329051) in the same array; the Actor normalizes both to a room ID before requesting the calendar.

How do I control which months and days are returned?

Use startMonth + startYear to set where the window begins and monthsAhead (1–12) for how many consecutive months to keep; use dayStatus (all, available, blocked) to filter which days are emitted within that window.

How does this Actor handle Airbnb's anti-bot measures?

It retries failed requests up to three times with exponential backoff and automatically escalates from a direct connection to datacenter proxies and then residential proxies when requests keep failing, if proxy configuration is enabled.

Does it extract the per-date minimum-nights requirement, and is it real?

Yes. minNights, maxNights, availableForCheckin, and availableForCheckout come from the same PdpAvailabilityCalendar response Airbnb's own calendar UI uses for that exact date — they are not derived or estimated. If a date's minimum-nights value is missing from Airbnb's response, the field is passed through as null rather than guessed, and such dates are excluded when minNightsAtMost is active.

How many results does it return per listing?

One calendar request covers up to 12 months of dates per listing; monthsAhead is capped at 12 and controls how many of those months are kept in the output. There is no separate per-query result cap beyond the number of calendar days in the requested window.

How do I monitor occupancy and minimum-stay changes over time?

Schedule a recurring run across your tracked room IDs with Apify's Scheduler, store each run's summary row per roomId, and diff availabilityRate, nextAvailableDate, minNightsMin, and minNightsMax against the previous run to alert on the change that matters to you.

Does it work with Claude, ChatGPT, and AI agent frameworks?

Yes. It's callable as an HTTP endpoint by any agent framework, and it's also reachable through Apify's MCP server for MCP-compatible clients — either path lets an agent retrieve live availability and minimum-nights data before answering.

Can I use it without managing proxies or Airbnb credentials?

Yes. The Actor extracts its own request credentials from the public room page and, when Apify Proxy is enabled, handles the datacenter-to-residential escalation itself — you only need to supply the room URLs or IDs.

Your feedback

Found a bug, or is a field missing from your Airbnb calendar data? Let us know through the Actor's Issues tab on Apify Store or the Scrapier support contact listed on the Actor page — reports like this directly shape what we fix and add next.