Airbnb Rooms URL Scraper — Host Portfolio & Co-Host Listings avatar

Airbnb Rooms URL Scraper — Host Portfolio & Co-Host Listings

Pricing

Pay per usage

Go to Apify Store
Airbnb Rooms URL Scraper — Host Portfolio & Co-Host Listings

Airbnb Rooms URL Scraper — Host Portfolio & Co-Host Listings

This actor extracts clean, structured Airbnb room URLs from search results, maps, filters, or specific locations. It automates URL collection for research, pricing analysis, lead generation, and large-scale Airbnb data projects with reliable output.

Pricing

Pay per usage

Rating

0.0

(0)

Developer

Scraper Engine

Scraper Engine

Maintained by Community

Actor stats

0

Bookmarked

4

Total users

0

Monthly active users

9 days ago

Last modified

Share

Airbnb Rooms URL Scraper — Host Portfolio & Co-Host Listings

Paste an Airbnb room URL and get back the listing, the host behind it, the host's entire public property portfolio, and every named co-host with the portfolio they run — as structured JSON. It also accepts a host profile URL directly, skipping the listing step. No Airbnb login is required, and every field is documented against the live payload, not guessed. Run it now on the Apify Store to see a real host portfolio in seconds.

🏘️ What is the Airbnb Host Portfolio and Co-Host Listings Scraper?

It is an Apify Actor that expands an airbnb.com/rooms/<id> URL into three things: the full listing record, the host's public roster of other properties, and the portfolio each co-host on the listing runs. A airbnb.com/users/show/<id> host profile URL works too, going straight to the portfolio without a listing fetch. No Airbnb account, cookie or API key is needed — everything comes from pages and GraphQL sections Airbnb serves to any visitor. It is built for short-term-rental analysts, acquisition scouts, housing researchers and data teams who need to know how many doors sit behind one "host."

🔓 What Airbnb host and listing data is publicly available to scrape?

A listing page, a host's public profile and the "Meet your host" panel are all visible to any visitor without signing in — that is the entire surface this Actor reads.

Data categoryPublicly availableRestricted
Listing details (title, description, amenities, house rules, cancellation policy, photos)✅ Full listing page
Ratings and review count✅ Category breakdown + total count❌ Full review text/photos beyond what the page renders
Host identity (name, photo, superhost flag, verifications, about, time as host)✅ From the public profile / host card❌ Email, phone, exact address
Co-hosts named on a listing✅ Name + profile photo, resolved to a numeric id
Host's other properties (roster)✅ Up to 10 rows, plus the honest total count⚠️ Airbnb itself never serves more than 10 rows on any public profile, logged in or not — this is a platform ceiling, not a login wall
Exact nightly price, live availability calendar, messaging the host❌ Not resolved by this Actor🔒 Booking flow / host inbox

The Airbnb Host Portfolio and Co-Host Listings Scraper only returns publicly visible data — what any visitor sees. Nothing behind a login wall.

📋 What data can you extract with the Airbnb Host Portfolio and Co-Host Listings Scraper?

Every row carries the full listing record, host and co-host identity, ratings, and — the reason this Actor exists — the host's real portfolio size plus a roll-up of every property in it.

Listing identity and descriptive fields

FieldDescription
type"listing" or "hostProfile", depending on which kind of URL was resolved
inputMode"roomUrl" or "hostUrl"
requestedUrlThe exact URL the Actor requested (room URL with stay params, or the host URL as given)
id / listingIdAirbnb's numeric listing id (null on hostProfile rows)
url / listingUrlCanonical rebuilt room URL with locale/currency/stay params (listing rows); url is the host profile URL on hostProfile rows
titleListing title
description / htmlDescriptionPlain-text and HTML versions of the long description
subDescription{title, items[]} — the "About this space" bullet overview
propertyType / roomTypee.g. "House" / "Entire home/apt"
location / locationSubtitleShort city label and the full "City, Region, Country" string
locationDescriptionsArray of {title, content, mapMarkerRadiusInMeters} — the "About the area" text blocks
coordinates{latitude, longitude}
breadcrumbsArray of {linkRoute, linkText} SEO trail
imagesArray of {caption, imageUrl, orientation}
amenitiesArray of {title, values[]} grouped by category; each value is {title, subtitle, icon, available}
houseRules{general: [{title, values[]}]}; each value is {title, icon, additionalInfo}
cancellationPoliciesArray of {title, policyName, policyId}
highlightsArray of {title, subtitle, icon, type} — Airbnb's "what guests love" chips
brandHighlights{hasGoldenLaurel} — Airbnb's Guest Favorite flag
seoTitle / metaDescription / sharingConfigTitle / thumbnailAirbnb's own SEO and social-share copy
androidLink / iosLinkAirbnb app deep links
descriptionOriginalLanguage / languageSource locale of the description, and the locale the row was scraped in
checkIn / checkOutStay dates echoed back from the request
timestampISO-8601 build time of the base listing record
scrapedAtISO-8601 UTC time the row was pushed to the dataset

Host, co-host and rating fields

FieldDescription
personCapacityGuest capacity
homeTierAirbnb's internal tier id
rating{accuracy, checking, cleanliness, communication, location, value, guestSatisfaction, reviewsCount}
host{id, contextualUserId, name, profileImage, isSuperHost, isVerified, highlights[], about, ratingCount, ratingAverage, hostDetails[], timeAsHost:{years,months}} — sourced from the listing's own host card. On a hostProfile row this object stays empty (there is no listing to source it from); use hostUserId / hostDisplayName from the portfolio block instead
coHostsArray of {contextualUserId, name, profilePictureUrl, id} — the numeric id is resolved from the "Meet your host" panel so co-host portfolios can be looked up
coHostCountNumber of co-hosts on a listing row; on a hostProfile row, the number of distinct co-hosts found across the scanned roster properties

Host portfolio and co-host portfolio fields

This is the layer the base Airbnb listing scraper does not have.

FieldDescription
hostUserId / hostProfileUrl / hostDisplayName / hostProfileImageHost identity, resolved from the public profile
hostIsSuperhost / hostProfileLocation / hostProfileAboutSuperhost flag, stated city and bio from the profile
hostTimeAsHost{years, months}
hostIdentityVerificationsArray, e.g. ["Identity", "Email address", "Phone number"]
hostReviewsFromGuestsCountGuest review count across the host's account
hostListingsCountAirbnb's own total — honest at any portfolio size
hostListingsRosterCappedtrue when Airbnb returned fewer roster rows than the real total
hostListings[]One row per portfolio property: listingId, url, title, roomTypeCategory, roomTypeLabel, localizedRoomType, propertyType, bedrooms, beds, bathrooms, ratingAverage, reviewsCount, isSuperhost, instantBookEnabled, isNewListing, thumbnail, isCurrentListing, plus city when mapPortfolioCities is on
hostPortfolioSummaryRoll-up over the rows actually returned: listingsCount, operatorTier, rosterRows, rosterCapped, ratedListings, unratedListings, averageRating, totalReviewsOnRoster, entirePlaceCount, privateRoomCount, sharedRoomCount, hotelRoomCount, entirePlaceShare, superhostListings, instantBookListings, newListings, totalBedrooms, totalBeds, totalBathrooms, propertyTypeBreakdown[], plus cityBreakdown[], distinctCities, citiesUnresolved when mapPortfolioCities is on
hostPortfolioResolvedfalse when the host's profile had no public container to read
coHostPortfolios[]One block per co-host: {coHostId, coHostName, coHostProfileUrl, coHostProfileImage, listingsCount, rosterCapped, isSuperhost, location, listings[]}listings[] is the same shape as hostListings[]
coHostListingsTotalSum of every co-host's real portfolio size (null when no co-host is named)
host.profile / coHosts[].profileOnly when enrichHostProfiles (or enrichUserProfiles) is on: {id, name, profileImage, about, location, isSuperHost, timeAsHost, timeAsUser, hasIdentityBadge, identityVerificationTypes, reviewsFromGuestsCount}, empty keys stripped

🛠️ Why not build this yourself?

Airbnb does not publish a self-serve API for host portfolios, co-host relationships or roster data — the fields above only exist inside the site's own web app, behind an internal GraphQL endpoint (StaysPdpSections) and a legacy profile query that are not documented for third-party use. Reaching them means reverse-engineering the persisted-query hash, keeping up with Airbnb's payload shape as it migrates (this Actor already tracks a move from the old sections[] array to pdpPresentation), and getting past Akamai's TLS fingerprinting — a plain Python HTTP client is refused on sight from most datacenter IPs, which is why this Actor impersonates a real Chrome TLS fingerprint and runs a proxy escalation ladder. Maintaining that yourself means re-deriving the query hash and payload paths every time Airbnb ships a front-end change, plus buying and rotating residential proxy capacity. This Actor absorbs all of that; you send URLs and read JSON.

▶️ How to use the Airbnb Host Portfolio and Co-Host Listings Scraper

  1. Open the Actor on its Apify Store page and click Try for free (or Run, if you already have it in your account).
  2. Provide the required input: startUrls — one or more Airbnb room URLs, host profile URLs, or plain search phrases, mixable in the same run.
  3. Set the optional filters worth tuning first: minHostListings to keep only serious operators, includeCoHostListings if you don't need co-host portfolios, and mapPortfolioCities if you want market spread by city.
  4. Start the run.
  5. Download the results as JSON, CSV, Excel, or any other format Apify's dataset export supports, or stream them via the API while the run is still going.

How to scale to bulk host and listing extraction

startUrls is a plain array — add as many room URLs, host profile URLs, or search phrases as you need in one run; there is no schema-level cap on the list length. Internally the Actor processes up to 6 targets concurrently and caches every host/co-host profile fetch per run, so a batch of 200 room URLs that all belong to the same management company costs one profile fetch, not 200.

💼 What can you do with Airbnb host portfolio data?

  • 🏙️ Short-term-rental analysts use hostListingsCount and hostPortfolioSummary.operatorTier across a neighborhood's listings to measure how much of the visible supply sits behind multi-property operators rather than individual hosts.
  • 🤝 Acquisition and M&A scouts use coHostPortfolios[].listingsCount and hostDisplayName to find the management company actually running a "small host" listing, before reaching out.
  • 🏛️ Regulators and housing researchers use hostPortfolioSummary.entirePlaceShare and hostListingsCount as evidence of whole-home commercial operation versus genuine home-sharing.
  • 📊 Property managers use hostPortfolioSummary.averageRating, propertyTypeBreakdown and totalReviewsOnRoster to benchmark a competitor's roster size and review volume.
  • 🤖 AI agents and RAG pipelines pass hostProfileAbout, description and hostPortfolioSummary straight into a vector store or an agent's context window — typed JSON needs no HTML parsing before it is usable as a tool result.

🛡️ How does the scraper handle rate limits and blocking?

Every request is sent with a Chrome 131 TLS fingerprint (curl_cffi's impersonate="chrome131"), because Airbnb sits behind Akamai and refuses a plain Python client's fingerprint from datacenter exits. Proxy use follows a ladder: if you set an explicit proxyConfiguration, that proxy is used from the very first request; if you leave it off, the Actor starts with no proxy and escalates automatically — first to Apify's datacenter proxy, then to a sticky residential proxy — the moment a response comes back without its expected data container (a soft-block signal, not a parsing bug). Room-page fetches get up to 3 retries with an escalation between each attempt; profile fetches get up to 3 retries with a short delay. A listing that genuinely has no payload (de-listed, private, or a dead id) is treated as unavailable rather than retried forever, logged, and skipped — it is not written to the dataset and not charged.

⬇️ Input

ParameterRequiredTypeDescriptionExample value
startUrlsYesarrayRoom URLs, host profile URLs, bare room ids, or search phrases, mixable in one run["https://www.airbnb.com/rooms/25166525"]
includeHostListingsNobooleanOpen the host's public profile and return the rest of their roster in hostListings[]. Default: truetrue
maxHostListingsNointeger (1–10)Roster rows kept per profile. Airbnb never returns more than 10 on any public profile. Default: 1010
includeCoHostListingsNobooleanResolve every co-host on the listing and roster their portfolio too. Default: truetrue
minHostListingsNointeger (0–10000)Drop hosts whose real hostListingsCount is below this. Filtered rows are not written and not charged. Default: 02
mapPortfolioCitiesNobooleanResolve each portfolio property to a city and add cityBreakdown / distinctCities. Costs up to maxHostListings extra small requests per host. Default: falsefalse
enrichHostProfilesNobooleanAttach the legacy host.profile / coHosts[].profile cards. Default: falsefalse
enrichUserProfilesNobooleanOriginal name of the same switch; kept working for saved base inputs — turning on either one enables the profile cards. Default: falsefalse
checkInNostring (YYYY-MM-DD)Sent to Airbnb as check_in on every room URL"2026-09-15"
checkOutNostring (YYYY-MM-DD)Sent to Airbnb as check_out on every room URL"2026-09-18"
adultsNointeger (min 1)Guest count sent with each room request2
childrenNointeger (min 0)Children (ages 2–12) sent with each room request0
infantsNointeger (min 0)Infants (under 2) sent with each room request0
petsNointeger (min 0)Pets sent with each room request0
localeNostring, enum (93 values)Language of titles, property types, amenities and location subtitles. Default: "en-US""en-US"
currencyNostring, enum (48 values)Currency requested from Airbnb for any price-bearing field. Default: "USD""USD"
proxyConfigurationNoobjectApify Proxy or your own proxy URLs. Default: {"useApifyProxy": false}{"useApifyProxy": false}

Example input

{
"startUrls": [
"https://www.airbnb.com/rooms/25166525",
"https://www.airbnb.com/rooms/53309811",
"https://www.airbnb.com/users/show/213799039"
],
"includeHostListings": true,
"maxHostListings": 10,
"includeCoHostListings": true,
"minHostListings": 2,
"mapPortfolioCities": false,
"enrichHostProfiles": false,
"enrichUserProfiles": false,
"checkIn": "2026-09-15",
"checkOut": "2026-09-18",
"adults": 2,
"children": 0,
"infants": 0,
"pets": 0,
"locale": "en-US",
"currency": "USD",
"proxyConfiguration": { "useApifyProxy": false }
}

⬆️ Output

Typed, normalized JSON with a consistent schema across runs: one row per resolved room URL (type: "listing") and one row per host profile URL (type: "hostProfile"). Every listing row carries the full base listing record first, with the host-portfolio and co-host blocks merged on top. Export as JSON, CSV, Excel, XML, or RSS directly from the Apify dataset, or read it through the API while the run is still active.

Example output

{
"type": "listing",
"inputMode": "roomUrl",
"requestedUrl": "https://www.airbnb.com/rooms/53309811?adults=2&check_in=2026-09-15&check_out=2026-09-18",
"id": "53309811",
"listingId": "53309811",
"url": "https://www.airbnb.com/rooms/53309811?locale=en-US&currency=USD&adults=2",
"listingUrl": "https://www.airbnb.com/rooms/53309811",
"title": "Miami Lux Lake Front Retreat",
"description": "Wake up to lake views in this bright, fully renovated home minutes from Wynwood.",
"propertyType": "Entire home",
"roomType": "Entire home/apt",
"personCapacity": 12,
"location": "Miami",
"locationSubtitle": "Miami, Florida, United States",
"coordinates": { "latitude": 25.7889, "longitude": -80.2 },
"rating": {
"guestSatisfaction": 4.98,
"cleanliness": 4.98,
"communication": 4.99,
"location": 4.9,
"reviewsCount": 60
},
"host": {
"id": "268185052",
"name": "Omg Homes",
"isSuperHost": true,
"ratingCount": 974,
"ratingAverage": 4.94
},
"coHosts": [
{ "id": "471724265", "contextualUserId": "471724265", "name": "Ricardo" }
],
"amenities": [
{ "title": "Bathroom", "values": [ { "title": "Hair dryer", "available": true } ] }
],
"checkIn": "2026-09-15",
"checkOut": "2026-09-18",
"hostUserId": "268185052",
"hostProfileUrl": "https://www.airbnb.com/users/show/268185052",
"hostDisplayName": "Omg Homes",
"hostIsSuperhost": true,
"hostListingsCount": 3,
"hostListingsRosterCapped": false,
"hostListings": [
{
"listingId": "1392286122370334235",
"url": "https://www.airbnb.com/rooms/1392286122370334235",
"title": "Everglades-Homestead. Tropical Retreat. Miami-Keys",
"roomTypeCategory": "entire_home",
"roomTypeLabel": "Entire place",
"propertyType": "House",
"bedrooms": 4,
"beds": 6,
"bathrooms": 3.5,
"ratingAverage": 4.98,
"reviewsCount": 54,
"isSuperhost": true,
"instantBookEnabled": true,
"isNewListing": false,
"isCurrentListing": false
}
],
"hostPortfolioSummary": {
"listingsCount": 3,
"operatorTier": "small_operator",
"rosterRows": 3,
"rosterCapped": false,
"averageRating": 4.98,
"totalReviewsOnRoster": 335,
"entirePlaceCount": 3,
"entirePlaceShare": 1.0,
"superhostListings": 3,
"totalBedrooms": 12,
"totalBeds": 18,
"totalBathrooms": 11.5,
"propertyTypeBreakdown": [ { "propertyType": "House", "count": 3 } ]
},
"hostPortfolioResolved": true,
"coHostCount": 1,
"coHostListingsTotal": 3,
"coHostPortfolios": [
{
"coHostId": "471724265",
"coHostName": "Ricardo",
"coHostProfileUrl": "https://www.airbnb.com/users/show/471724265",
"listingsCount": 3,
"rosterCapped": false,
"isSuperhost": false,
"listings": [ "same shape as hostListings[]" ]
}
],
"language": "en-US",
"scrapedAt": "2026-08-04T00:00:00Z"
}

⚙️ How does it work?

Requests go out over curl_cffi with a Chrome 131 TLS fingerprint, since Airbnb sits behind Akamai and a plain Python client's fingerprint is refused before a page is even served. The listing content is read from the same pdpPresentation and StaysPdpSections structures Airbnb's own web app renders from; the host's roster comes from their public profile page, and co-host identities come from the "Meet your host" panel — all surfaces that require no login, cookie or API key. A missing data container in an HTTP 200 response is treated as a soft block and triggers a proxy-ladder escalation, while a genuinely de-listed or private listing is recognized as such and skipped rather than retried. The output schema stays the same shape regardless of which Airbnb layout served the page, so a UI change on Airbnb's side does not change your downstream field names.

🔌 Integrations

Works with anything that can call the Apify API — no separate signup or credential beyond your Apify API token.

Calling the scraper programmatically

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_API_TOKEN>")
run = client.actor("<YOUR_USERNAME>/airbnb-rooms-urls-scraper-host-portfolio-and-co-host-listings").call(
run_input={
"startUrls": ["https://www.airbnb.com/rooms/25166525"],
"includeHostListings": True,
"includeCoHostListings": True,
}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["hostDisplayName"], item["hostListingsCount"])

Works in Go, Ruby, Node.js, cURL — any language that can make an HTTP request.

No-code tools (n8n, Make)

In n8n, use the HTTP Request node pointed at the Actor's run-sync-get-dataset-items endpoint with your input JSON as the body. In Make, the Apify app module runs the Actor and passes the resulting dataset items straight into the next step of your scenario — no separate database wiring needed.

Scraping publicly accessible data — the same information any visitor sees without logging in — is generally lawful, including under precedent such as hiQ Labs v. LinkedIn in the United States. The Airbnb Host Portfolio and Co-Host Listings Scraper returns only publicly available data: listing content plus the host and co-host identities and rosters Airbnb itself displays to any visitor. Because this data includes personal data about identifiable individuals — a host's or co-host's name, photo, bio and portfolio — GDPR (in the EU/UK) and the CCPA (in California) govern how you may store, use and retain it once collected; you need a lawful basis for processing personal data and should honor deletion or access requests from data subjects. Consult legal counsel if your use case involves bulk storage of personal data.

❓ Frequently asked questions

What Airbnb host and listing fields does this scraper return?

The top fields are hostListingsCount (the host's real portfolio size), hostListings[] (the roster itself), coHostPortfolios[], hostPortfolioSummary, and the full base listing record (title, description, amenities, rating). See What data can you extract above for the complete field set.

Does this scraper require an Airbnb account or login?

No. Every surface it reads — the room page, the host's public profile, and the "Meet your host" panel — is public and requires no cookie, session or API key.

How many Airbnb hosts or listings can I extract in one run?

startUrls accepts any number of room URLs, host profile URLs or search phrases in a single run — there is no schema-level cap on the list. A search phrase resolves up to 20 listing ids per keyword. Internally, up to 6 targets are processed concurrently.

What happens if a listing is de-listed or a host has no public profile?

A de-listed, private or removed listing still returns HTTP 200 with an empty payload; the Actor recognizes this as an unavailable listing (not a block), logs it, and does not write a row for it. A host profile with no parseable public container is handled the same way — hostPortfolioResolved is false on rows that do get written, or the target is skipped entirely if it was the only thing being resolved. Skipped and filtered rows are never written to the dataset and never charged, so check the Actor's run log for FAILED entries if a dataset row count is lower than your input list.

Can I scrape multiple Airbnb hosts or listings at once?

Yes. Mix room URLs, host profile URLs and search phrases in the same startUrls array; each is resolved independently and profile fetches are cached per run, so overlapping hosts across many listings only cost one fetch each.

Does this scraper work with Claude, ChatGPT and other AI agent tools?

It is callable as a standard HTTP endpoint by any agent framework — start a run via the Apify API or apify_client and read the resulting dataset. No MCP server is documented for this Actor.

How does this differ from the standalone Airbnb Rooms URL Scraper?

It is a superset: all of the base listing scraper's 11 input keys still work exactly as before, and every one of the 35 base listing fields (verified against data_extractor.build_output) is produced first, unchanged. This variant adds the host-portfolio block, the co-host-portfolio block, and the roster roll-up on top — nothing from the base row is renamed or removed.

Does this scraper return data in a format LLMs can use directly?

Yes. Typed, normalized JSON with consistent field names across runs — no HTML parsing, no CSS selectors. Pass it directly to an LLM's context, index it into a vector store, or feed it to an agent tool.

What happens when Airbnb changes its layout or anti-bot system?

The Actor is maintained and the output schema is designed to stay stable across Airbnb front-end changes — the source already tracks one such migration, from Airbnb's older sections[] array to the current pdpPresentation structure. No specific update turnaround time is published.

Can I use this scraper without managing proxies or browser infrastructure?

Yes. It ships with a Chrome-TLS-fingerprint HTTP client and an automatic proxy ladder (none → Apify datacenter → Apify residential) that escalates on its own when a response looks blocked. You can also supply your own Apify Proxy or third-party proxy URLs via proxyConfiguration.

Which fields work best for AI training data and RAG indexing?

For RAG, index description, hostProfileAbout and host.about — the highest-information free text. For structured training features, hostListingsCount, hostPortfolioSummary, and rating return as consistent typed primitives (integers, floats, booleans) across every row.

ScraperWhat it extracts
../tripadvisor-review-scraperHotel reviews, ratings, reviewer profiles and owner responses — the reviewer side of the hospitality data this Actor covers from the host side
../Google-Maps-ExtractorBusiness name, address, phone, website, rating and coordinates for any place on Google Maps — useful for cross-referencing a host's portfolio addresses against real-world business listings

💬 Your feedback

Found a bug or missing a field? Let us know through the Actor's Issues tab on the Apify Console, or leave a review on the Store listing — it is the fastest way to get a fix prioritized.