Airbnb Scraper - Stays, Reviews, Hosts & Prices
Pricing
from $0.90 / 1,000 listing records
Airbnb Scraper - Stays, Reviews, Hosts & Prices
Scrape Airbnb stays by destination or link: nightly and total price, rating breakdown, host stats, amenities, house rules, coordinates, photos, and the full review history with text and star ratings. Dual mode, filters, incremental monitoring, resume, MCP export.
Pricing
from $0.90 / 1,000 listing records
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
19 hours ago
Last modified
Categories
Share
Airbnb Scraper: Stays, Reviews, Hosts & Prices
Scrape Airbnb stays by destination or by link, with the fields the listing page actually shows: nightly and total price, the full rating breakdown, host stats, amenities, house rules, coordinates, photos, and the complete review history with review text, star rating, date, reviewer first name and the host reply.
Built for people who need the whole result set, not the first page: a run keeps returning stays past the 270 the website's own result pager stops at, and stops when the destination genuinely runs out.
What you get
Every row is one stay. Search rows are free beyond the per-record price; turning on detail or reviews adds one enrichment event per listing.
| Group | Fields |
|---|---|
| Identity | listingId, url, title, categoryLabel, stayCategory, roomType, propertyType, subtitle |
| Price | pricePerNight, pricePerNightListed, priceTotal, priceOriginalTotal, priceCurrency, priceCurrencyRequested, priceLabel, priceQualifier, nights, checkIn, checkOut, adults |
| Ratings | rating, reviewsCount, ratingCleanliness, ratingAccuracy, ratingCheckin, ratingCommunication, ratingLocation, ratingValue, ratingDistribution, reviewTags, isGuestFavorite, isSuperhost, badges |
| Capacity | personCapacity, bedrooms, beds, bathrooms, sleepingArrangements |
| Location | latitude, longitude, city, region, country, locationSubtitle, locationLabel, locationIsVerified |
| Content | description, highlights, images, imagesCount, amenities, amenityGroups, amenitiesCount, houseRules, safetyAndProperty, cancellationPolicy, licenseInfo |
| Host | hostName, hostId, hostIsSuperhost, hostIsVerified, hostRating, hostReviewsCount, hostYearsHosting, hostResponseRate, hostResponseTime, hostProfileImageUrl, coHostNames |
| Reviews | reviews[] (reviewId, createdAt, relativeDate, rating, comment, language, reviewerName, reviewerId, reviewerLocation, reviewerPictureUrl, hostResponse, highlight, photoUrls), reviewsFetched, reviewsAverageOfFetched |
| Monitoring | changeType, changedFields, firstSeenAt, lastSeenAt, detailLoaded |
Sample row (trimmed, values replaced with placeholders):
{"kind": "listing","listingId": "1000000000000000000","url": "https://www.airbnb.com/rooms/1000000000000000000","title": "Example listing name","stayCategory": "Entire home/apt","roomType": "Entire home/apt","propertyType": "Entire rental unit","pricePerNight": 180.0,"priceTotal": 540.0,"priceCurrency": "EUR","nights": 3,"checkIn": "2026-11-10","checkOut": "2026-11-13","rating": 4.92,"reviewsCount": 57,"ratingCleanliness": 4.97,"ratingValue": 4.85,"personCapacity": 4,"bedrooms": 1,"beds": 1,"bathrooms": 1.0,"latitude": 48.8632,"longitude": 2.3521,"city": "Paris","country": "France","hostName": "Example host","hostReviewsCount": 57,"hostResponseRate": "100%","amenitiesCount": 38,"reviews": [{"reviewId": "1000000000000000001","createdAt": "2026-08-01T00:00:00Z","rating": 5,"comment": "Example review text.","reviewerName": "Example guest"}],"reviewsFetched": 30,"detailLoaded": true}
Input parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| mode | string | search | search (destination search with the fields below) or url (paste listing and search links, used verbatim) |
| searchQueries | array | ["Paris, France"] | Search mode: destinations written the way you would type them into the site, e.g. Paris, France, Kyoto, Japan |
| listingUrls | array | empty | URL mode: listing links (https://www.airbnb.com/rooms/12345678), bare listing ids, or search links, read in order |
| urls | array | empty | Alias for Listing and search links, accepted under the name other Apify actors use for URL mode |
| checkIn | string | empty | Stay start date as YYYY-MM-DD. Applies in both modes; pin it (with Check-out) when you monitor price |
| checkOut | string | empty | Stay end date as YYYY-MM-DD. Ignored unless Check-in is also set |
| adults | integer | 1 | Number of adults the stay is priced for (1 to 16) |
| children | integer | 0 | Number of children, ages 2 to 12 (0 to 15) |
| infants | integer | 0 | Number of infants under 2 (0 to 5) |
| pets | integer | 0 | Number of pets; narrows a search to stays that accept them |
| currency | string | USD | Three-letter currency code prices are quoted in, e.g. USD, EUR, GBP, AUD, JPY, BRL |
| priceMin | integer | empty | Search mode: lowest nightly price, in the currency above |
| priceMax | integer | empty | Search mode: highest nightly price, in the currency above |
| roomTypes | array | empty | Search mode: keep only these stay types (Entire home/apt, Private room, Shared room, Hotel room); empty for all |
| minBedrooms | integer | empty | Search mode: keep only stays with at least this many bedrooms (0 to 8) |
| minBeds | integer | empty | Search mode: keep only stays with at least this many beds (0 to 8) |
| minBathrooms | integer | empty | Search mode: keep only stays with at least this many bathrooms (0 to 8) |
| superhostOnly | boolean | false | Search mode: keep only stays whose host carries the Superhost badge |
| instantBookOnly | boolean | false | Search mode: keep only stays bookable without waiting for host approval |
| guestFavoriteOnly | boolean | false | Search mode: keep only stays carrying the Guest favourite badge |
| maxItems | integer | 20 | Stop after this many listing records (0 = no limit; the run stops when every search runs out) |
| fetchDetails | boolean | false | Add description, amenities, house rules, host stats and the full rating breakdown per listing; one Listing enrichment event each |
| includeReviews | boolean | false | Add the review history to every record; shares the single Listing enrichment event with the detail read |
| maxReviewsPerListing | integer | 20 | Cap on reviews collected per listing when Read the review history is on (read 24 per page); 0 skips reviews |
| resumeFromRunId | string | empty | Previous run ID or dataset ID to continue a large pull without returning listings already collected there |
| incrementalMode | boolean | false | Recurring monitoring: the first run marks every listing NEW; later runs return only NEW, UPDATED and REAPPEARED |
| stateKey | string | empty | Optional name for an incremental-mode monitoring campaign; auto-derived from the search setup when empty |
| emitUnchanged | boolean | false | Incremental mode only: also return (and bill for) listings unchanged since the last run |
| emitExpired | boolean | false | Incremental mode only: also return (and bill for) listings no longer found, once a run fully scans the tracked search |
| mcpConnectors | array | empty | Pipe results into apps you already use over Model Context Protocol; never changes the dataset output |
| notionParentPageUrl | string | empty | URL or id of the Notion page under which listing pages are created (Notion connector only) |
| maxNotifyListings | integer | 50 | Cap on listings written to each connector per run (1 to 1000); does not affect the dataset |
| proxyConfiguration | object | Apify Proxy on | Connection settings; the defaults are enough, on every Apify plan |
Two ways to run it
Destination search
Name one or more places the way you would type them into the site
(Paris, France, Kyoto, Japan, Austin, Texas). Add your stay dates, guest
counts and filters and the actor builds the search for you and returns stays
until Max items.
Filters: minimum and maximum price per night, stay type (entire home or apartment, private room, shared room, hotel room), minimum bedrooms, beds and bathrooms, Superhost only, Instant Book only, Guest favourites only.
With several destinations, each gets an equal share of Max items.
Listing and search links
Paste either shape into URL mode:
- a listing link,
https://www.airbnb.com/rooms/12345678(or just the id), read in full: description, amenities, house rules, host, rating breakdown, and the review history when you turn reviews on; - a search link,
https://www.airbnb.com/s/Paris--France/homes?..., used verbatim. Whatever your link asks for is what you get, and a link that already points at a later stretch of results continues from there. The search filter fields are deliberately not merged into a pasted link.
Both shapes can be mixed in one run.
Reviews
Turn on Read the review history and every record gains its reviews, up to Max reviews per listing (default 20, set 0 to skip). Every review carries its text, star rating, exact date, language, the reviewer's first name and profile link, and the host's public reply when there is one.
reviewsCount always reports the listing's own total, even when the cap
collected fewer, so a cap never rewrites the listing's real number.
reviewsFetched tells you how many you actually got.
Reviews share the single Listing enrichment event with the detail read, so a listing that gets both is charged once, not twice, and a listing with 300 reviews costs the same as one with 3.
Recurring monitoring and resume
- Incremental changes for scheduled runs returns only what moved. The first
run marks every listing
NEW; later runs returnNEW,UPDATEDandREAPPEARED, withchangedFieldsnaming exactly what changed. Turn on Emit unchanged or Emit expired to also getUNCHANGEDandEXPIREDrows (those are extra rows, and they are billed). EXPIREDis only produced after a run that completely scanned the tracked search: a run stopped by the item limit, a resumed run, or a run whose pages did not all load never tombstones listings it did not reach.- Without pinned stay dates the site quotes its own rolling window, so the stay dates, length and price move on their own. Those fields are then left out of the change comparison. Pin Check-in and Check-out when you want to monitor price.
- State is kept separately for every destination, filter and lookup setup. Use State key to name a campaign or to deliberately share state.
- Resume from a previous run takes a run ID or dataset ID and skips everything already collected there.
What you are charged for
Three events, all shown on the Store page:
- Actor Start, once per run.
- Listing record, one per row in the dataset.
- Listing enrichment, once per listing whose full detail or review history was read. Never per review page, never per retry, and never charged when the read failed: a failed enrichment still returns the search record, uncharged.
A run that returns only search records never triggers the enrichment event.
Send results into your apps (MCP connectors)
Optionally pipe results into the apps you already use over Model Context Protocol. Authorize a connector under Apify, Settings, API & Integrations, then name it in mcpConnectors. Notion gets a page per listing (set notionParentPageUrl); other connectors get a best-effort record write or a digest. maxNotifyListings caps how many rows go to each connector. The dataset output never changes.
Connection and reliability
- Apify Proxy with the default settings is enough, on every Apify plan.
- Requests retry at most five times with a short per-attempt timeout, rotating to a fresh exit on a transport failure, and then fail fast rather than grind.
- If enrichment reads start failing systematically, the run switches enrichment off for the rest of the run and returns search records instead of grinding every remaining listing. Nothing extra is billed for the listings it skipped.
- A run that reads nothing because requests were rejected fails loudly with a connection message. It never renders a total block as a quiet "no results".
Notes and limits
- The website's own result pager stops at 270 stays per search. A run is not bound by that number and stops when a destination returns nothing new.
priceCurrencyreports the currency that was actually rendered. When the symbol is ambiguous (a bare$) and the run's requested currency cannot break the tie, it is left empty rather than guessed.- Coordinates are the approximate location the site publishes before booking.
ratingandreviewsCountare empty on a listing that has no reviews yet. They are left empty rather than reported as zero, because the search result does not distinguish "no reviews" from "not shown".stayCategoryis empty when the result does not carry a category line at all, rather than being guessed from the property name.isGuestFavoriteistrueor empty, neverfalse: a result carries at most one badge, so another badge can displace the Guest favourite one on a listing that does carry it. Read full detail if you need it settled.stayCategoryis the property category the search result itself carries ("Room in Paris", "Hotel in 9th Arrondissement"). It overlaps the stay-type filter rather than matching it one to one: in the site's own taxonomy a hotel room is also a private room, so a Private room search legitimately returns rows whosestayCategoryisHotel room.roomTypeis the value the listing page itself publishes and only appears when detail is read.pricePerNightis the nightly rate after any discount, which is the same quantity the price filter narrows on.pricePerNightListedis the pre-discount rate the price breakdown shows, so a listing with an early-booking discount reports both.- Host and location fields can be empty on hotel-style listings, which do not publish an individual host section.
- The source re-ranks results continuously. The same first page fetched twice within a minute shares only part of its rows, so a walk's consecutive pages can repeat a few listings near the boundary. Every row is deduplicated and the dataset is unique by listing ID; a page that repeats rows the walk has already read never produces duplicate output.
- A destination the site does not recognise is answered with the site's own
exploratory worldwide results rather than an error, so a typo'd destination
returns unrelated stays instead of failing. Check the
locationLabelcolumn when a result set looks off-topic.
Local development
python3.12 -m venv .venv.venv/bin/pip install -r requirements.txt.venv/bin/python -m pytest tests -qcd . && apify run --purge