Airbnb Rooms URLs Scraper avatar

Airbnb Rooms URLs Scraper

Pricing

$24.99/month + usage

Go to Apify Store
Airbnb Rooms URLs Scraper

Airbnb Rooms URLs Scraper

Airbnb Rooms URLs Scraper collects room listing links from any city, region, or keyword search. It delivers clean, deduplicated URLs ideal for enrichment, competitor tracking, analytics, or building your own Airbnb datasets quickly and at scale.

Pricing

$24.99/month + usage

Rating

0.0

(0)

Developer

Scrapier

Scrapier

Maintained by Community

Actor stats

0

Bookmarked

9

Total users

0

Monthly active users

13 days ago

Last modified

Share

Airbnb Room Scraper — Listings, Amenities and Full Rating Breakdown

Airbnb Room Scraper pulls a complete, structured record for any public Airbnb room listing. Paste /rooms/<id> URLs, or a plain search phrase, and it returns title, description, every amenity, listing highlights, house rules, the full photo set, host and co-host details, the category-by-category rating breakdown, location and cancellation policy. Every response is structured JSON — ready to pass directly to an LLM, index into a vector store, or feed a monitoring pipeline. No Airbnb account or login is required to run it.


🧭 What is Airbnb Room Scraper?

Airbnb Room Scraper is an Apify Actor that reads Airbnb's public room-listing pages (and, when given a plain phrase instead of a URL, Airbnb's public search-results page) and returns one structured JSON record per listing. It does not need an Airbnb account, login, or session cookie — the outbound requests carry only browser-style headers, no authentication.

What sets it apart from a basic listing scraper is the rating breakdown: instead of a single rounded star value, every row carries the six individual category scores Airbnb itself calculates (accuracy, check-in, cleanliness, communication, location, value), plus the overall guest-satisfaction score and the exact, unabbreviated review count.

  • 🏠 Full property details — title, description, property/room type, guest capacity, amenities, highlights and house rules
  • Complete rating breakdown — six category scores plus overall guest satisfaction and exact review count
  • 👤 Host and co-host data — host bio, Superhost/verified flags, years hosting, and an optional deep profile fetch
  • 🖼️ Full photo set — every image in the photo tour, with caption and orientation
  • 🌐 93 locales and 48 currencies, plus check-in/check-out dates and guest-count query controls
  • 🔎 Search-phrase input — a plain keyword resolves to Airbnb listing URLs automatically

📦 What data can you get with Airbnb Room Scraper?

Airbnb Room Scraper extracts five result types in one run: full room-listing details, the rating breakdown, host and co-host data, the complete photo set, and — when the input is a search phrase — the listing URLs that phrase resolves to.

Result TypeExtracted FieldsPrimary Use Case
Room listingtitle, description, propertyType, roomType, personCapacity, homeTier, amenities, highlights, houseRules, cancellationPolicies, breadcrumbs, location, coordinates, locationSubtitle, locationDescriptionsProperty-listing enrichment, catalogue building
Rating breakdownrating.accuracy, rating.checking, rating.cleanliness, rating.communication, rating.location, rating.value, rating.guestSatisfaction, rating.reviewsCountQuality benchmarking, competitor tracking
Host & co-host datahost.id, host.name, host.isSuperHost, host.isVerified, host.ratingCount, host.ratingAverage, host.timeAsHost, host.about, host.highlights, host.profile (optional), coHostsHost reputation research, outreach lists
Photo setimages[].caption, images[].imageUrl, images[].orientationVisual audits, listing-quality review
Search resolutionresolved /rooms/<id> URLs found for a keywordMarket discovery, lead generation from a destination search

⭐ Rating breakdown

Most Airbnb scrapers surface only the single rounded star value shown on the search card. This Actor parses the underlying loggingContext payload Airbnb itself uses to render the per-category bars on the listing page, so every row carries all six category scores separately, not an averaged blend — useful when you need to know why a listing's overall score moved, not just that it did.

{
"rating": {
"accuracy": 4.9,
"checking": 4.9,
"cleanliness": 4.9,
"communication": 4.9,
"location": 4.8,
"value": 4.9,
"guestSatisfaction": 4.92,
"reviewsCount": 489
}
}

reviewsCount is the exact figure, never abbreviated (no "400+"). Review text itself is not returned — only the aggregate breakdown and count (see What this Actor does not return).

👤 Host and co-host data

Every row includes the host's public passport data — name, profile photo, Superhost and identity-verified flags, review count and average, years hosting, bio and host highlights — read straight off the listing page, no extra request needed. Setting enrichUserProfiles to true fetches the host's public Airbnb profile page and attaches it as host.profile for one additional request per listing. Co-hosts are returned as coHosts[] with the name and photo the listing itself provides; Airbnb serves no public profile payload for a co-host when logged out, so co-host profile enrichment is not attempted.


🤔 Why not build this yourself?

Airbnb does not publish a self-serve API for third-party listing search or scraping — its partner API requires an approved integration and is not a general-purpose query endpoint. Building a scraper against the plain HTML is harder than it looks:

  • Payload location shifts. Airbnb has already relocated the listing's content-bearing data at least once — the older sections.sections[] blocks now come back as empty {"__typename": ...} stubs, with the real content moved into data.node.pdpPresentation. A scraper built against the old structure silently returns blank fields.
  • TLS-fingerprint blocking. Airbnb sits behind Akamai, and a plain Python HTTP client's TLS handshake is refused from most exit IPs — a request has to impersonate a real browser's TLS fingerprint to get served at all.
  • Locale domain handoff. Requesting a non-English locale doesn't return the localized page directly; Airbnb answers with a signed POST-form handoff to a country subdomain that has to be followed and re-posted.
  • Proxy escalation cost. Sustained scraping needs a proxy pool that can be escalated from datacenter to residential IPs when Airbnb blocks an exit, which means paying for and managing that infrastructure yourself.

Airbnb Room Scraper already handles all four, so you get structured rows instead of building and maintaining this yourself.


🚀 How to scrape Airbnb with Airbnb Room Scraper?

  1. Open Airbnb Room Scraper on its Apify Store listing and click Try for free (or Start, if you already have it in your account).
  2. Enter your input into startUrls — one or more Airbnb /rooms/<id> URLs, or a plain search phrase such as "Lisbon Portugal". This is the only required field.
  3. Optionally set the real query controls the input schema exposes: checkIn / checkOut dates, adults / children / infants / pets guest counts, locale and currency.
  4. Click Start and let the run finish.
  5. Open the Dataset tab and export the results as JSON, CSV, Excel, XML or RSS, or pull them through the Apify API.

Running multiple queries in one job

startUrls accepts a mixed array — room URLs and search phrases can sit in the same list — and every entry is resolved and scraped within a single run. Duplicate listings (the same room ID reached from two different entries) are automatically de-duplicated before scraping, so a mixed batch never produces two rows for the same room.


⬇️ Input

ParameterRequiredTypeDefaultDescription
startUrlsYesarray["https://www.airbnb.com/rooms/53997462", "https://www.airbnb.com/rooms/12937"]Airbnb room URLs, one per line, or a plain search phrase resolved via Airbnb search.
enrichUserProfilesNobooleanfalseFetch each host's public profile page and attach it as host.profile. Costs one extra request per listing.
checkInNostringCheck-in date, format YYYY-MM-DD.
checkOutNostringCheck-out date, format YYYY-MM-DD.
localeNostring (enum, 93 values)en-USLanguage/region for the listing text. Non-English locales are resolved through Airbnb's country domain handoff automatically.
currencyNostring (enum, 48 values)USDCurrency sent with each request and echoed in the returned listing url.
adultsNointeger, min 1Number of adult guests.
childrenNointeger, min 0Number of children.
infantsNointeger, min 0Number of infants.
petsNointeger, min 0Number of pets.
proxyConfigurationNoobject{"useApifyProxy": false}Proxy used for every request. If set, it is honoured from the first request; if left off, the run starts direct and escalates to datacenter, then residential, proxies automatically when Airbnb blocks the exit IP.

Example input

{
"startUrls": [
"https://www.airbnb.com/rooms/53997462",
"https://www.airbnb.com/rooms/12937",
"Lisbon Portugal"
],
"checkIn": "2026-09-15",
"checkOut": "2026-09-18",
"adults": 2,
"locale": "en-US",
"currency": "USD",
"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}

Common pitfall: checkIn and checkOut are validated against YYYY-MM-DD before the run starts. A value in any other format (e.g. 09/15/2026) is silently dropped — logged as a warning and treated as if the field were empty — rather than causing the run to fail, so a malformed date will not surface as an error in your results.


⬆️ Output

Each successfully scraped listing is pushed as one row to the run's default Dataset, exportable as JSON, CSV, Excel, XML or RSS from the Apify Console or via the API. The full run is also written to the key-value store under OUTPUT, keyed by the requested URL.

Scraped results

[
{
"id": "12937",
"url": "https://www.airbnb.com/rooms/12937?locale=en-US&currency=USD&adults=2",
"requestedUrl": "https://www.airbnb.com/rooms/12937",
"title": "1 Stop to Midtown! Private Bedroom, Landmark House",
"description": "Charming private room in a landmark Queens townhouse...",
"htmlDescription": { "htmlText": "Charming private room in a landmark Queens townhouse...<br />..." },
"subDescription": { "title": "Private room in townhouse", "items": ["2 guests", "1 bedroom", "1 bed", "1 shared bath"] },
"propertyType": "Private room in townhouse",
"roomType": "Private room",
"homeTier": 0,
"personCapacity": 2,
"rating": {
"accuracy": 4.9, "checking": 4.9, "cleanliness": 4.9,
"communication": 4.9, "location": 4.8, "value": 4.9,
"guestSatisfaction": 4.92, "reviewsCount": 489
},
"brandHighlights": { "hasGoldenLaurel": true },
"host": {
"id": "50124",
"contextualUserId": "50124",
"name": "Orestes",
"profileImage": "https://a0.muscache.com/im/pictures/user/host.jpg",
"isSuperHost": true,
"isVerified": true,
"highlights": ["Speaks English and Spanish"],
"about": "Longtime Queens resident who loves hosting travelers.",
"ratingCount": 489,
"ratingAverage": 4.92,
"hostDetails": ["Superhost", "16 years hosting"],
"timeAsHost": { "years": 15, "months": 7 }
},
"coHosts": [],
"location": "Queens",
"locationSubtitle": "Queens, New York, United States",
"locationDescriptions": [
{ "title": "Getting around", "content": "Subway station 5 minutes away.", "mapMarkerRadiusInMeters": 250 }
],
"coordinates": { "latitude": 40.74757, "longitude": -73.94571 },
"amenities": [
{ "title": "Scenic views", "values": [ { "title": "Garden view", "subtitle": null, "icon": "SYSTEM_FLOWER", "available": true } ] }
],
"highlights": [
{ "title": "Great check-in experience", "subtitle": "Recent guests loved the smooth start to this stay.", "icon": "SYSTEM_KEY", "type": "LISTING_CHECKIN_REVIEW_RATING" }
],
"images": [
{ "caption": "Bedroom", "imageUrl": "https://a0.muscache.com/im/pictures/room1.jpg", "orientation": "LANDSCAPE" },
{ "caption": "Living area", "imageUrl": "https://a0.muscache.com/im/pictures/room2.jpg", "orientation": "PORTRAIT" }
],
"breadcrumbs": [
{ "linkRoute": "/queens-new-york", "linkText": "Queens" }
],
"houseRules": { "general": [ { "title": "During your stay", "values": [ { "title": "No smoking", "icon": "SYSTEM_SMOKING", "additionalInfo": null } ] } ] },
"cancellationPolicies": [
{ "title": "Free cancellation before August 16.", "policyName": "Firm", "policyId": 62 }
],
"metaDescription": "Private room · Queens, New York, United States",
"seoTitle": "1 Stop to Midtown! Private Bedroom, Landmark House",
"sharingConfigTitle": "1 Stop to Midtown! Private Bedroom",
"thumbnail": "https://a0.muscache.com/im/pictures/room1.jpg",
"androidLink": "airbnb://d/abc123",
"iosLink": "airbnb://d/abc123",
"descriptionOriginalLanguage": "en",
"checkIn": "2026-09-15",
"checkOut": "2026-09-18",
"language": "en-US",
"timestamp": "2026-08-04T10:00:00Z"
},
{
"id": "53997462",
"url": "https://www.airbnb.com/rooms/53997462?locale=en-US&currency=USD",
"requestedUrl": "https://www.airbnb.com/rooms/53997462",
"title": "Modern Loft near the Marina",
"propertyType": "Entire loft",
"roomType": "Entire home/apt",
"personCapacity": 4,
"rating": { "accuracy": 4.8, "checking": 4.9, "cleanliness": 4.9, "communication": 5.0, "location": 4.9, "value": 4.7, "guestSatisfaction": 4.86, "reviewsCount": 213 },
"host": { "id": "88213", "name": "Priya", "isSuperHost": false, "isVerified": true, "ratingCount": 213, "ratingAverage": 4.86 },
"coHosts": [],
"location": "Amsterdam",
"amenities": [],
"highlights": [],
"images": [],
"houseRules": { "general": [] },
"cancellationPolicies": [],
"language": "en-US",
"timestamp": "2026-08-04T10:00:05Z"
},
{
"id": "9081726",
"url": "https://www.airbnb.com/rooms/9081726?locale=en-US&currency=USD",
"requestedUrl": "https://www.airbnb.com/rooms/9081726",
"title": "Cozy Studio in Alfama, Lisbon",
"propertyType": "Entire rental unit",
"roomType": "Entire home/apt",
"personCapacity": 2,
"rating": { "accuracy": 4.95, "checking": 4.9, "cleanliness": 4.9, "communication": 4.95, "location": 5.0, "value": 4.85, "guestSatisfaction": 4.91, "reviewsCount": 342 },
"host": { "id": "34512", "name": "Ines", "isSuperHost": true, "isVerified": true, "ratingCount": 342, "ratingAverage": 4.91 },
"coHosts": [],
"location": "Lisbon",
"amenities": [],
"highlights": [],
"images": [],
"houseRules": { "general": [] },
"cancellationPolicies": [],
"language": "en-US",
"timestamp": "2026-08-04T10:00:07Z"
}
]

host.profile (present only when enrichUserProfiles is true and Airbnb serves a public payload for that host) carries a subset of: id, name, profileImage, about, location, work, school, languages, isSuperHost, isVerified, createdAt — or, on the fallback contextual-profile path, timeAsHost, timeAsUser, hasIdentityBadge, identityVerificationTypes, verificationInfo, profileVisibility. Airbnb serves one of two different profile-page shapes depending on the host, and empty fields are dropped rather than returned as null.

houseRules returns only the general group. Airbnb's own additionalHouseRules field is not included — the field exists in the source payload but returns null on every listing this Actor's own testing checked, so it is omitted rather than shipped as a permanently blank column.

🚧 What this Actor does not return

  • No price or availability. Airbnb does not include nightly rate, total price, or an availability flag in the server-rendered listing document — not even when checkIn/checkOut are supplied. Rather than emit a placeholder, the field is omitted entirely.
  • No review text. Only the aggregate rating breakdown and the exact reviewsCount are returned — not individual reviews.
  • No availability calendar.
  • Co-host profiles are not enriched. Airbnb identifies a co-host only by an opaque contextualUserId and serves no public profile payload for it when logged out, so enrichUserProfiles only enriches the primary host. The co-host's name and photo from the listing itself are still returned in coHosts.
  • Search-phrase input returns at most 20 listings, taken from the first page of Airbnb's search results. There is no pagination past that page.
  • De-listed, private or removed listings are skipped, not emitted. Airbnb answers those with HTTP 200 and an empty payload; this Actor treats that as an unavailable listing and logs it rather than pushing a blank row.

💡 How can I use the data extracted with Airbnb Room Scraper?

  • 🏢 Property managers and revenue teams: track a portfolio's or a competitive set's rating breakdown and amenities over time to spot where a listing is losing ground on cleanliness or value specifically, not just "the score dropped."
  • 🤖 AI engineers and LLM developers: feed description, amenities, highlights and houseRules straight into an LLM as grounding context for a travel assistant or listing-comparison agent — every field arrives as typed JSON, no HTML to strip.
  • 📊 Market researchers: aggregate propertyType, personCapacity, location and rating across a destination's search results to build short-term-rental market snapshots.
  • 🔬 Academic and data researchers: build reproducible, timestamped datasets of public listing attributes for housing or tourism research.

📈 How do you monitor an Airbnb listing's ratings over time?

Rating drift is the discipline of re-scraping the same set of listings on a schedule and diffing the rating object between runs, instead of relying on the single rounded star Airbnb shows on a search card. Because this Actor returns all six category scores separately, a drop that a rounded average would hide — cleanliness falling while communication holds — becomes visible immediately.

Diff these fields between runs: rating.accuracy, rating.checking, rating.cleanliness, rating.communication, rating.location, rating.value, rating.guestSatisfaction, and rating.reviewsCount. A meaningful jump in reviewsCount combined with a falling category score is a stronger signal than either alone. amenities and highlights are worth diffing too — a removed amenity group or a new highlight badge (like a Guest Favorite, brandHighlights.hasGoldenLaurel) often precedes or follows a rating change.

A practical loop: run the same startUrls list on an Apify schedule (daily or weekly), pull each run's dataset via the API, and compare it to the previous run's — alert when a category score moves more than your chosen threshold, or when reviewsCount jumps sharply. Apify Console's Schedules feature and the dataset API are the mechanism; the Actor itself does not diff runs for you.


🔗 Integrate Airbnb Room Scraper and automate your workflow

Airbnb Room Scraper works with any language or tool that can send an HTTP request — it runs on Apify, so the standard Apify API and client libraries apply.

REST API with Python

from apify_client import ApifyClient
client = ApifyClient("<APIFY_API_TOKEN>")
run_input = {
"startUrls": ["https://www.airbnb.com/rooms/12937", "Lisbon Portugal"],
"locale": "en-US",
"currency": "USD",
}
run = client.actor("scrapier/airbnb-rooms-urls-scraper").call(run_input=run_input)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["title"], item["rating"]["guestSatisfaction"])

Scheduled monitoring and delivery

Set up a recurring run from the Apify Console's Schedules tab (cron expression, any interval) to re-scrape the same startUrls on a cadence, then pull each run's dataset through the API or an Apify webhook fired on run completion. There is no push-based delivery built into the Actor itself — scheduling and webhooks are the platform mechanism for it.


Scraping publicly accessible web pages is generally lawful. U.S. courts have held that accessing data any visitor can view without logging in does not violate the Computer Fraud and Abuse Act (hiQ Labs, Inc. v. LinkedIn Corp., Ninth Circuit, 2019). Airbnb Room Scraper only reads what a browser can already see on a /rooms/<id> page or a public search page — no login or session cookie is used.

The data itself is mixed. Listing details (description, amenities, house rules, cancellation policy) are business/product data governed mainly by Airbnb's Terms of Service rather than privacy law. The host object and the optional enrichUserProfiles output, though, are personal data about an identifiable person — so GDPR and CCPA obligations can attach if you store host data on EU or California residents. Minimize what you keep. Scraping for one-off research carries a different risk profile than scraping at scale for AI training or resale. Consult your legal team for commercial use cases involving bulk data storage.


❓ Frequently asked questions

Which Airbnb locales and currencies does the scraper support?

locale supports 93 language/region options (default en-US) and currency supports 48 currency codes (default USD). Non-English locales are resolved automatically through Airbnb's country-domain handoff, so the returned title, description, amenities and houseRules come back fully translated.

Can I search Airbnb by a keyword instead of pasting URLs?

Yes. Any startUrls entry that isn't an Airbnb /rooms/<id> URL is treated as a search phrase (e.g. "Lisbon Portugal") and resolved through Airbnb's search page to up to 20 listing URLs, which are then scraped like any other input.

How does Airbnb Room Scraper handle Airbnb's anti-bot measures?

Every request goes out through a Chrome-131 TLS impersonation client, because Airbnb's Akamai-backed edge refuses a plain Python TLS handshake from most exit IPs. If a request still comes back blocked, the Actor automatically escalates the exit IP — starting direct, then datacenter proxy, then residential proxy — retrying up to 3 times on residential before giving up on that URL.

Does Airbnb Room Scraper extract the full rating breakdown?

Yes — in the rating object on every row: accuracy, checking, cleanliness, communication, location, value, guestSatisfaction and the exact reviewsCount. These are only absent if Airbnb's own listing payload omits them for that room.

How many results does Airbnb Room Scraper return per query?

For a room URL, one row per unique listing (duplicates by room ID are removed before scraping). For a search phrase, up to 20 listing URLs from the first page of Airbnb's search results — there is no pagination beyond that first page.

Does Airbnb Room Scraper return nightly price or availability?

No. Airbnb does not include price or an availability flag in the server-rendered listing document, even with check-in/check-out dates supplied, so this Actor does not return either field.

What happens with de-listed, private or removed listings?

Airbnb answers those with HTTP 200 and an empty payload. The Actor detects this, logs the URL as unavailable, and does not push a row for it — so you will not see a blank or null-filled record for a dead listing.

How do I monitor an Airbnb listing's ratings and amenities over time?

Run the same startUrls on a recurring Apify schedule, diff each run's rating object and amenities/highlights arrays against the previous run's, and alert on the field that changed. See How do you monitor an Airbnb listing's ratings over time? above.

Does Airbnb Room Scraper work with Claude, ChatGPT, and AI agent frameworks?

It is callable as a standard HTTP endpoint via the Apify API or apify_client, so any agent framework that can issue an HTTP request can call it as a tool — the agent submits startUrls, receives structured JSON back, and can ground its answer in the returned fields.

Can I use Airbnb Room Scraper without managing proxies or an Airbnb account?

Yes. No Airbnb account or login is ever used or required. Proxy configuration is optional — leave proxyConfiguration at its default and the Actor starts direct, escalating to Apify's datacenter and then residential proxies automatically if Airbnb blocks the request.


💬 Your feedback

Found a bug, or missing a field you need? Open an issue on this Actor's Issues tab on its Apify Store page — that's the fastest way to reach the maintainers directly.