Airbnb Occupancy Scraper with Minimum Nights Calendar
Pricing
Pay per usage
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
Maintained by CommunityActor stats
0
Bookmarked
4
Total users
1
Monthly active users
a day ago
Last modified
Categories
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, andavailableForCheckout - A per-listing summary row with
availabilityRate,availableDays,blockedDays, andnextAvailableDate - 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 Type | Extracted Fields | Primary Use Case |
|---|---|---|
Summary row (rowType: "summary") | roomId, room_id, rowType, isChild, parentRoomId, totalDays, availableDays, blockedDays, availabilityRate, nextAvailableDate, minNightsMin, minNightsMax, windowStart, windowEnd, roomUrl, scrapedAt | Fast 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, scrapedAt | Per-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?
- Open the Actor's page in Apify Store and click Try for free (or Run) to load the input form.
- 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). - Set the calendar window with
startMonth,startYear, andmonthsAhead(1–12 months), and optionally narrow the output withdayStatusandminNightsAtMost. - Click Start to run the Actor.
- 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.
| Parameter | Required | Type | Description | Example Value |
|---|---|---|---|---|
listings | Yes | array | One or more Airbnb listing URLs or numeric room IDs | ["https://www.airbnb.com/rooms/35329051"] |
startMonth | No | integer | First calendar month to read booking rules from (1–12). Default 12 | 9 |
startYear | No | integer | Year of the start month. Default 2026 | 2026 |
monthsAhead | No | integer | Consecutive months to keep from the start month (1–12). Default 12 | 3 |
minNightsAtMost | No | integer | Only emit dates whose minimum-nights requirement is at most this value. 0 = off. Default 0 | 3 |
dayStatus | No | string | Which days to emit: all, available, or blocked. Default all | available |
includeStayRules | No | boolean | Include minNights, maxNights, availableForCheckin, availableForCheckout on day rows. Default true | true |
includeSummary | No | boolean | Emit one summary row per listing. Default true | true |
proxyConfiguration | No | object | Apify 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, andavailabilityRateacross 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 theminNightsMin/minNightsMaxrange 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 requestsTOKEN = "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.
Is it legal to scrape Airbnb occupancy data?
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.
