Airbnb Scraper - Stays, Reviews, Hosts & Prices avatar

Airbnb Scraper - Stays, Reviews, Hosts & Prices

Pricing

from $0.90 / 1,000 listing records

Go to Apify Store
Airbnb Scraper - Stays, Reviews, Hosts & Prices

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

Abot API

Maintained by Community

Actor 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.

GroupFields
IdentitylistingId, url, title, categoryLabel, stayCategory, roomType, propertyType, subtitle
PricepricePerNight, pricePerNightListed, priceTotal, priceOriginalTotal, priceCurrency, priceCurrencyRequested, priceLabel, priceQualifier, nights, checkIn, checkOut, adults
Ratingsrating, reviewsCount, ratingCleanliness, ratingAccuracy, ratingCheckin, ratingCommunication, ratingLocation, ratingValue, ratingDistribution, reviewTags, isGuestFavorite, isSuperhost, badges
CapacitypersonCapacity, bedrooms, beds, bathrooms, sleepingArrangements
Locationlatitude, longitude, city, region, country, locationSubtitle, locationLabel, locationIsVerified
Contentdescription, highlights, images, imagesCount, amenities, amenityGroups, amenitiesCount, houseRules, safetyAndProperty, cancellationPolicy, licenseInfo
HosthostName, hostId, hostIsSuperhost, hostIsVerified, hostRating, hostReviewsCount, hostYearsHosting, hostResponseRate, hostResponseTime, hostProfileImageUrl, coHostNames
Reviewsreviews[] (reviewId, createdAt, relativeDate, rating, comment, language, reviewerName, reviewerId, reviewerLocation, reviewerPictureUrl, hostResponse, highlight, photoUrls), reviewsFetched, reviewsAverageOfFetched
MonitoringchangeType, 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

ParameterTypeDefaultDescription
modestringsearchsearch (destination search with the fields below) or url (paste listing and search links, used verbatim)
searchQueriesarray["Paris, France"]Search mode: destinations written the way you would type them into the site, e.g. Paris, France, Kyoto, Japan
listingUrlsarrayemptyURL mode: listing links (https://www.airbnb.com/rooms/12345678), bare listing ids, or search links, read in order
urlsarrayemptyAlias for Listing and search links, accepted under the name other Apify actors use for URL mode
checkInstringemptyStay start date as YYYY-MM-DD. Applies in both modes; pin it (with Check-out) when you monitor price
checkOutstringemptyStay end date as YYYY-MM-DD. Ignored unless Check-in is also set
adultsinteger1Number of adults the stay is priced for (1 to 16)
childreninteger0Number of children, ages 2 to 12 (0 to 15)
infantsinteger0Number of infants under 2 (0 to 5)
petsinteger0Number of pets; narrows a search to stays that accept them
currencystringUSDThree-letter currency code prices are quoted in, e.g. USD, EUR, GBP, AUD, JPY, BRL
priceMinintegeremptySearch mode: lowest nightly price, in the currency above
priceMaxintegeremptySearch mode: highest nightly price, in the currency above
roomTypesarrayemptySearch mode: keep only these stay types (Entire home/apt, Private room, Shared room, Hotel room); empty for all
minBedroomsintegeremptySearch mode: keep only stays with at least this many bedrooms (0 to 8)
minBedsintegeremptySearch mode: keep only stays with at least this many beds (0 to 8)
minBathroomsintegeremptySearch mode: keep only stays with at least this many bathrooms (0 to 8)
superhostOnlybooleanfalseSearch mode: keep only stays whose host carries the Superhost badge
instantBookOnlybooleanfalseSearch mode: keep only stays bookable without waiting for host approval
guestFavoriteOnlybooleanfalseSearch mode: keep only stays carrying the Guest favourite badge
maxItemsinteger20Stop after this many listing records (0 = no limit; the run stops when every search runs out)
fetchDetailsbooleanfalseAdd description, amenities, house rules, host stats and the full rating breakdown per listing; one Listing enrichment event each
includeReviewsbooleanfalseAdd the review history to every record; shares the single Listing enrichment event with the detail read
maxReviewsPerListinginteger20Cap on reviews collected per listing when Read the review history is on (read 24 per page); 0 skips reviews
resumeFromRunIdstringemptyPrevious run ID or dataset ID to continue a large pull without returning listings already collected there
incrementalModebooleanfalseRecurring monitoring: the first run marks every listing NEW; later runs return only NEW, UPDATED and REAPPEARED
stateKeystringemptyOptional name for an incremental-mode monitoring campaign; auto-derived from the search setup when empty
emitUnchangedbooleanfalseIncremental mode only: also return (and bill for) listings unchanged since the last run
emitExpiredbooleanfalseIncremental mode only: also return (and bill for) listings no longer found, once a run fully scans the tracked search
mcpConnectorsarrayemptyPipe results into apps you already use over Model Context Protocol; never changes the dataset output
notionParentPageUrlstringemptyURL or id of the Notion page under which listing pages are created (Notion connector only)
maxNotifyListingsinteger50Cap on listings written to each connector per run (1 to 1000); does not affect the dataset
proxyConfigurationobjectApify Proxy onConnection settings; the defaults are enough, on every Apify plan

Two ways to run it

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.

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 return NEW, UPDATED and REAPPEARED, with changedFields naming exactly what changed. Turn on Emit unchanged or Emit expired to also get UNCHANGED and EXPIRED rows (those are extra rows, and they are billed).
  • EXPIRED is 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.
  • priceCurrency reports 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.
  • rating and reviewsCount are 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".
  • stayCategory is empty when the result does not carry a category line at all, rather than being guessed from the property name.
  • isGuestFavorite is true or empty, never false: 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.
  • stayCategory is 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 whose stayCategory is Hotel room. roomType is the value the listing page itself publishes and only appears when detail is read.
  • pricePerNight is the nightly rate after any discount, which is the same quantity the price filter narrows on. pricePerNightListed is 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 locationLabel column 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 -q
cd . && apify run --purge