Airbnb Rooms URLs Scraper with Nightly Rates and Open Dates
Pricing
from $4.99 / 1,000 results
Airbnb Rooms URLs Scraper with Nightly Rates and Open Dates
This Airbnb Rooms URLs Scraper captures listings links from any Airbnb search query. It supports pagination, filters, and location targeting. Great for analysts, developers, and data teams needing high-quality Airbnb URL datasets fast.
Pricing
from $4.99 / 1,000 results
Rating
0.0
(0)
Developer
API Empire
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
9 days ago
Last modified
Categories
Share
Airbnb Scraper — Extract Listings, Rates and Open Dates as JSON
This Airbnb scraper reads any Airbnb room listing URL and returns the full property record, a 365-day availability calendar, and Airbnb's own nightly rate quotes for sampled dates — open nights, taken nights, minimum-stay rules, open-date windows, and weekday-versus-weekend average pricing. Every response is typed, normalized JSON: no HTML, no selectors, no parsing. Paste in Airbnb room URLs, pick a calendar horizon and a currency, and get back structured availability and pricing data ready for a spreadsheet, a pricing model, or an AI agent's context window.
🧭 What is the Airbnb Rooms URLs Scraper with Nightly Rates and Open Dates?
It is an Apify Actor that turns any airbnb.com/rooms/<id> URL into three layers of structured data in one run: the property record (host, amenities, images, house rules, cancellation policy), the forward availability calendar (up to 12 months / 365 days of open and blocked nights), and Airbnb's own rate quotes for a sample of those dates. No Airbnb account or login is required — the listing page and Airbnb's internal GraphQL endpoints both answer logged-out, and the public API key used to call them is read straight off the listing page.
- 🏠 Scrape the full Airbnb listing record — host, ratings, amenities, house rules, images, cancellation policy
- 🗓️ Scrape the availability calendar — up to 365 days of
available,availableForCheckin,availableForCheckout,minNights,maxNights - 💵 Scrape nightly rate quotes — Airbnb's own price for sampled dates, with stay totals and a per-night breakdown
- 👤 Optionally enrich the host and co-host profiles
- 📦 Export everything as JSON or CSV — no proxy management, no HTML parsing
📦 What data does the Airbnb Rooms URLs Scraper with Nightly Rates and Open Dates collect?
One run returns four distinct layers of Airbnb data, all attached to the same listing row:
| Data Type | Key Fields | JSON Field Names |
|---|---|---|
| Listing record | title, property type, capacity, rating, host | title, propertyType, personCapacity, rating.guestSatisfaction, host.name |
| Availability calendar | date, open/blocked, min/max nights | calendar[].date, calendar[].available, calendar[].minNights |
| Nightly rate quotes | per-night price, stay total, breakdown line | calendar[].perNightAmount, calendar[].stayTotalAmount, calendar[].priceBreakdownLabel |
| Host & co-host profiles (optional) | name, about, superhost status | host.profile.about, host.isSuperHost, coHosts[].name |
└── Need more Airbnb data?
This Actor is the calendar-and-rates variant of the base Airbnb-Rooms-URLs-Scraper published in the same API-Empire family — every field the base listing scraper returns is still produced here first, with the calendar and rate fields merged on top. If all you need is the property record with no calendar or pricing, set calendarMonths to 0 and this Actor behaves like the plain listing scraper at no extra request cost.
🛠️ Why not build this yourself?
Airbnb does not publish a public, self-serve API for reading another host's listing, calendar or pricing data — the "Airbnb API" that exists is a closed, approval-gated connectivity program for property-management software managing its own inventory, not a way to look up arbitrary listings. Building a reader yourself means reverse-engineering Airbnb's internal GraphQL endpoints, keeping the persisted-query hashes current as Airbnb rotates them, presenting a TLS fingerprint that survives Akamai, and maintaining a proxy escalation path for soft blocks — all before writing a single line of pricing logic.
That maintenance burden is what this Actor absorbs. It ships with the current persisted-query hashes and public API key already wired up, a curl_cffi client impersonating a real Chrome TLS fingerprint, and a none → datacenter → residential proxy ladder that only escalates when a response comes back without the expected data container. You still choose when a plain HTTP client to Airbnb's own public listing page is enough versus when you need this Actor's calendar and rate layer.
🎯 Why do developers and teams scrape Airbnb listings?
└── For revenue managers and pricing analysts
avgPerNightAmount, weekdayAvgPerNightAmount and weekendAvgPerNightAmount give a comparable rate curve across a competitor set without opening each listing by hand. Point startUrls at every listing in a submarket, set rateSampling to spread-across-horizon, and read monthlyAvailability[] to see how both occupancy and price move month to month — the input for a dynamic-pricing model or a weekly rate review.
└── For real estate and short-term-rental investors
openNights, takenNights, availabilityRate and longestOpenRunNights are Airbnb's own occupancy signals for a listing, computed over the full 365-day horizon regardless of the availableNightsOnly filter. Combined with minNightsLowest / minNightsHighest, this is enough to compare how booked-out and how flexible a set of properties are before underwriting one.
└── For AI engineers and agent builders
The calendar and rate blocks are already typed JSON — a booking agent can pass openDateWindows[] and calendar[].perNightAmount straight into a tool call without writing an HTML parser, and requestedStayQuote.quoteStatus tells the agent in plain text why a specific stay is not bookable (not-bookable: the stay is shorter than the 3-night minimum on 2026-08-05) instead of a bare false.
└── For short-term-rental market researchers
Because every field is read from Airbnb's own calendar and quote responses rather than estimated, calendarPriceCoverage (quoted/days) and datesQuoteFailed let a researcher report exactly how much of a market's forward pricing is actually observable versus how much Airbnb declined to quote — a distinction that matters for any published occupancy or rate study.
⚡ How to scrape Airbnb listings (step by step)
- Open the Actor on its Apify Store page and click Run, or call it with
apify_clientfrom your own code. - Provide the one required input,
startUrls— one Airbnb room URL per line, for examplehttps://www.airbnb.com/rooms/12937. - Set the calendar and rate options that fit the job:
calendarMonthsfor the horizon,includeNightlyPricesandmaxPricedDatesfor the rate quotes,rateSamplingfor which dates get quoted. - Start the run. Each listing URL is fetched and processed independently, up to five in parallel.
- Download the results as JSON or CSV from the run's dataset, or read them with the Apify API /
apify_client.
└── What to do when Airbnb changes its structure
Airbnb's page layout and internal GraphQL schema are not a stable public contract, so any scraper built against them needs upkeep. This Actor is maintained against Airbnb's current markup and persisted-query hashes, and the output schema stays stable — field names and types on your end don't change even when Airbnb's internal payload does.
⬇️ Input
| Parameter | Required | Type | Description | Example Value |
|---|---|---|---|---|
startUrls | Yes | array | One Airbnb room link per line. A plain keyword is accepted but not useful — see the limitation below. | ["https://www.airbnb.com/rooms/12937"] |
calendarMonths | No | integer (0–12, default 12) | Months of calendar to read, counted from the horizon start. 0 skips the calendar entirely. | 12 |
calendarStartDate | No | string (datepicker) | YYYY-MM-DD or relative (2 months). Empty falls back to checkIn, then today. | 2026-09-01 |
availableNightsOnly | No | boolean (default false) | ON drops booked/blocked nights from calendar[]. Counters (openNights, takenNights, month roll-ups) always cover the full horizon regardless. | false |
includeNightlyPrices | No | boolean (default true) | ON adds a rate quote (stay total, breakdown, per-night figure) to each sampled date. One extra request per quoted date. | true |
stayLengthNights | No | integer (1–28, default 1) | Nights per quote. Raised automatically to a date's own minNights when that is higher; the length actually used comes back in quoteNights. | 2 |
maxPricedDates | No | integer (0–365, default 20) | Hard cost cap on quoted dates per listing. 0 quotes nothing, 365 quotes every open check-in date. | 20 |
rateSampling | No | string, enum: soonest-first, spread-across-horizon (default soonest-first) | soonest-first prices the next open dates; spread-across-horizon samples evenly for a seasonality curve. | spread-across-horizon |
checkIn | No | string (datepicker) | YYYY-MM-DD. Also the calendar horizon start when calendarStartDate is empty. | 2026-09-10 |
checkOut | No | string (datepicker) | YYYY-MM-DD. With checkIn set, this pair is quoted on its own and returned in requestedStayQuote. | 2026-09-13 |
adults | No | integer (minimum 1) | Adults priced on the listing page and every rate quote. Empty defaults to 1 adult. | 2 |
children | No | integer (minimum 0) | Children (2–12). Affects price on listings that charge per extra guest. | 0 |
infants | No | integer (minimum 0) | Infants under 2. Usually free, but can trip occupancy rules. | 0 |
pets | No | integer (minimum 0) | Pets travelling with the guests. Some listings add a pet fee. | 0 |
currency | No | string, enum of 48 currency codes (default USD) | Every quoted rate is expressed in this currency — Airbnb converts it server-side, not this Actor. | USD |
locale | No | string, enum of 93 locale codes (default en-US) | Language and region used for listing text and price-breakdown wording. | en-US |
enrichUserProfiles | No | boolean (default false) | ON adds one profile request per host and co-host and nests it under host.profile. Slower, unrelated to pricing. | false |
proxyConfiguration | No | object (proxy editor) | Starts with no proxy; escalates to datacenter, then residential, only when a response lacks the expected data container. | {"useApifyProxy": false} |
{"startUrls": ["https://www.airbnb.com/rooms/53997462","https://www.airbnb.com/rooms/12937"],"calendarMonths": 12,"calendarStartDate": "","availableNightsOnly": false,"includeNightlyPrices": true,"stayLengthNights": 2,"maxPricedDates": 20,"rateSampling": "spread-across-horizon","checkIn": "2026-09-10","checkOut": "2026-09-13","adults": 2,"children": 0,"infants": 0,"pets": 0,"currency": "USD","locale": "en-US","enrichUserProfiles": false,"proxyConfiguration": { "useApifyProxy": false }}
Common pitfall: startUrls also accepts a plain keyword, but Airbnb's rendered search HTML carries zero /rooms/ links — the results only exist in the page's JSON bootstrap, and that bootstrap held 0 room links when last measured (2026-08-02). Paste room URLs directly; don't rely on keyword input.
⬆️ Output
One dataset row per listing, pushed the moment that listing finishes processing. Export as JSON or CSV directly from the run's dataset.
└── Scraped listing record
{"requestedUrl": "https://www.airbnb.com/rooms/12937","id": "12937","title": "1 Stop to Midtown! Private Bedroom, Landmark House","seoTitle": "1 Stop to Midtown! Private Bedroom, Landmark House - Townhouses for Rent in Queens, New York, United States - Airbnb","url": "https://www.airbnb.com/rooms/12937","propertyType": "Private room in townhouse","roomType": "private_room","personCapacity": 2,"coordinates": { "latitude": 40.7282, "longitude": -73.9022 },"location": "Queens, New York, United States","rating": {"accuracy": 4.9,"cleanliness": 4.86,"communication": 4.95,"guestSatisfaction": 4.92,"reviewsCount": 489},"host": {"id": "50124","name": "Regis","isSuperHost": true,"ratingAverage": 4.92,"ratingCount": 489,"timeAsHost": { "years": 9, "months": 3 }},"coHosts": [],"amenities": [ { "title": "Bathroom", "values": [ { "title": "Hair dryer", "available": true } ] } ],"houseRules": { "general": [ { "title": "During your stay", "values": [ { "title": "No smoking" } ] } ] },"images": [ { "caption": "Bedroom", "imageUrl": "https://a0.muscache.com/im/pictures/example.jpg" } ],"checkIn": null,"checkOut": null,"language": "en-US","timestamp": "2026-08-04T12:00:00Z","scrapedAt": "2026-08-04T12:00:00Z"}
The listing record carries these fields on every row, in addition to the ones shown above: descriptionOriginalLanguage, metaDescription, sharingConfigTitle, thumbnail, androidLink, iosLink, homeTier, locationSubtitle, locationDescriptions, description, htmlDescription, subDescription, brandHighlights, breadcrumbs, highlights, cancellationPolicies, host.contextualUserId, host.profileImage, host.isVerified, host.highlights, host.about, host.hostDetails, and — only when enrichUserProfiles is true — host.profile.
└── Availability calendar and rate quotes
The calendar summary sits on the same row as the listing fields above:
{"calendarMonthsRequested": 12,"calendarHorizonStart": "2026-08-04","calendarDaysReturned": 365,"calendarFirstDate": "2026-08-04","calendarLastDate": "2027-08-03","openNights": 199,"takenNights": 166,"availabilityRate": 0.5452,"nextAvailableDate": "2026-08-08","openDateWindowsCount": 14,"openDateWindows": [{ "startDate": "2026-08-08", "endDate": "2026-08-30", "nights": 23, "checkInAllowed": true }],"nextOpenWindow": { "startDate": "2026-08-08", "endDate": "2026-08-30", "nights": 23, "checkInAllowed": true },"longestOpenRunNights": 117,"longestOpenRunStart": "2026-11-01","longestOpenRunEnd": "2027-02-25","minNightsLowest": 2,"minNightsHighest": 3,"weekdayOpenNights": 142,"weekendOpenNights": 57,"rateCurrency": "USD","avgPerNightAmount": 316.77,"minPerNightAmount": 303,"maxPerNightAmount": 329.33,"weekdayAvgPerNightAmount": 314.74,"weekendAvgPerNightAmount": 321.5,"datesQuoted": 20,"datesQuoteFailed": 0,"calendarPriceCoverage": "20/365","calendarStatus": "ok","requestedStayQuote": null,"monthlyAvailability": [{ "month": "2026-08", "daysReturned": 28, "openNights": 23, "takenNights": 5, "availabilityRate": 0.8214, "nightsQuoted": 20, "avgPerNightAmount": 316.77 }],"calendar": [{"date": "2026-08-08","dayOfWeek": "Saturday","isWeekendNight": true,"available": true,"availableForCheckin": true,"availableForCheckout": false,"bookable": true,"minNights": 3,"maxNights": 1125,"quoteCheckIn": "2026-08-08","quoteCheckOut": "2026-08-10","quoteNights": 3,"stayTotalFormatted": "$959","stayTotalAmount": 959,"stayTotalQualifier": "for 3 nights","staySubtotalFormatted": "$959.00","staySubtotalAmount": 959,"priceBreakdownLabel": "3 nights x $319.67","perNightFormatted": "$319.67","perNightAmount": 319.67}]}
| Field | Type | Meaning |
|---|---|---|
calendarMonthsRequested | integer | Months asked for (calendarMonths echoed). |
calendarHorizonStart | string | Date the horizon starts from. |
calendarDaysReturned | integer | Days Airbnb returned (365 for a full 12-month horizon). |
calendarFirstDate / calendarLastDate | string | Range actually covered. |
openNights / takenNights | integer | Full-horizon night counts, unaffected by availableNightsOnly. |
availabilityRate | number | openNights / calendarDaysReturned, 4 decimal places. |
nextAvailableDate | string | First open night in the horizon. |
openDateWindowsCount / openDateWindows[] / nextOpenWindow | integer / array / object | Contiguous open runs — count, full list, and the first one. |
longestOpenRunNights / longestOpenRunStart / longestOpenRunEnd | integer / string / string | The single longest open stretch. |
minNightsLowest / minNightsHighest | integer | Minimum-stay range seen across the horizon. |
weekdayOpenNights / weekendOpenNights | integer | Open nights split Friday+Saturday (weekend) vs the rest. |
rateCurrency | string | Currency of the quotes (echoes currency). |
avgPerNightAmount / minPerNightAmount / maxPerNightAmount | number | Over quoted dates only. |
weekdayAvgPerNightAmount / weekendAvgPerNightAmount | number | Same, split by night type. |
datesQuoted / datesQuoteFailed | integer | Dates that did / did not return a price. |
calendarPriceCoverage | string | quoted/days. |
calendarStatus | string | ok, skipped-calendarMonths-0, calendar-unavailable or no-listing-id. |
monthlyAvailability[] | array | Per month: month, daysReturned, openNights, takenNights, availabilityRate, nightsQuoted, avgPerNightAmount. |
requestedStayQuote | object or null | Populated only when both checkIn and checkOut are set — see below. |
calendar[] | array | Day rows: date, dayOfWeek, isWeekendNight, available, availableForCheckin, availableForCheckout, bookable, minNights, maxNights, quoteCheckIn, quoteCheckOut, quoteNights, stayTotalFormatted, stayTotalAmount, stayTotalQualifier, staySubtotalFormatted, staySubtotalAmount, priceBreakdownLabel, perNightFormatted, perNightAmount. |
When checkIn and checkOut are both set, requestedStayQuote carries checkIn, checkOut, nights, quoted (boolean), quoteStatus (quoted, or not-bookable: <reason> derived from the calendar), plus the same stayTotalFormatted/stayTotalAmount/perNightAmount-style fields as a calendar[] row.
🔍 How does this compare to other Airbnb scrapers?
| Feature | This Actor | Generic listing-only Airbnb scraper |
|---|---|---|
| Property record (host, amenities, images, policies) | ✅ | ✅ |
| Forward availability calendar (365 days) | ✅ | ❌ |
| Airbnb's own nightly rate quotes, min-nights aware | ✅ | ❌ |
| Weekday vs weekend average pricing | ✅ | ❌ |
| Optional host / co-host profile enrichment | ✅ | Not documented |
| Output format | Typed JSON | Varies |
If you're building an AI agent or a RAG pipeline, the output-format row is the decision-maker — parsing HTML inside an agent loop is a reliability failure mode, not a feature. Everything above is read from Airbnb's own calendar and quote responses; nothing is estimated.
🔢 How many results can you scrape with the Airbnb Rooms URLs Scraper with Nightly Rates and Open Dates?
There is no cap on how many startUrls you can submit — every URL becomes one dataset row, processed up to 5 listings concurrently. Within each listing, the real ceilings come from Airbnb and from the input schema itself: the calendar can only reach 12 months / 365 days forward (calendarMonths maximum, matching Airbnb's own calendar service), a rate quote can cover at most 28 nights (stayLengthNights maximum), and at most 365 dates can be priced per listing (maxPricedDates maximum) — each priced date costs one extra request, so maxPricedDates: 365 means roughly 366 requests for that one listing. A keyword instead of a URL is capped internally at 20 resolved rooms, but that path currently returns 0 results (see the input pitfall above), so a keyword is not a practical way to scrape more listings today. A listing that never returns its data container (de-listed, private, or persistently blocked) produces no row at all rather than a partial or error record.
🔌 Integrate the Airbnb Rooms URLs Scraper with Nightly Rates and Open Dates and automate your workflow
This Actor works with any language or tool that can send an HTTP request — the Apify API sits behind every run.
└── REST API integration
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_API_TOKEN>")run = client.actor("<YOUR_USERNAME>/airbnb-rooms-urls-scraper-with-nightly-rates-and-open-dates").call(run_input={"startUrls": ["https://www.airbnb.com/rooms/12937"],"calendarMonths": 12,"maxPricedDates": 20,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["id"], item["avgPerNightAmount"], item["openNights"])
Works in Python, Node.js, Go, Ruby or cURL — any client that can call the Apify API. Runs can also be triggered on a recurring schedule or wired to a webhook from the Apify Console, with no code beyond the initial setup.
⚖️ Is it legal to scrape Airbnb listings?
Yes. This Actor reads only publicly available Airbnb pages — the same listing, calendar and pricing information any visitor sees without logging in — and returns it as structured data instead of rendered HTML. The core output here is business and product data (listing details, availability, pricing), which is governed by Airbnb's Terms of Service and database-rights law, not by GDPR or CCPA, which apply to personal data. The optional enrichUserProfiles input is the exception: turning it on pulls a host's publicly posted name, photo and bio, which is personal data, and GDPR/CCPA can apply to how it is stored and reused. Consult legal counsel for commercial use cases involving bulk personal data.
❓ Frequently asked questions
└── Does it work without an Airbnb account?
Yes. Neither the listing page nor the calendar/quote endpoints require a login; the public API key they need is read straight off the listing page you scrape.
└── How often is the scraped data updated?
Every run fetches the listing, calendar and rate quotes live from Airbnb at the moment it runs — nothing is cached or served from a previous run.
└── What happens if a listing is de-listed or removed?
A de-listed or private room still answers with HTTP 200, but with an empty payload node. The Actor recognizes this as "unavailable" rather than a block, logs a warning, and produces no dataset row for that URL — it does not push a null or error record.
└── Can I scrape private or login-gated Airbnb content?
No. Only listing pages, calendars and rate quotes that Airbnb serves to a logged-out visitor are returned. Anything behind an Airbnb account login is out of scope.
└── How is usage charged?
This Actor charges the row_result event once per listing that is successfully scraped and pushed to the dataset. A listing that fails, is blocked, or is de-listed produces no dataset row and is not charged — only a log line records what happened.
└── Does it work for AI agent workflows and LLM pipelines?
Yes. There is no dedicated MCP server for this Actor; it is called like any other Apify Actor over the REST API or apify_client, and every response is typed JSON that can be passed directly into an agent tool call or an LLM context window without a parsing step.
└── How does it handle Airbnb's anti-bot system?
Airbnb sits behind Akamai. The Actor presents a real Chrome TLS fingerprint via curl_cffi, starts every run with no proxy, and escalates to Apify's datacenter proxy and then residential proxy only when a response comes back without the expected data container — with a fresh residential exit IP on each retry, up to 3 residential attempts.
└── How does this compare to other Airbnb scrapers?
Most Airbnb scrapers stop at the static listing page — property details, photos, host info — with no live availability or pricing. This Actor adds the 365-day calendar and Airbnb's own per-date rate quotes on top, with the stay length automatically raised to match a date's minimum-nights rule instead of returning nothing.
└── Does it return data in a format LLMs can use directly?
Yes. Every field is typed, normalized JSON with stable field names — no HTML, no selectors, no parsing required before passing it to an LLM or indexing it into a vector store.
└── Can I use it without managing proxies?
Yes. The default proxyConfiguration starts every run with no proxy at all and only escalates to Apify's datacenter, then residential, proxies when Airbnb stops returning the expected data.
└── What happens when Airbnb changes its structure or blocks the scraper?
The Actor is maintained against Airbnb's current page structure and internal API. The output schema stays stable on your end — field names and types don't change even when Airbnb's markup does.
💬 Your feedback
Found a bug or missing a field? We want to know. Reach out through the Actor's page on the Apify Store or open an issue with the API-Empire team's support channel — reports of broken fields or new Airbnb page variants are what keep this Actor's schema accurate.
