Datasets API endpoint
Returns aggregate Airbnb short-term-rental market rollups from the dataset id enum value `airbnb-markets`. Aggregate-only: each row is a market cell, never an individual listing. Thin cells are suppressed. group_by enum: `country`, `market`, `admin1` (top subdivision), `locality` (settlement), `room_type` (`entire_place`/`private_room`/`hotel`/`shared_room`), `property_type` (Airbnb's canonical listing type from the detail page). `admin1`, `locality`, `room_type` and `property_type` are enrichment-derived and stay empty until their coverage is high enough to be reliable. Each cell also carries `median_price_usd`, the median nightly price converted to USD via an approximate dated FX snapshot, for cross-country comparison (combine with `group_by=room_type` for median price by room type); `guest_favorite_pct`, the share of listings carrying the Guest Favorite badge (an observed lower bound, like `superhost_pct`); and `avg_person_capacity`, the average guests a listing sleeps over the detail-page-enriched sample. Sort enum: `listings_desc`, `superhost_pct_desc`, `rating_desc`, `key_asc`. Billing: this search costs 1 credit per record returned, with a minimum of 2 (an empty result costs 2, a full page of 100 costs 100).
/datasets/airbnb-markets/searchReturns aggregate Airbnb short-term-rental market statistics rolled up from a large public-listing supply census. Each result row is a market cell — a country (default) or a metro — with listing supply, Superhost share, ratings and review counts. It is aggregate-only: it never returns individual listings, hosts, photos or review text, and cells below the small-cell suppression floor are omitted entirely.
Dataset id enum:
airbnb-marketsQuery parameters:
group_by: optional aggregate cell dimension. Allowed values: country, market, admin1, locality, room_type, property_type. Defaults to country. admin1 is the top subdivision (state/province/region) and locality is the settlement (city/town/village), both derived from reverse geocoding. room_type buckets each market by listing type — entire_place, private_room, hotel, shared_room — so you can compare supply and price across accommodation types. property_type is Airbnb's finer canonical listing type (e.g. Entire guest suite, Private room in rental unit), read authoritatively from the listing detail page.country: optional exact ISO-3166-1 alpha-2 country filter, e.g. FR.market: optional exact metro-market filter, e.g. Paris, max 128 characters.superhost: optional filter to count only Superhost listings.guest_favorite: optional filter to count only Guest Favorite listings (an observed lower bound; the badge under-counts).min_rating: optional minimum listing rating, from 0 through 5.min_review_count: optional minimum listing review count, 0 or greater.active_since: optional freshness filter, an ISO-8601 date (YYYY-MM-DD); only listings last seen on or after it are counted.min_listings: optional minimum listings per cell; raises the small-cell suppression floor. It can only raise the floor, never lower it below the built-in minimum.sort: optional sort order. Allowed values: listings_desc, superhost_pct_desc, rating_desc, key_asc. Defaults to listings_desc.page: optional page number, defaults to 1.page_size: optional page size, defaults to 20 and maxes at 100.Response behavior:
admin1, locality, room_type or property_type returns enrichment-derived market cells (sub-country geography, or accommodation type). admin1/locality come from a reverse-geocode pass, room_type (entire_place, private_room, hotel, shared_room) is classified from each listing's search-card descriptor going forward, and property_type (Airbnb's finer canonical type) is read from the listing detail page. Because each covers a growing share of the census, these dimensions return an empty items array until that coverage is high enough for the cell counts to be reliable, then fill in on their own as coverage grows. country and market are always available.avg_person_capacity is the average number of guests a listing sleeps, computed over the cell's detail-page-enriched sample; like the *_enriched fields it is reported only once that sample is large enough to be reliable. Combine it with median_price_usd for a rough price-per-guest read.group_by=room_type with median_price_usd gives the median nightly USD price per accommodation type (e.g. entire homes vs private rooms), optionally filtered to one country or market.median_price_usd is the cell's median nightly price converted to USD via an approximate, dated FX snapshot, so markets are price-comparable across countries despite Airbnb localizing the display currency. It is reported only for cells with enough USD-normalized priced listings and is a market-level approximation, not an exact conversion.avg_rating is reported only for cells with enough rated listings, so a handful of reviews never swings a published market average; it is omitted otherwise.superhost_pct is the Superhost share of the cell, from 0 through 100. It is an observed lower bound: it counts listings seen carrying the Superhost badge on the search card, which renders inconsistently, so it under-counts.guest_favorite_pct is the share of the cell's listings carrying the Guest Favorite badge, from 0 through 100, with guest_favorite_listings the underlying count. Like superhost_pct it is an observed lower bound — the badge renders inconsistently on the search card, so it under-counts.superhost_pct_enriched is the reliable Superhost share, computed over a random sample of the cell's listings enriched from the listing detail page (enrichment draws a representative sample, so the rate is unbiased even at partial coverage). It, along with enriched_listings (the size of that enriched sample), distinct_hosts (the number of distinct operators among the enriched listings) and listings_per_host (enriched_listings / distinct_hosts, an operator-concentration signal), is reported only once the enriched sample is large enough to be reliable; all four are omitted until then. Detail-page enrichment covers a growing subset of the census, so these fields appear for more markets over time. distinct_hosts is an aggregate count only — no host identity is ever returned.guest_favorite_pct_enriched is the reliable Guest Favorite share over that same detail-page-enriched sample (the listing detail page carries an authoritative Guest Favorite flag, unlike the inconsistent search-card badge behind guest_favorite_pct). It is reported under the same gate as superhost_pct_enriched and omitted until the enriched sample is large enough.min_listings field in the response echoes the effective suppression floor that was applied.10000; page * page_size must not exceed 10000.items array (not an error) when no cell clears the suppression floor.1 credit per record returned, minimum 2. A search that returns 20 records costs 20 credits, a full page of 100 costs 100, and an empty or one-record result costs 2. You are charged for what comes back, not for the page_size you ask for, but your balance must cover the requested page_size for the call to be accepted. The response header x-credit-cost shows what a call was charged.
| Field | Filled in, of 1 checked | Values in the sample |
|---|---|---|
| key | 1 | |
| listings | 1 | 1,348,902 |
| superhost_listings | 1 | 438,199 |
| superhost_pct | 1 | 32.5 |
| guest_favorite_listings | 1 | 573,945 |
| guest_favorite_pct | 1 | 42.5 |
| rated_listings | 1 | 1,139,658 |
| avg_rating | 1 | 4.67 |
| avg_review_count | 1 | 66.7 |
| median_price_usd | 1 | 245.1 |
| enriched_listings | 1 | 357,275 |
| superhost_pct_enriched | 1 | 58.2 |
| guest_favorite_pct_enriched | 1 | 48.9 |
| avg_person_capacity | 1 | 5.99 |
| distinct_hosts | 1 | 217,056 |
| listings_per_host | 1 | 1.65 |
| last_seen | 1 | 2026-07-29 |
| Parameter | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
| group_by | string | No | country | Aggregate cell dimension enum: country, market, admin1, locality, room_type, property_type. Defaults to country Allowed values: country, market, admin1, locality, room_type, property_type. | |
| country | string | No | Exact ISO-3166-1 alpha-2 country filter, e.g. FR | ||
| market | string | No | Exact metro-market filter, e.g. Paris, max 128 characters | ||
| superhost | boolean | No | Count only Superhost listings | ||
| guest_favorite | boolean | No | Count only Guest Favorite listings (an observed lower bound; the badge under-counts) | ||
| min_rating | number | No | Minimum listing rating, from 0 through 5 | ||
| min_review_count | integer | No | Minimum listing review count, 0 or greater | ||
| active_since | string | No | Freshness filter, an ISO-8601 date (YYYY-MM-DD); only listings last seen on or after it are counted | ||
| min_listings | integer | No | Minimum listings per cell; raises the small-cell suppression floor (never lowered below the built-in minimum) | ||
| sort | string | No | Sort enum: listings_desc, superhost_pct_desc, rating_desc, key_asc Allowed values: listings_desc, superhost_pct_desc, rating_desc, key_asc. | ||
| page | integer | No | 1 | Page number, defaults to 1 | |
| page_size | integer | No | 20 and maxes at 100 | Page size, defaults to 20 and maxes at 100; page * page_size must be <= 10000 | |
| x-api-key (header) | string | Yes | API key required |
curl -X GET "https://api.crawlora.net/api/v1/datasets/airbnb-markets/search?group_by=country&country=us&superhost=true&guest_favorite=true&sort=listings_desc&page=1" \ -H "x-api-key: $CRAWLORA_API_KEY"
{
"code": 200,
"msg": "OK",
"data": {
"dataset": "airbnb-markets",
"group_by": "country",
"items": [
{
"key": "US",
"listings": 1212294,
"superhost_listings": 303073,
"superhost_pct": 25,
"guest_favorite_listings": 121229,
"guest_favorite_pct": 10,
"rated_listings": 776000,
"avg_rating": 4.72,
"avg_review_count": 31.5,
"median_price_usd": 148,
"enriched_listings": 280000,
"superhost_pct_enriched": 29.4,
"guest_favorite_pct_enriched": 18.7,
"avg_person_capacity": 4.2,
"distinct_hosts": 214500,
"listings_per_host": 1.31,
"last_seen": "2026-07-03T00:00:00Z"
}
],
"page": 1,
"page_size": 20,
"total": 1,
"sort": "listings_desc",
"min_listings": 50
}
}Request schema
No body schema
Response schema
#/definitions/datasets.airbnbMarketsSearchResponseDoc
| Field | Type | Required | Enum | Bounds | Example | Description |
|---|---|---|---|---|---|---|
| code | integer | No | 200 | |||
| data | datasets.AirbnbMarketSearchResponse | No | ||||
| data.dataset | string | No | Identifier of the dataset queried (`airbnb-markets`). | |||
| data.group_by | string | No | Dimension the cells are grouped by: `country`, `market`, `admin1`, `locality`, `room_type` or `property_type`. | |||
| data.items | array | No | Aggregate market cells on this page, one per group. | |||
| data.items[].avg_person_capacity | number | No | Average number of guests a listing sleeps, over the sampled listings. Omitted until the sample is large enough. | |||
| data.items[].avg_rating | number | No | Average listing rating across rated listings. Omitted when the market has too few rated listings. | |||
| data.items[].avg_review_count | number | No | Average number of reviews per listing. | |||
| data.items[].distinct_hosts | integer | No | Number of distinct hosts among the sampled listings. Omitted until the sample is large enough. | |||
| data.items[].enriched_listings | integer | No | Number of listings in the detail-page sample behind the reliable rates. Omitted when no listing has been sampled. | |||
| data.items[].guest_favorite_listings | integer | No | Number of listings seen with the Guest Favorite badge. | |||
| data.items[].guest_favorite_pct | number | No | Share of listings seen with the Guest Favorite badge, from 0 to 100. A lower bound, because the badge does not always show. | |||
| data.items[].guest_favorite_pct_enriched | number | No | Share of sampled listings that are Guest Favorites, from 0 to 100, taken from listing detail pages. Omitted until the sample is large enough. | |||
| data.items[].key | string | No | Market this row covers: a country code, metro name or other value of the chosen `group_by` dimension. | |||
| data.items[].last_seen | string | No | Most recent time a listing in this market was seen, in UTC (RFC 3339). | |||
| data.items[].listings | integer | No | Number of listings in the market. | |||
| data.items[].listings_per_host | number | No | Sampled listings divided by distinct hosts, a sign of how concentrated hosting is. Omitted until the sample is large enough. | |||
| data.items[].median_price_usd | number | No | Median nightly price in US dollars, converted with an approximate dated exchange rate. Omitted when too few listings have a price. | |||
| data.items[].rated_listings | integer | No | Number of listings that have a rating. | |||
| data.items[].superhost_listings | integer | No | Number of listings seen with the Superhost badge on the search card. | |||
| data.items[].superhost_pct | number | No | Share of listings seen with the Superhost badge, from 0 to 100. A lower bound, because the badge does not always show. | |||
| data.items[].superhost_pct_enriched | number | No | Share of sampled listings that are Superhosts, from 0 to 100, taken from listing detail pages. Omitted until the sample is large enough. | |||
| data.min_listings | integer | No | Minimum number of listings a cell needs to be included. | |||
| data.page | integer | No | Page number returned. | |||
| data.page_size | integer | No | Number of items per page. | |||
| data.sort | string | No | Sort order applied. | |||
| data.total | integer | No | Total number of cells. | |||
| msg | string | No | OK |
| Status | Description | Schema |
|---|---|---|
| 400 | Bad Request | #/definitions/app.Response |
| 429 | Too Many Requests | #/definitions/app.Response |
| 500 | Internal Server Error | #/definitions/app.Response |
Use environment variables for secrets and keep Crawlora API keys server-side.
curl -X GET "https://api.crawlora.net/api/v1/datasets/airbnb-markets/search?group_by=country&country=us&superhost=true&guest_favorite=true&sort=listings_desc&page=1" \
-H "x-api-key: $CRAWLORA_API_KEY"