Airbnb Listings Scraper - Prices, Ratings & Geo avatar

Airbnb Listings Scraper - Prices, Ratings & Geo

Pricing

from $1.26 / 1,000 results

Go to Apify Store
Airbnb Listings Scraper - Prices, Ratings & Geo

Airbnb Listings Scraper - Prices, Ratings & Geo

Scrapes Airbnb stay listings from the search page's own embedded data: price, rating, coordinates, photos and room type. Deduplicates the listings Airbnb repeats within a page, decodes the real listing id, and reports the currency the page actually rendered.

Pricing

from $1.26 / 1,000 results

Rating

0.0

(0)

Developer

Ibnu Adzim

Ibnu Adzim

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

11 days ago

Last modified

Share

Airbnb Listings Scraper — Prices, Ratings & Geo

Reads Airbnb stay listings from the search page's own embedded data — the data-deferred-state blob the site server-renders. No API key, no GraphQL call, no account.

What you get

recordTypeOne perCarries
LISTINGstayreal listing id and /rooms/ URL, name, room type and area, latitude/longitude, rating (numeric and as Airbnb labelled it), badges, photos, and the price with the window it actually covers
SEARCH_SUMMARYdestinationlistings returned vs raw result objects, duplicates removed within and across pages, the currency requested vs the one rendered, and the stay lengths the prices cover
ERRORfailed inputa named reason

Four things the payload will mislead you about

1. One page reports 48 results that are 30 listings. The deferred state carries the set across overlapping sections — 18 ids appear exactly twice, same title, same price, nothing malformed. Counting result objects overstates by 60%. This actor deduplicates within a page as well as across pages, and reports rawResultObjects beside listingsReturned so the gap stays visible.

2. The currency follows the exit IP. Same listing, same session, seconds apart:

(no currency parameter) -> Rp 17,326,505 <- Rupiah, from the address
currency=USD -> $3,246
currency=EUR -> EUR 2,785

Nothing asked for Rupiah. So a local run and a cloud run through a US proxy silently produce different numbers for the same listing. An unknown code isn't refused either — it's sticky, keeping whatever was in effect. This actor always sends the currency explicitly, validates it, and reports currenciesReturned read from the rendered price symbol so a mismatch is visible rather than assumed away.

3. The headline price is a stay total, not a nightly rate. With no dates, Airbnb invents its own window:

no dates "$3,246" qualifier "for 5 nights"
checkin/checkout supplied "$795" qualifier "for 3 nights"

Reading that as a per-night price is wrong by whatever the window happened to be — and the window changes with the search. Every row carries priceQualifier, priceNights and priceIsStayTotal, and pricePerNightApprox is derived only when the night count is actually known.

4. The listing id is base64 and isn't the one in the URL. RGVtYW5kU3RheUxpc3Rpbmc6MTY3NTM4… decodes to DemandStayListing:1675389828808490095. The opaque form joins to nothing — including Airbnb's own /rooms/<id> URLs. Decoded here, with the raw form kept beside it.

Smaller things

  • Rating is a localized string. A listing with no reviews comes back as the word "New", not 0 or null. Both survive: ratingValue (numeric, null for New), ratingLabel (Airbnb's own text) and an isNewListing flag — so a new listing never gets averaged in as a zero.
  • Pagination cursors are constructed, not scraped. They're base64 of {"section_offset":0,"items_offset":N,"version":1} stepping by 18, and the server accepts ones this actor builds — so there's no cursor bookkeeping and no dependence on the page exposing them.
  • title is the room type and area ("Apartment in Paris"); the human name of the place is a separate field.

Notes

  • airbnb.com/robots.txt scopes its Claude rules to specific paths and leaves /s/ and /rooms/ allowed.
  • DataDome runs on this origin. It did not challenge during development, but a datacenter exit is far more likely to be challenged than a residential one. A challenge is reported as a named challenged error rather than silently returning nothing.
  • The proxy setting changes the data here, not just the routing — see the currency point above. Residential is recommended for anything large.
  • Pages are ~930 KB each, so pacing defaults to 3 seconds.