Airbnb Calendar Scraper · Availability & Occupancy
Pricing
from $0.80 / 1,000 results
Airbnb Calendar Scraper · Availability & Occupancy
Extract availability calendars, occupancy rates, and pricing from any Airbnb market. Paste a city search URL to scan hundreds of listings at once, or monitor specific properties. Outputs per-listing occupancy %, blocked days, price / night, full daily calendar. Built for STR managers and investors.
Pricing
from $0.80 / 1,000 results
Rating
0.0
(0)
Developer
Corentin Robert
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
Airbnb Calendar Availability Scraper
Paste Airbnb URLs — listing URLs, search URLs, or a mix of both — and get the full availability calendar for every property. Day by day, for as many months ahead as you need: open dates, blocked dates, min/max night rules, and a calculated occupancy rate. One clean row per listing, export-ready.
Listing URL (airbnb.com/rooms/…) → calendar for that specific property.
Search URL (airbnb.com/s/Paris--France/homes) → discovers all listings in that market, fetches their calendars in one run.
No login. No API key. No Airbnb account.
Who is this for?
| You are… | Typical goal | Suggested setup |
|---|---|---|
| STR manager / conciergerie | Track competitor occupancy in your market | Paste a city search URL, monthsAhead: 6, run weekly |
| Revenue management analyst | Feed availability data to a dynamic pricing tool | API/JSON, monthsAhead: 12, scheduled run |
| Travel agency | Check availability before proposing a property | Paste the listing URL, monthsAhead: 1 or 2 |
| STR investor | Estimate annual revenue potential before buying | monthsAhead: 12 — look at occupancyRate + firstAvailableDate |
| Market research firm | Aggregate occupancy patterns at city level | Search URL + discoveryMode: full, export CSV or JSON |
| Property manager | Monitor your own listings' blocked calendars | Your own listing URLs, daily scheduled run |
What you get by default: one row per listing with city, propertyType, rooms, beds, rating, availableDays, blockedDays, occupancyRate, firstAvailableDate, and the full calendar array (one entry per day).
Part of the Airbnb Actors suite — see linked Actors for host discovery, listing depth, reviews, and atypical stays.
What you get
| Field | Type | Description |
|---|---|---|
listingId | string | Numeric Airbnb listing ID |
listingUrl | string | Canonical airbnb.com/rooms/ID URL |
listingName | string | Listing title as shown on Airbnb |
propertyType | string | e.g. Apartment in Paris, Private room in Lyon |
city | string | City from listing title |
rooms | number | Number of bedrooms |
beds | number | Number of beds |
bathrooms | number | Number of bathrooms |
searchPrice | string | Price shown in search results (e.g. $1,156) |
searchPriceQualifier | string | Price context (e.g. for 5 nights, per night) |
rating | number | Numeric rating (e.g. 4.92) — null for new listings |
reviewCount | number | Number of reviews — null for new listings |
sourceUrl | string | The search URL that found this listing |
searchRank | number | Position in discovery results |
scrapedAt | string | ISO 8601 scrape timestamp |
firstDateScanned | string | First date in the calendar window |
lastDateScanned | string | Last date in the calendar window |
currency | string | Currency used for pricing |
monthsScraped | number | Months returned by the API |
totalDays | number | Total days scanned |
availableDays | number | Days open to booking |
blockedDays | number | Days blocked (booked or owner-blocked) |
occupancyRate | number | blockedDays / totalDays × 100 (%) |
firstAvailableDate | string | Nearest open check-in date |
calendar | array | One object per day (see below) |
listingName,propertyType,city,rooms,beds,bathrooms,searchPrice, andratingcome from Airbnb's search result JSON — they are only available when a search URL is used as input. With direct listing URLs, these fields are absent.
Calendar day object
| Field | Type | Description |
|---|---|---|
date | string | YYYY-MM-DD |
available | boolean | Open for booking |
availableForCheckin | boolean | Check-in allowed |
availableForCheckout | boolean | Check-out allowed |
bookable | boolean | Fully bookable (checkin + min nights satisfied) |
minNights | number | Minimum stay from this date |
maxNights | number | Maximum stay from this date |
price | string|null | Formatted nightly price — null when not exposed by Airbnb |
Typical fill rates
| Field | Fill | Notes |
|---|---|---|
available, availableForCheckin/out, bookable | 100% | Every day returned by the API |
minNights, maxNights | 100% | Always present |
occupancyRate, firstAvailableDate | 100% | Computed from calendar |
listingName, propertyType, city, rooms, beds | ~100% (search URL only) | From search JSON |
rating, reviewCount | ~90% (search URL only) | New listings have no rating yet → null |
price | ~0–30% | Only when Airbnb exposes it via the calendar API |
How it works
- Parse input — each URL is classified as a listing URL or a search URL.
- For listing URLs — extract the listing ID and call Airbnb's
PdpAvailabilityCalendarAPI directly (up to 12 months per request, auto-heals stale hashes). - For search URLs — fetch search result pages, extract listing IDs and metadata from the embedded JSON. In Quick scan mode this is 1 pass; in Maximum coverage mode, 17 passes with different date windows, guest counts, and trip lengths (finds 4–6× more listings).
- Fetch calendars — 10 listings in parallel for all discovered listings.
- Push data — one dataset row per listing as soon as the calendar is fetched.
HTTP-only — no browser, no Airbnb login, 256 MB RAM.
Performance
| Input | Listings | Months | Wall time |
|---|---|---|---|
| 1 listing URL | 1 | 3 | ~3 s |
| 20 listing URLs | 20 | 3 | ~8 s |
| Search URL — quick scan | 100–400 | 3 | ~1–2 min |
| Search URL — maximum coverage (Paris) | 2 000–3 000 | 3 | ~10–20 min |
For 500+ listings, add proxyConfiguration to avoid rate limiting on the calendar API.
Airbnb Actors suite (Outreacher / corent1robert)
| Step | Actor | Link | Best for |
|---|---|---|---|
| 1 — Discover hosts | Airbnb Pro Host Business Email Scraper | Store → | City search, pro host contacts |
| 2 — Size portfolios | Airbnb Host Portfolio Scraper | Store → | Profile URLs → listing count, geo, room counts |
| 3 — Full listing rows | Airbnb Property Details Scraper | Store → | 30+ fields: amenities, GPS, photos, pricing |
| 4 — Atypical stays | Airbnb Atypical Stays Scraper | Store → | Castles, treehouses, boats |
| 5 — Reviews | Airbnb Reviews Scraper | Store → | Every review — rating, comment, date |
| 6 — Calendar & occupancy | This Actor | Console → | Day-level availability, occupancy rate |
Quick Start
- Open the Actor in Apify Console.
- Paste one or more Airbnb URLs in the Airbnb URLs field:
- A listing URL:
https://www.airbnb.com/rooms/25497233 - A search URL:
https://www.airbnb.com/s/Paris--France/homes - Or a mix of both
- A listing URL:
- Set Months ahead (default 3).
- For search URLs, choose Discovery mode — Quick scan for a fast sample, Maximum coverage for full market breadth.
- Click Start — results appear in the Dataset tab.
Open the Overview view for a summary table, or Flat calendar for one row per day (Excel/Sheets-friendly).
Input
Console fields
| Field | Default | Description |
|---|---|---|
urls | 1 sample listing URL | Listing URLs (/rooms/…) and/or search URLs (/s/…) — mix freely |
monthsAhead | "3" | How many months to fetch: "1", "2", "3", "6", or "12" |
discoveryMode | "quick" | For search URLs: "quick" = 1 pass (fast), "full" = 17 passes (4–6× more listings) |
API-only fields
| Field | Default | Description |
|---|---|---|
currency | auto-detected | ISO 4217 code (e.g. "EUR") — inferred from the search URL location |
proxyConfiguration | — | Apify proxy config; recommended for 500+ listing runs |
verboseLogs | false | Log API hash and per-request timing |
Example — listing URLs
{"urls": ["https://www.airbnb.com/rooms/25497233"],"monthsAhead": "3"}
Example — city quick scan
{"urls": ["https://www.airbnb.com/s/Lisbon--Portugal/homes"],"monthsAhead": "3"}
Example — full market scan
{"urls": ["https://www.airbnb.com/s/Paris--France/homes"],"monthsAhead": "3","discoveryMode": "full","proxyConfiguration": { "useApifyProxy": true }}
Example — mix
{"urls": ["https://www.airbnb.com/s/Barcelona--Spain/homes","https://www.airbnb.com/rooms/25497233"],"monthsAhead": "6","discoveryMode": "full"}
Output sample
{"listingId": "1672982064669323496","listingUrl": "https://www.airbnb.com/rooms/1672982064669323496","listingName": "Marais district - Authentic, quiet, Parisian charm","propertyType": "Apartment in Paris","city": "Paris","rooms": 1,"beds": 2,"bathrooms": 1,"searchPrice": "$1,156","searchPriceQualifier": "for 5 nights","rating": 4.92,"reviewCount": 47,"sourceUrl": "https://www.airbnb.com/s/Paris--France/homes","searchRank": 2,"scrapedAt": "2026-05-30T09:00:00.000Z","firstDateScanned": "2026-05-30","lastDateScanned": "2026-08-30","currency": "EUR","monthsScraped": 3,"totalDays": 92,"availableDays": 8,"blockedDays": 84,"occupancyRate": 91.3,"firstAvailableDate": "2026-07-13","calendar": [{"date": "2026-05-30","available": false,"availableForCheckin": false,"availableForCheckout": true,"bookable": false,"minNights": 5,"maxNights": 90,"price": null}]}
Limitations
- Availability only, no booking. Reads the public calendar — does not book, hold, or request dates.
- Price is often null. Only populated when Airbnb exposes it via the calendar API. For pricing on a specific date range, use Property Details Scraper.
- Max 24 months ahead. Airbnb's calendar returns no data beyond ~2 years out.
- Deleted / private listings return a
403— the Actor writes an error row with anerrorfield instead of crashing. - Listing metadata (city, rooms, beds…) requires a search URL. With direct listing URLs, these fields are absent.
- Rate limits on large runs. For 500+ listings, add
proxyConfigurationto avoid 429 errors. - Maximum coverage is slow on dense cities. Paris or Barcelona can yield 2 000–3 000 listings across 17 discovery passes. Expect 10–20 minutes.
Local development
npm installapify run
Output in storage/datasets/default/. Edit .actor/INPUT.json to change the input.
Support
Questions or custom workflows: corentin@outreacher.fr