Airbnb Scraper - Listings, Prices & Ratings API, No 240 Cap
Pricing
from $1.20 / 1,000 listings
Airbnb Scraper - Listings, Prices & Ratings API, No 240 Cap
Scrape Airbnb search results as clean JSON: price, nightly/total breakdown, rating, coordinates, photos, room type. Splits large searches past Airbnb's 240-listing cap. Optional guest reviews (no reviewer identity), availability calendars with an occupancy proxy, and per-listing detail enrichment.
Pricing
from $1.20 / 1,000 listings
Rating
0.0
(0)
Developer
TRUONG VAN HOA
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
12 days ago
Last modified
Categories
Share
Airbnb Scraper API — listings, prices & ratings, no 240-result limit
An Airbnb data API with no login and no API key: search by location or paste your own
airbnb.com/s/... search URL and get every matching listing as clean, flat JSON — price (nightly
and total, with the full breakdown), star rating, review count, coordinates, photos, room
type, superhost/guest-favorite badges. Turn on Exhaustive mode and it automatically works
around Airbnb's own page-cursor limit instead of silently truncating at ~240-270 results like
every other Airbnb scraper on the Store.
- Breaks the 240-result cap. Airbnb's own search pagination caps out at 15 pages (~270
results) per query, no matter how many listings actually match. The main incumbent Airbnb
scraper just returns that capped page and stops — you get 240 rows even if 4,000 listings
match. This Actor detects the cap live (via the page's own price histogram and map-bounds hint,
no extra geocoding calls) and recursively splits the search into non-overlapping price bands,
then map quadrants if a price band is still capped, merging and de-duplicating everything by
listing id until it is below the cap,
maxItemsis reached, or a depth limit is hit (logged loudly if so — see Limits below). - Real nightly and total prices. Airbnb shows a total-for-the-stay price on search cards, not
a nightly rate. This Actor reads the per-listing night count from the page's own text (it can
vary listing-to-listing due to minimum-stay rules, even for the same search dates) and derives
priceNightlyfrompriceTotal / nights, plus the rawpriceBreakdownline items. - Optional deep enrichment. Turn on
includeDetailsto fetch each listing's own page for description, amenities, house rules, host name + superhost flag, bedrooms/beds/baths and the six sub-ratings (cleanliness, accuracy, check-in, communication, location, value). - Guest reviews, without reviewer identity. Turn on
includeReviewsto get one record per review (type: "review"): date, star rating, language, the review text as published, an English/locale translation when Airbnb offers one, and the host's reply. About 10x cheaper than per-review pricing of $0.005 elsewhere on the Store. Reviewer names, first names, photos, profile IDs and profile links are never collected or output. - Availability calendar and occupancy proxy. Turn on
includeCalendarto add a per-day calendar to each listing (available or not, minimum and maximum nights) plusavailableDaysNext30,availableDaysNext90andoccupancyProxy. - Listing URLs without a search. Paste listing links or IDs in
listingUrlsto pull reviews, calendars or details for exactly those listings. - Pay only for results. No monthly rental; duplicates and filtered-out listings are free.
Use cases
| Use case | How |
|---|---|
| STR investors / revenue managers | locations + dates, exhaustive: true, maxItems in the thousands → every comparable listing's price and rating for a market, not just the first 240 |
| AirDNA-alternative market research | Same market, multiple date ranges over time (scheduled runs) → nightly-price and occupancy-proxy (isNew/reviewsCount) trends without a data-subscription contract |
| Property managers | startUrls with your own saved search filters (room type, price band, amenities) → a live comparable set for a specific neighborhood |
| Review mining / sentiment analysis | listingUrls or a search + includeReviews, reviewsSort, reviewsSince → review text, rating, language and host replies for your comparable set; feed them into your own sentiment or topic model |
| Availability & occupancy proxy for STR investors | includeCalendar with calendarMonths on a market search, scheduled weekly → free days in the next 30/90 days and an occupancyProxy per listing, and how it moves over time |
| Price/rating dashboards | includeDetails: true for a shortlist of listing URLs → full amenity and sub-rating breakdown per competitor |
Input
| Field | Example | Notes |
|---|---|---|
locations | ["Lisbon, Portugal"] | Free-text place names; Airbnb resolves them (redirect) to the canonical search page |
startUrls | ["https://www.airbnb.com/s/...] | Use your own saved Airbnb search URL(s) instead of/with locations. Every query param on the URL (price, map bounds, amenities, room type, dates...) is preserved |
checkIn / checkOut | 2026-11-05 / 2026-11-08 | YYYY-MM-DD. Leave both empty for flexible-date pricing |
adults, children, infants, pets | 2, 0, 0, 0 | Guest counts |
priceMin / priceMax | 40 / 150 | Nightly price filter, in currency |
minBedrooms, minBeds, minBathrooms | 1 | |
roomType | any | entire_home | private_room | |
currency | "USD" | 3-letter code |
locale | "en" | Language for listing text |
maxItems | 100 | Hard cap on saved (and charged) listings |
exhaustive | true (default) | Split past the ~270-result single-query cap instead of returning just the capped page |
includeDetails | false | Fetch each listing's own page for description/amenities/house rules/host/sub-ratings. One extra request + one listing-details charge per listing |
listingUrls | ["https://www.airbnb.com/rooms/12345", "67890"] | Listing links or numeric IDs; runs reviews/calendar/details for exactly these without a search. listing-record is charged only when includeDetails fills the listing record with the full listing data; with reviews and/or calendar alone only those add-ons are charged. If locations, startUrls and listingUrls are all empty a small default search (Lisbon) runs |
includeReviews | false | One type: "review" record per review. Charged per review |
maxReviewsPerListing | 50 (max 1000) | Cap per listing; 50 reviews = one request |
reviewsSort | recent | relevant | Which reviews come first |
reviewsSince | 2025-06-30 | Skip older reviews; with recent the scan stops at the first older one |
includeCalendar | false | Adds calendar[] and the summary fields to each listing. Charged once per listing calendar fetched |
calendarMonths | 3 (max 12) | Months ahead, starting today (a month counts as at least 30 days, so 3 months always cover the 90-day summary) |
maxConcurrency | 3 | Parallel detail-page fetches when includeDetails is on |
proxyConfiguration | { "useApifyProxy": true } | Apify Proxy (datacenter, included in every Apify plan) or your own proxy URLs; when set, every request (search pages, listing pages, review/calendar calls, JS bundle reads) goes through it from the first request. Recommended: Airbnb blocks some datacenter IPs outright (see Blocking below) |
autoProxyFallback | true | When the run has no proxy and Airbnb blocks it, switch to Apify Proxy for the rest of the run instead of giving up. Set false to never use Apify Proxy |
Example 1: one city, dates, plain search
{"locations": ["Lisbon, Portugal"],"checkIn": "2026-11-05","checkOut": "2026-11-08","maxItems": 200}
Example 2: exhaustive market census past the 270 cap
{"locations": ["Lisbon, Portugal"],"checkIn": "2026-11-05","checkOut": "2026-11-08","exhaustive": true,"maxItems": 3000}
Example 3: your own saved search + detail enrichment
{"startUrls": ["https://www.airbnb.com/s/homes?query=Coimbra%2C%20Portugal&adults=2&checkin=2026-10-12&checkout=2026-10-15&price_min=40&price_max=120"],"includeDetails": true,"maxItems": 50}
Example 4: reviews and calendars for specific listings
{"listingUrls": ["https://www.airbnb.com/rooms/14226815", "20778206"],"includeReviews": true,"maxReviewsPerListing": 100,"reviewsSince": "2025-01-01","includeCalendar": true,"calendarMonths": 3}
Output
Every record has a type: "listing" or "review". Listing records look like this (real output, from a live run against Lisbon, Portugal):
{"type": "listing","id": "557949219885897700","url": "https://www.airbnb.com/rooms/557949219885897700","name": "St. Anthony V","title": "Apartment in Santa Maria Maior","roomType": "entire_home","searchLocation": "Lisbon, Portugal","latitude": 38.71354,"longitude": -9.1357,"rating": 4.92,"reviewsCount": 201,"isNew": false,"isSuperhost": false,"isGuestFavorite": true,"priceTotal": 381,"priceNightly": 127,"priceOriginalTotal": null,"nights": 3,"currency": "USD","priceLabel": "$381","priceBreakdown": [{ "description": "3 nights x $126.98", "price": 380.93, "priceLabel": "$380.93" }],"photos": ["https://a0.muscache.com/im/pictures/miso/Hosting-557949219885897700/original/24d31335-....jpeg"],"checkIn": "2026-11-05","checkOut": "2026-11-08","adults": 2,"scrapedAt": "2026-09-18T12:25:59.326Z"}
With includeDetails: true, every record also gets (real output, from a live listing page):
{"description": "This one-bedroom apartment in the city centre of Coimbra is perfect for couples ...","amenities": ["Waterfront", "Kitchen", "Wifi", "..."],"houseRules": "Check-in after 3:00 PM; Checkout before 11:00 AM; Self check-in with lockbox; ...","bedrooms": 1,"beds": 3,"bathrooms": 1,"personCapacity": 4,"hostName": "Azul Downtown Apartments","hostIsSuperhost": false,"subRatings": {"cleanliness": 4.8,"accuracy": 4.71,"checkin": 4.45,"communication": 4.75,"location": 4.67,"value": 4.61}}
Field notes:
priceNightlyis derived (priceTotal / nights), not a field Airbnb serves directly — it can differ slightly from yourpriceMin/priceMaxfilter, which Airbnb applies to its own internal base rate before some taxes/fees.nightsis read per-listing from the page (minimum-stay rules can make it longer than your requested date range), falling back to yourcheckIn/checkOutspan only when that text is missing.rating/reviewsCountarenullfor brand-new listings (isNew: true), not a parsing failure.
Review records (includeReviews)
{"type": "review","listingId": "14226815","listingUrl": "https://www.airbnb.com/rooms/14226815","reviewId": "1779648037635337220","createdAt": "2026-09-21T10:42:58Z","rating": 5,"language": "en","text": "Great stay, very walkable and quiet...","translatedText": null,"stayInfo": "Stayed a few nights","hostResponse": null,"hostResponseAt": null,"hostResponseDateText": null,"scrapedAt": "2026-09-29T06:00:00.000Z"}
translatedText is filled when the review is not in your locale and Airbnb offers a translation. hostResponseAt is month precision ("2026-08", null for non-English dates); hostResponseDateText is Airbnb's own wording. The text is exactly what the guest published (it can mention names the guest chose to write); the reviewer's own identity fields are not part of the output.
Calendar fields (includeCalendar)
Added to each listing record: calendar (array of {date, available, minNights, maxNights, price, currency} from today for calendarMonths months; price is null because Airbnb does not show a nightly price on the public calendar), availableDaysNext30, availableDaysNext90, and occupancyProxy = 1 - available days / days in calendar. availableDaysNext30 / availableDaysNext90 are null (never a misleadingly low number) when the fetched calendar does not cover the full 30 / 90 days - e.g. calendarMonths: 1 or 2 gives no 90-day figure; the default 3 months always covers both. The occupancy proxy is not real occupancy: a day that is not available may be booked or blocked by the host. Use it to compare listings and track trends, not as revenue truth. If the calendar could not be read, calendar is null and it is not charged.
Pricing
Pay per event — you are charged only for what is saved:
| Event | When |
|---|---|
listing-record | Each listing saved to the dataset: every search result, and a listingUrls listing when includeDetails fills its record with the full listing data (duplicates and filtered-out listings are free; a listingUrls listing with only reviews/calendar pays only those add-ons) |
listing-details | Each listing whose own page was successfully fetched and merged in (only charged on success) |
review-record | Each review saved ($0.0005, i.e. $0.50 per 1,000 reviews) |
listing-calendar | Each listing calendar fetched and merged in ($0.002; only charged on success) |
Worked example: an exhaustive run that saves 3,000 listings with includeDetails off costs
3,000 × $0.0012 = $3.60. Turning includeDetails on for the same run adds 3,000 ×
$0.002 = $6.00, for $9.60 total. Set Max total charge on the run to cap spend — the Actor
stops cleanly when the cap is reached: it only starts a listing when everything that listing may
charge still fits, and it never fetches more reviews than the remaining budget pays for.
Reviews for 100 listings x 50 reviews cost 5,000 x $0.0005 = $2.50.
Limits & honest caveats
- Prices depend on dates, currency and guest count. The same search run on different dates (or
with
adultschanged) will show differentpriceTotal/priceNightly— this is Airbnb dynamic pricing, not a bug. - Blocking and proxies. Airbnb blocks some datacenter IPs outright: a run from such an IP gets
a streak of HTTP 403/429 answers on its very first search page while the same search from
another IP succeeds a minute later (seen on roughly half of the runs from Apify's cloud without a
proxy). The Actor handles this by itself: a block streak (5 blocked answers in a row) on a run
without a proxy switches the run to Apify Proxy (datacenter, included in every Apify plan)
for the rest of the run, with a clear
Blocked by Airbnb ... switching to Apify Proxyline in the log; every further block streak is retried with a fresh session (new browser identity and, through the proxy, a new IP) and a longer back-off, up to 3 times per page, before that page is given up with a warning. Starting withproxyConfiguration: { "useApifyProxy": true }(the prefilled value in the UI) skips the blocked requests altogether;autoProxyFallback: falsekeeps the run off Apify Proxy entirely. If every search page stayed blocked, the run says so in its status message and log () instead of blaming your input, and nothing is charged.Blocked by Airbnb: every search page was blocked ... try again in a few minutes or enable a proxy - Airbnb may also serve an empty page-shell variant (a ~2 MB response with no data, roughly
1 request in 5 in this Actor's own testing) instead of blocking outright; the Actor retries it
up to 3× with a fresh session each time, then once more after the same recovery round as a block,
and only then skips that page (warning, not a crash). A status message ending in
N search page(s) blocked by Airbnb/N page(s) returned no datameans some listings on those pages are missing from an otherwise good run. - Exhaustive mode has a depth limit (4 price-band splits, then 3 map-quadrant splits). For an extremely dense micro-area that is still over the cap at maximum depth, the Actor accepts that capped leaf and logs a clear warning rather than splitting forever.
- Use a proxy for large or frequent exhaustive runs. A datacenter proxy via
proxyConfigurationis recommended once you run at scale or on a schedule, to stay polite, avoid the blocked-IP streaks above and reduce the page-shell-variant rate. - Public listing data only. No login, no cookies, no host contact details. Reviewer identity is never collected: no reviewer name, photo, profile ID or profile link, and not even the reviewer's home location.
- Reviews and calendars come from the same public endpoints the listing page itself calls. Airbnb rotates the query identifiers of those endpoints with its web deploys; when that happens the Actor reads the current ones from the listing page's own JavaScript at runtime and carries on. If even that fails (Airbnb changed the endpoint itself), the affected reviews/calendars are skipped for the run with a clear warning, nothing skipped is charged, listing searches keep working, and the actor needs an update - please report it on the Issues tab.
Code example
A runnable Python script (only requests needed) that calls this Actor and writes a CSV: airbnb/city_price_summary.py — pull a city's listings for your dates and print nightly-price stats by room type.
FAQ
Is this affiliated with Airbnb? No. This is an independent tool that reads Airbnb's public search and listing pages. Nothing here is investment advice.
Why did I get fewer than maxItems? The market you searched has fewer matching listings than
maxItems, or exhaustive mode hit its depth limit on a very dense sub-area (check the run log for
"Depth limit reached" warnings), or some pages were blocked by Airbnb (the status message then
ends with N search page(s) blocked by Airbnb; run again with Apify Proxy on).
The run says "Blocked by Airbnb" and saved nothing. Am I charged? No - nothing is charged
when nothing is saved. Run it again in a few minutes, or set proxyConfiguration to Apify Proxy
(the UI's prefilled value) so the run never starts on a blocked IP.
Why is priceNightly slightly outside my priceMin/priceMax? See the field notes above —
Airbnb's own filter and this Actor's derived nightly rate aren't always computed on the exact same
base (taxes/fees).
Can I use a startUrls search with map bounds or amenity filters I set on airbnb.com? Yes —
copy the URL from your browser after setting filters; every query parameter is preserved, only
pagination/split parameters are added on top.
Something wrong or missing? Open an issue on the Actor's Issues tab.