Airbnb Host Portfolio & Operator Mapper avatar

Airbnb Host Portfolio & Operator Mapper

Pricing

from $0.80 / 1,000 row saveds

Go to Apify Store
Airbnb Host Portfolio & Operator Mapper

Airbnb Host Portfolio & Operator Mapper

Turn Airbnb listings into host entities. One row per operator: every listing found in the areas you scan, whole-property share, years hosting, registration numbers and an auditable 0-100 operator score. Filter to multi-property hosts, scan a city as a grid, get a coverage report. No account needed.

Pricing

from $0.80 / 1,000 row saveds

Rating

0.0

(0)

Developer

Hamza

Hamza

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

17 days ago

Last modified

Share

Airbnb shows you listings. This actor shows you the people and companies behind them. Point it at a city or a map rectangle and it comes back with one row per host: every listing of theirs it found, how many are whole properties, how long they have been hosting, their own rating, the registration or licence number on each listing and where that number was published, the geographic centre and spread of their portfolio, and a published 0–100 commercial-operator score. It is built for regulators, housing researchers, hotel and short-let analysts, and anyone who needs to separate the neighbour renting a spare room from an operator running forty flats. No Airbnb account, no login, nothing to connect.

What you can do with it

  • Find the commercial operators in a market. Set a minimum portfolio size of two or more and the dataset becomes a list of multi-property hosts, ranked by size and by operator score.
  • Support a short-let compliance review. Every listing reports its registration or licence number and which of the places Airbnb publishes it the number came from, plus an optional check against the format your city uses.
  • Measure real market concentration. Whole-property share, portfolio size distribution and median nightly rate per host tell you how much of a neighbourhood's supply sits with a handful of operators.
  • Build a property-management prospect list. Hosts with several whole properties, a real tenure and no superhost badge are exactly the audience for management, cleaning, insurance and pricing tools.
  • Map a competitor's footprint. The portfolio centroid, spread in kilometres and neighbourhood list show where an operator actually concentrates.
  • Track a market over time. Run it on a schedule and compare host rows between runs to see who is growing, who has left and who has newly appeared.

What you get

One row per host. Abridged example:

{
"recordType": "host",
"hostUserId": "10214195",
"hostName": "Pierre",
"hostProfileUrl": "https://www.airbnb.com/users/profile/1462834525352805037",
"hostContextualUserId": "1462834525352805037",
"isSuperhost": false,
"isVerified": true,
"hostTitleText": "Host",
"yearsHosting": 11,
"monthsHosting": 133,
"hostRatingAverage": 4.68,
"hostRatingCount": 79,
"listingCount": 2,
"listingCountIsComplete": false,
"listingCountScope": "Minimum — listings found in the areas scanned (Paris, France); the host may hold more",
"listingCountStatement": "2 listings found for this host in the areas this run scanned (Paris, France). That is a minimum, not a total: the scan stopped at the listing limit set for the run, so this host may hold more listings in the same areas. Listings this host holds outside the areas scanned are not counted, and Airbnb does not publish a host's total listing count anywhere on a listing page, so no tool can report one. Scan a wider area or raise the listing limit to raise this floor.",
"placesSeenIn": ["Paris, France"],
"coverageConfidence": "partial",
"scanStoppedAtListingLimit": true,
"scanStoppedAtRunLimit": false,
"areasLeftCrowded": 0,
"portfolioMetricsArePartial": true,
"listingIds": ["1737062443587734735", "1716681499327714304"],
"entireHomeCount": 2,
"entireHomeSharePct": 100,
"privateRoomCount": 0,
"medianNightlyRate": 217.2,
"currency": "USD",
"totalPersonCapacity": 8,
"medianBedrooms": 1,
"listingsWithRegistration": 2,
"listingsWithoutRegistration": 0,
"registrationNumbers": ["7510203094826"],
"licenceSources": ["descriptionModal"],
"registrationFormatValidCount": 1,
"centroidLatitude": 48.87051,
"centroidLongitude": 2.34879,
"coordinateSpreadKm": 4.311,
"neighbourhoods": ["Paris, Île-de-France, France"],
"commercialOperatorScore": 47,
"commercialOperatorScoreIsProvisional": true,
"commercialOperatorVerdict": null,
"commercialOperatorVerdictBasis": "No verdict: the scan covered part of the area, so a larger portfolio cannot be ruled out and calling this host small would be a guess. The score of 47 out of 100 describes only the listings found here.",
"commercialOperatorScoreInputs": {
"listingCount": 2,
"entireHomeCount": 2,
"entireHomeSharePct": 100,
"yearsHosting": 11,
"portfolioSizePoints": 6.67,
"entireHomePoints": 25,
"tenurePoints": 15
},
"placesScanned": ["Paris, France"],
"scrapedAt": "2026-07-29T10:00:00.000Z"
}

Alongside the host rows you also get, unless you switch them off, one recordType: "listing" row per property — with its own registrationNumber, licenceSource, propertyType, bedrooms, beds, bathrooms, personCapacity, ratingValue, reviewCount, coordinates and the host it belongs to — and one recordType: "coverageReport" row per area scanned, which states in plain English how much of that area was actually covered.

Input reference

FieldTypeDefaultWhat it does
placeslist of strings["Paris, France"]Cities or areas to scan, written the way you would type them into Airbnb's own search box. Up to 10.
bboxeslist of objects[]Optional exact rectangles, each {neLat, neLng, swLat, swLng} with an optional query naming the neighbourhood. Up to 20.
tileSaturationThresholdinteger240When one map area reaches this many listings it is divided into four smaller areas and each is scanned again. Lower is more thorough and slower. Max 320.
maxQuadtreeDepthinteger3How many times a crowded area may be divided. Max 6.
roomTypesmulti-select[]Restrict to Entire home/apt, Private room, Shared room or Hotel room. Whole properties are what short-let rules usually target.
priceBandslist of objects[]Optional {min, max} slices, used only when an area is still crowded after being divided as far as allowed. Up to 8.
minPortfolioSizeinteger1Only save hosts with at least this many listings in the area scanned. Set 2+ for multi-property operators only. Max 50.
unregisteredOnlybooleanfalseSave only hosts with at least one listing whose registration number is not visible.
registrationFormatstringemptyOptional pattern each number is checked against, e.g. ^\d{13}$. Each record then reports whether it matched.
includeLicencebooleantrueCollect registration and licence numbers.
emitListingRowsbooleantrueAlso save one row per listing behind each portfolio. Turning it off lowers both the row count and the cost.
maxListingsinteger500The main size and cost control: how many listings get looked up individually to find their host. It also decides how much of an area you see — see the note below. Max 5,000.
maxRequestsinteger800A hard ceiling on total work per run. The run stops cleanly when it is reached and the coverage report says so. Max 8,000.
Parallel workersinteger4How many listings are worked through at the same time. Higher finishes sooner; 4 is a good balance. Max 8.
currencystringUSDCurrency for the nightly rates in the output.
localestringenLanguage for names, property types and neighbourhood labels.
proxyCountrystringemptyCountry to appear to browse from, as a two-letter code. Leave empty unless a market looks different from different countries.

What the default 500 buys, and when to change it. 500 is a cheap first look — enough to scan a single district until it stops producing new listings. A whole city is a different job: Paris alone carries tens of thousands of listings, so a 500-listing run over it is a thin slice, and in a thin slice almost every host looks like a one-property host — a real operator with thirty flats across the city only shows the handful that happened to fall inside the slice. That is a fact about how much was scanned, not about the market, and the run says so in the log, in the coverage report and on every host row.

The default is deliberately left small, because it is also what you are billed for and raising it does not on its own make a city complete: even the 5,000 maximum is a fraction of Paris. If you want portfolios rather than a sample, scan an area small enough to finish — one or two map rectangles over the districts you care about — and the run can then tell you a host is small, instead of withholding the verdict. If you want a broad market sweep, raise maxListings and read every count as the floor it is labelled as.

Output fields

Host rows (recordType: "host")

FieldTypeDescription
hostUserIdstringAirbnb's own identifier for the host. Stable between runs, so it is the key to join on.
hostName / hostTitleTextstringDisplay name, and the label Airbnb shows under it (Host, Superhost).
hostProfileUrl / hostContextualUserIdstringLink to the public profile, and the separate identifier that link is built from.
isSuperhost / isVerifiedbooleanBadge and identity-verification status.
yearsHosting / monthsHostingnumberTenure, in whole years and in total months.
hostRatingAverage / hostRatingCountnumberThe host's own rating and review total across all their listings.
listingCount / listingIdsnumber / arrayHow many of this host's listings the run found in the areas it scanned, and their identifiers. It is a floor, not a verified total — see the note under this table.
listingCountIsCompletebooleantrue only when every area this host appeared in was scanned until it stopped producing new listings. false means the count is a minimum.
listingCountScopestringOne line naming exactly what the count covers, so a column of numbers is never read on its own.
listingCountStatementstringThe same thing in full sentences: what was counted, why it may be short, and how to raise it.
placesSeenIn / coverageConfidencearray / stringWhich of the areas you asked for this host turned up in, and how well those areas were covered (high, partial, low, unknown).
scanStoppedAtListingLimit / scanStoppedAtRunLimit / areasLeftCrowdedboolean / boolean / numberWhether your listing limit or the run's own size limit ended the scan early, and how many areas were still producing new listings when it stopped. Any of these means the count is short.
portfolioMetricsArePartial / metricsAffectedByScanScopeboolean / arrayWhether the portfolio numbers on this row are bounded by the scan, and the exact list of columns that are.
entireHomeCount / entireHomeSharePct / privateRoomCountnumberHow much of the portfolio found in the areas scanned is a whole property versus a room.
medianNightlyRate / currencynumber / stringMedian nightly rate observed across the portfolio, in your chosen currency.
totalPersonCapacity / medianBedroomsnumberCombined guest capacity and typical property size, across the listings found.
listingsWithRegistration / listingsWithoutRegistrationnumberHow many of the listings found publish a registration number. Both are counts of what was found, so both move if a wider area is scanned.
registrationNumbers / licenceSourcesarrayThe distinct numbers found, and where each was published.
registrationFormatValidCountnumberHow many matched your expected format. Null when no format was given.
centroidLatitude / centroidLongitude / coordinateSpreadKmnumberGeographic centre of the portfolio and the distance between its two furthest listings.
neighbourhoodsarrayNeighbourhood labels the portfolio spans.
commercialOperatorScorenumber0–100 composite, see below. Built from the listings found, so it moves as the scan widens.
commercialOperatorScoreIsProvisionalbooleantrue when the score was computed from a portfolio that was only partly found.
commercialOperatorVerdictstringlikely commercial operator, small or individual host, or blank. It is left blank rather than guessed whenever the areas were not scanned in full and the listings found are too few to be sure — calling a large operator a small host is the one mistake this dataset refuses to make.
commercialOperatorVerdictBasisstringWhy the verdict says what it says, in one sentence.
commercialOperatorScoreInputsobjectEvery number that produced the score, so it can be recomputed by hand.
placesScannedarrayWhich of your inputs this run covered.
scrapedAt / actorRunIdstringWhen the row was produced, and by which run.

About listingCount. It counts the host's listings that this run found in the areas it scanned. It is a floor, not a verified total: the same host may hold more listings in the same city that the run did not reach, and more again in cities it never looked at. Airbnb does not publish a host's total listing count anywhere on a listing page — a listing page carries the host's rating, review count and how long they have been hosting, and nothing about how many properties they hold — so no tool can report a verified total, and any that claims to is counting what it happened to find. To raise the floor, scan a wider area (more cities, or map rectangles covering the neighbourhoods you care about) and raise maxListings so the sweep is not cut short. Sort by listingCount to rank operators, but read listingCountIsComplete and listingCountScope before quoting any single number.

Listing rows (recordType: "listing")

listingId, listingUrl, listingName, listingTitle, latitude, longitude, propertyType, roomTypeText, personCapacity, bedrooms, beds, bathrooms, ratingValue, reviewCount, isGuestFavorite, nightlyRate, currency, neighbourhood, registrationNumber, hasRegistration, licenceSource, registrationFormatValid, hostUserId, hostName, isSuperhost, tileId, tileDepth, place, scrapedAt.

Coverage rows (recordType: "coverageReport")

place, rootBbox, tilesVisited, tilesSplit, tilesStillSaturated, uniqueListings, requestsUsed, budgetExhausted, listingCeilingReached, maxDepthReached, mapAreasUnread, mapAreasPartlyRead, coverageConfidence (high / partial / low), completenessStatement, listingsEnumerated, listingsResolved, listingsAttributed, listingsWithoutHostCard, listingsWithoutPdp, hostsFound, hostsBelowMinPortfolio, scrapedAt.

listingsResolved counts the listings whose details were read; listingsAttributed counts the ones that actually named a host, and listingsWithoutHostCard counts the difference — listings that published no host at all. Only the attributed ones can appear in a portfolio, so those three numbers, plus listingsWithoutPdp, add up to listingsEnumerated.

listingCeilingReached is true when the scan stopped because it had collected as many listings as you allowed, rather than because the areas ran out. When that happens the confidence is never high and the plain-English statement says so — a run that stops at your own limit has seen a slice of the market, not all of it.

How the operator score is calculated

The score is a published formula, not a black box, and every input to it is in the row so you can check the arithmetic:

ComponentWeightHow it is awarded
Portfolio size60 points1 listing scores 0; 10 or more scores the full 60; linear in between.
Whole-property share25 points25 × the share of the portfolio that is a whole property rather than a room.
Tenure15 points15 × (years hosting ÷ 5), capped at 5 years.

So a host with ten whole properties and five years of hosting scores 100, while a long-standing host with a single whole flat scores 40 — the size of the portfolio is deliberately the dominant term. It is a comparison aid, not an official designation of any kind.

Because portfolio size dominates, the score moves with how much ground the run covered. That is why each row carries commercialOperatorScoreIsProvisional and why commercialOperatorVerdict is asymmetric: likely commercial operator is given whenever the listings already found earn 50 points or more, since finding more of a host's listings cannot make them smaller — but

small or individual host
is only ever given when every area that host appeared in was scanned until it stopped producing new listings. Anywhere else the verdict is left blank, with the reason in commercialOperatorVerdictBasis. A blank verdict means "not established", never "small".

Pricing

This actor is pay per event and there are two charges:

  • Row saved — $0.0008 for every row written, which is $0.80 per 1,000 rows. It covers host rows, listing rows and coverage rows alike.
  • Listing host resolved — $0.008 each time one listing is opened individually to read who hosts it and whether a registration number is published. This is the real work behind the dataset: it happens once per listing, and it is the reason maxListings is the setting that controls your bill.

A typical first pass — 500 listings resolved into roughly 300 host rows — costs about $4.24, or about $4.64 with the per-listing rows kept as well. Filtering by minimum portfolio size or by missing registration reduces the rows you keep but not the resolution charge, because a host can only be filtered once their listings have been attributed to them. Areas that turn out to be empty cost nothing, and if you set a maximum cost for a run the actor stops cleanly as soon as that budget is spent rather than overshooting it.

Limits and what this actor cannot do

Every one of these is real, and most of them are Airbnb's own ceilings rather than this actor's:

  • listingCount is a floor, never a verified total. It counts the host's listings this run found inside the areas it scanned. Airbnb does not publish a host's total listing count anywhere on a listing page — the page carries their rating, review count and how long they have been hosting, and nothing about how many properties they hold — so no tool can report a verified total, and one that claims to is reporting what it happened to find. Every host row therefore carries listingCountIsComplete, listingCountScope and the coverage grade for the areas that host was seen in, so the qualifier travels with the number even when you sort, filter or export. To raise the floor: scan a wider area (add cities, or map rectangles over the neighbourhoods you care about) and raise maxListings so the sweep is not cut short. A run of 500 listings over a city with tens of thousands will show most operators as one- or two-property hosts, because that is all it looked at.
  • Everything counted out of the portfolio inherits that floor — whole-property share, guest capacity, how many listings lack a registration number, and the operator score itself. Each host row names those columns in metricsAffectedByScanScope and flags them with portfolioMetricsArePartial. Where the areas were not scanned in full, the row gives a score but withholds the one-word verdict rather than label a large operator a small host.
  • Airbnb publishes no index of a host's listings. A portfolio can only be assembled by scanning an area and grouping what is found, so a host with properties outside the area you scanned is under-counted. This is the single most important limitation of this dataset, and it is why every run ships a coverage report.
  • Airbnb shows only a few hundred listings for any single search and starts repeating itself past that point. A market is therefore covered by splitting it into map areas and merging the results, and coverage cannot be proven complete — the coverage report names the areas that were still crowded when scanning stopped and gives a confidence level of high, partial or low. Even high means "thorough for the area scanned", never "complete".
  • Registration and licence numbers are published inconsistently by market. Each record reports where its number was found, and a blank means "not published anywhere we can see it" — not that a listing is unlicensed or that a host is breaking any rule. Treat the unregisteredOnly filter as a starting point for a review, never as a finding.
  • The host's own rating count is host-level. It covers all of their listings and legitimately differs from any single listing's review count — 79 against 78 on a real host we checked. Both numbers are in the output; do not compare them as if they measured the same thing.
  • Bedroom, bed and bathroom counts come from the listing's own summary line, which is the only place Airbnb publishes them. A listing described only as a studio has no bedroom count, and that is reported as blank rather than guessed.
  • Nightly rates are what Airbnb was showing at the time of the run, for its own default stay window and without any dates of yours. They are useful for comparing hosts within one run, not as a booked-revenue figure, and cleaning and service fees are not itemised separately.
  • The operator score is a composite with published weights, not an official classification, a legal determination or a measure of anything Airbnb itself publishes. Because it is built from the listings found, it moves as the scan widens, and a low score on a partly scanned area means "not shown to be large here", never "small".
  • A host with no published host card cannot be attributed. Those listings are counted separately in the run log and in each coverage row, and left out of the portfolios rather than assigned to a placeholder — which is why the listings looked up and the listings attributed to a host are two different numbers.
  • Only English has been verified. Other languages will change how property types, neighbourhood labels and summary lines read, and the size parsing has not been checked against them.
  • Speed depends on the size of the job and on how quickly Airbnb answers. No fixed run time is promised.
  • Airbnb's terms prohibit automated access. You are responsible for using this data lawfully and in line with the source site's terms, and for whatever conclusions you draw from it.

FAQ

Do I need an Airbnb account? No. No Airbnb account, no login, no personal details — enter a city and run it.

Is the data complete? No, and no tool can make it so. Airbnb never publishes a list of a host's properties nor a count of them, and it stops showing new listings for any one search after a few hundred. This actor gets past the second problem by scanning a market as a grid of smaller areas, but the honest answer travels on every row: listingCount is what was found in the areas scanned, listingCountIsComplete says whether those areas were finished, and the coverage report grades each area high, partial or low. Read those before quoting a number.

Does a blank registration number mean the listing is illegal? No, and please do not report it that way. It means no number was published anywhere visible for that listing. Some markets do not require one, some hosts put it somewhere the public page does not show, and some listings are exempt. Every record that does carry a number also says where it was found, which is what makes the positives auditable.

Can I run it on a schedule? Yes. Host rows are keyed on hostUserId, which is stable between runs, so comparing two runs of the same area shows you which operators grew, shrank, appeared or disappeared. Keep the place list and the size settings identical between runs or the comparison will reflect your settings rather than the market.

How do I get only the big operators? Set minPortfolioSize to 2 or more. Bear in mind that portfolio size is measured inside the area you scanned, so widening the area usually raises it — a host with three flats across a city looks like a one-listing host if you only scan one district.

Why do some hosts have fewer listings than I expected? Because the number is a floor. Either their remaining listings sit outside the area scanned, or the run hit its maxListings ceiling before reaching them — the row itself says which, in listingCountScope, scanStoppedAtListingLimit and areasLeftCrowded. Airbnb publishes no total to compare against, so widening the area and raising maxListings is the only way to raise the floor. The coverage report's listingsWithoutPdp figure tells you how many listings were found but never looked up, and listingsWithoutHostCard how many were looked up but published no host at all.

Can I get a full year of prices or availability per listing? Not from this actor — it is built around host identity. Use the companion occupancy and price-tracking actors for that.