# Airbnb Market Intel Scraper | Listings, Occupancy & Revenue (`tactful_anvil/airbnb-market-intel-scraper`) Actor

Scrape any Airbnb market: nightly price, rating, reviews, bedrooms + 12-month calendar turned into occupancy 30/60/90, est. monthly revenue, RevPAR, superhost & host stats, plus a free market-summary row. AirDNA-style comps for STR investors & hosts. HTTP-only, pay per result, MCP-ready.

- **URL**: https://apify.com/tactful\_anvil/airbnb-market-intel-scraper.md
- **Developed by:** [Mr Zack](https://apify.com/tactful_anvil) (community)
- **Categories:** Travel, Real estate, Automation
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.80 / 1,000 listing (search data)s

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Airbnb Market Intel Scraper — Listings, ADR, Occupancy & Revenue Estimate

**Answer "what does a 2-bedroom in this market actually earn?" in one run.** Scrape any Airbnb search (city, neighborhood, region or a pasted Airbnb URL with your filters) and get every listing's nightly price, rating, reviews, bedrooms/beds/baths, badges and coordinates — plus, per listing, the **12-month availability calendar turned into occupancy 30/60/90/365, estimated monthly revenue and RevPAR**, superhost status, guest capacity, sub-ratings and host stats. A free **market-summary row** rolls it up: median / p25 / p75 nightly price, share of superhosts and guest favorites, median occupancy & revenue, and a breakdown by bedroom count.

HTTP-only (server-rendered pages + Airbnb's public calendar endpoint), no login, no proxy, no cookies. **Pay per result: $4 per 1,000 listings, $6 per 1,000 enriched listings** (calendar + details). Duplicates, failed listings and the summary row are never charged.

### Who uses this

- **Short-term-rental investors** comparing markets before buying — ADR, occupancy and revenue estimates per bedroom count, without a $100+/month AirDNA seat.
- **Hosts & property managers** pricing against the competition: who charges what, who is booked out, who is superhost, minimum nights.
- **Real-estate agents & lenders** building STR underwriting comps for a specific address or neighborhood.
- **Analysts & AI agents** that need a clean, structured snapshot of an Airbnb market on a schedule.

### Input

| Field | Default | What it does |
|---|---|---|
| `location` | `Austin, TX` | Anything you would type into Airbnb search. |
| `locations` | `[]` | Several markets in one run (one per line). |
| `searchUrls` | `[]` | Advanced: full `airbnb.com/s/...` URLs with your own filters (map area, amenities, instant book…). |
| `checkIn` / `checkOut` | 4 weeks out, 3 nights | Stay dates drive the nightly price Airbnb shows. |
| `adults` | `2` | Guest count. |
| `children` / `infants` / `pets` | `0` | **New in 0.0.3.** Party details — same effect on price/availability as on airbnb.com; `pets` = pet-friendly listings only. |
| `roomType` | `any` | `entire_home` or `private_room` to filter. |
| `minBedrooms` | `0` | Minimum bedrooms. |
| `minBeds` / `minBathrooms` | `0` | **New in 0.0.3.** Airbnb `min_beds` / `min_bathrooms`. |
| `minRating` / `minReviews` / `guestFavoriteOnly` | `0` / `0` / `false` | **New in 0.0.3.** Post-filters on the search card (rating, review count, Guest Favorite badge) — dropped listings are never charged. Use `minReviews: 20` to keep only proven earners. |
| `priceMin` / `priceMax` | `0` | Nightly price filter in `currency`. |
| `maxListings` | `54` | Charged listings per location (18 per page, Airbnb caps a search at 270). |
| `enrichCalendar` | `true` | Add calendar KPIs + detail fields (2 extra requests per listing). |
| `maxEnrich` | `30` | Enrich only the first N listings; 270 = all. |
| `currency` | `USD` | Any ISO code (EUR, GBP, AUD, IDR…). |
| `marketSummary` | `true` | Append the free roll-up row (also saved as key-value record `MARKET_SUMMARY`). |

### Output — listing row

| Field | Example | Notes |
|---|---|---|
| `listingId`, `url` | `547878270470501768` | Airbnb listing |
| `title`, `name` | `Guest suite in Austin`, `Serene & Sunny SoCo Sanctuary…` | |
| `propertyTypeShort`, `area` | `Guest suite`, `Austin` | parsed from title |
| `rating`, `reviewsCount`, `isNewListing` | `4.99`, `114`, `false` | |
| `isGuestFavorite`, `isTopGuestFavorite`, `badges` | `true`, `true`, `["Guest favorite"]` | |
| `bedrooms`, `beds`, `baths` | `1`, `1`, `1` | studio = 0 bedrooms |
| `nightlyPrice`, `nights`, `totalPrice`, `originalTotalPrice`, `discountPct`, `currency` | `274.33`, `3`, `823`, `null`, `null`, `USD` | price for the searched dates, before taxes |
| `checkIn`, `checkOut`, `freeCancellation` | `2026-10-09`, `2026-10-12`, `true` | |
| `latitude`, `longitude`, `pictureUrl`, `rank`, `searchLocation`, `scrapedAt` | | |
| **Enriched (`enriched: true`)** | | |
| `roomType`, `propertyType`, `personCapacity` | `Entire home/apt`, `Entire guest suite`, `2` | |
| `isSuperhost`, `hostName`, `hostRating`, `hostReviewCount`, `hostYears`, `hostIsVerified` | `true`, `Mary`, `4.99`, `114`, `4.5`, `true` | |
| `ratingCleanliness`, `ratingAccuracy`, `ratingCheckin`, `ratingCommunication`, `ratingLocation`, `ratingValue` | `5`, `4.99`, `4.98`, `5`, `4.97`, `4.95` | |
| `occupancy30`, `occupancy60`, `occupancy90`, `occupancy365` | `0.367`, `0.417`, `0.311`, `0.269` | share of calendar nights unavailable |
| `bookedNights30/60/90/365`, `availableNights30/90/365` | `11`, `25`, `28`, `97` … | |
| `estRevenue30`, `estRevenue90`, `estRevenue365` | `3018`, `7681`, `26610` | nightlyPrice × unavailable nights |
| `revPar30`, `revPar90` | `100.59`, `85.35` | nightlyPrice × occupancy |
| `minNights`, `maxNights`, `nextAvailableDate`, `calendarFrom`, `calendarTo` | `2`, `1125`, `2026-09-13`, … | |

**How to read occupancy:** Airbnb only exposes availability, so an unavailable night is either booked *or* blocked by the host. That is the same public-data proxy every STR analytics tool starts from — treat it as an upper bound and compare listings against each other rather than as an audited P\&L.

### Output — market-summary row (free)

`type: "market-summary"`, `listings`, `listingsEnriched`, `medianNightlyPrice`, `avgNightlyPrice`, `p25NightlyPrice`, `p75NightlyPrice`, `minNightlyPrice`, `maxNightlyPrice`, `avgRating`, `medianReviews`, `totalReviews`, `shareGuestFavorite`, `shareNewListings`, `shareSuperhost`, `medianOccupancy30`, `medianOccupancy90`, `medianEstRevenue30`, `medianRevPar30`, `medianMinNights`, `medianPersonCapacity`, `bedroomBreakdown[]` (`bedrooms`, `listings`, `medianNightlyPrice`, `medianOccupancy30`, `medianEstRevenue30`, `avgRating`).

### Example output (one real enriched row, 6 Sep 2026, "Austin, TX")

```json
{
  "listingId": "547878270470501768",
  "url": "https://www.airbnb.com/rooms/547878270470501768",
  "title": "Guest suite in Austin",
  "name": "Serene & Sunny SoCo Sanctuary with Farmhouse Feel",
  "rating": 4.99, "reviewsCount": 114, "isGuestFavorite": true,
  "bedrooms": 1, "beds": 1, "baths": 1,
  "nightlyPrice": 274.33, "nights": 3, "totalPrice": 823, "currency": "USD",
  "roomType": "Entire home/apt", "personCapacity": 2, "isSuperhost": true,
  "hostName": "Mary", "hostRating": 4.99, "hostYears": 4.5,
  "occupancy30": 0.367, "occupancy90": 0.311, "occupancy365": 0.269,
  "estRevenue30": 3018, "estRevenue90": 7681, "revPar30": 100.59,
  "minNights": 2, "nextAvailableDate": "2026-09-13", "enriched": true
}
```

Default input (Austin, 54 listings, 30 enriched) costs about **$0.28** and runs in under a minute.

### Pricing

| Event | Price |
|---|---|
| Listing (search data) | **$0.004** ($4 / 1,000) |
| Listing enriched (calendar + details) | **$0.006** ($6 / 1,000) — replaces the listing fee for that row |
| Actor start | $0.001 |

Compute is included. Duplicates across pages/locations, listings that fail to parse and the market-summary row are never charged. A failed enrichment falls back to the plain listing fee.

### Schedule it

Markets move weekly. In Apify Console open the Actor → **Schedules** → e.g. every Monday 06:00 with your locations, then connect the dataset to Google Sheets, Airtable, Slack or a webhook via **Integrations**. Compare `MARKET_SUMMARY` records week over week to spot price drops and occupancy shifts before your competitors do.

### Use it from code or AI agents (MCP)

```bash
curl -X POST "https://api.apify.com/v2/acts/tactful_anvil~airbnb-market-intel-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"location":"Canggu, Bali","roomType":"entire_home","minBedrooms":2,"maxListings":90,"maxEnrich":90,"currency":"USD"}'
```

Works out of the box with the **Apify MCP server** (`https://mcp.apify.com`) — add this Actor to your Claude, Cursor, ChatGPT or custom agent and ask "compare Airbnb occupancy and ADR for 2-bedroom homes in Austin vs Nashville". Python: `ApifyClient(token).actor("tactful_anvil/airbnb-market-intel-scraper").call(run_input={...})`.

### Why this Actor

- **Market intelligence, not just listings** — occupancy, revenue estimate and RevPAR per listing plus a market roll-up; competitors stop at price and rating.
- **HTTP-only & fast** — ~1 s per page, ~0.7 s per enriched listing, no browser, no proxies to pay for.
- **Fail-loud** — if Airbnb changes its layout the run fails with a clear message instead of "succeeding" with 0 rows.
- **Fair pricing** — flat per-result fees, nothing charged for duplicates, failures or the summary.

### Related Actors

- [Google Ads Transparency Scraper](https://apify.com/tactful_anvil/google-ads-transparency-scraper) — see which property managers and hosts advertise.
- [Brand Ads Cross-Network Spy](https://apify.com/tactful_anvil/brand-ads-cross-network-spy) — ad creatives across Google and Meta for any brand.
- [Contact Details Scraper](https://apify.com/tactful_anvil/contact-details-scraper) — emails, phones and socials from any website.
- [Kalshi Weather Markets Scraper](https://apify.com/tactful_anvil/kalshi-weather-markets-scraper) — prediction-market weather odds for demand forecasting.

### Found this useful? Bookmark & review

A bookmark or a short review on this page helps other hosts and investors find it — and tells me which fields to add next (reviews text, amenities, price history?). Issues tab is open.

### Changelog

- **0.0.4 (13 Sep 2026)** — `bedrooms` fill: Airbnb search cards sometimes omit the bedroom line (≈10–20 % of cards, mostly studios). When the listing name says “studio” the row now gets `bedrooms: 0` instead of `null`; other cards without the line stay `null` until the room page fills it (`fetchDetails`). No other field changed.
- **0.0.3 (8 Sep 2026)** — billing hardening: a charging hiccup can no longer abort a run that already returned listings (rows are delivered either way).
- **0.0.3 (8 Sep 2026)** — party details (`children`, `infants`, `pets`), `minBeds` / `minBathrooms`, quality post-filters `minRating` / `minReviews` / `guestFavoriteOnly` (never charged when dropped). No existing field changed.
- **0.1 (6 Sep 2026)** — launch: search pagination (15 pages), room details, 12-month calendar KPIs, market-summary row, multi-location, pasted search URLs.

# Actor input Schema

## `location` (type: `string`):

City, neighborhood, region or address exactly as you would type it into Airbnb search (e.g. "Austin, TX", "Canggu, Bali", "Lisbon, Portugal").

## `locations` (type: `array`):

Scan several markets in one run — one location per line. Overrides the single Location field when filled.

## `searchUrls` (type: `array`):

Paste full airbnb.com/s/... search URLs with any filters applied in the Airbnb UI (map area, amenities, instant book…). Pagination and currency are handled for you.

## `checkIn` (type: `string`):

Stay dates drive the nightly price Airbnb shows. Leave empty for a default stay 4 weeks from today (3 nights).

## `checkOut` (type: `string`):

Must be after check-in.

## `adults` (type: `integer`):

Guest count used for the search (1–16).

## `children` (type: `integer`):

Children in the party (Airbnb `children`). Changes availability and price like on the site.

## `infants` (type: `integer`):

Infants (under 2) — not counted toward capacity.

## `pets` (type: `integer`):

Pets — only pet-friendly listings are returned.

## `roomType` (type: `string`):

Filter to entire homes or private rooms, or take everything.

## `minBedrooms` (type: `integer`):

0 = no filter.

## `minBeds` (type: `integer`):

0 = no filter.

## `minBathrooms` (type: `integer`):

0 = no filter.

## `priceMin` (type: `integer`):

In the selected currency. 0 = no filter.

## `priceMax` (type: `integer`):

In the selected currency. 0 = no filter.

## `minRating` (type: `number`):

Keep only listings whose search-card rating is at least this (e.g. 4.8). Listings without a rating (new) are dropped. Dropped listings are never charged.

## `minReviews` (type: `integer`):

Keep only listings with at least this many reviews (proven demand). Never charged when dropped.

## `guestFavoriteOnly` (type: `boolean`):

Keep only listings carrying Airbnb's Guest Favorite / Top Guest Favorite badge on the search card. Never charged when dropped.

## `maxListings` (type: `integer`):

18 listings per page, Airbnb caps a search at 15 pages (270). Default 54 = 3 pages.

## `enrichCalendar` (type: `boolean`):

Adds occupancy 30/60/90/365, est. revenue, RevPAR, min nights, superhost, capacity, sub-ratings, host stats per listing (2 extra requests each, $6/1k instead of $4/1k).

## `maxEnrich` (type: `integer`):

Enrich only the first N listings (search order). Default 30. Set to 270 to enrich everything.

## `currency` (type: `string`):

ISO code, e.g. USD, EUR, GBP, AUD, IDR.

## `marketSummary` (type: `boolean`):

One extra (never charged) row: median/p25/p75 nightly price, avg rating, share superhost / guest favorite, median occupancy & est. revenue, breakdown by bedrooms. Also saved as key-value record MARKET\_SUMMARY.

## Actor input object example

```json
{
  "location": "Austin, TX",
  "locations": [],
  "searchUrls": [],
  "adults": 2,
  "children": 0,
  "infants": 0,
  "pets": 0,
  "roomType": "any",
  "minBedrooms": 0,
  "minBeds": 0,
  "minBathrooms": 0,
  "priceMin": 0,
  "priceMax": 0,
  "minRating": 0,
  "minReviews": 0,
  "guestFavoriteOnly": false,
  "maxListings": 54,
  "enrichCalendar": true,
  "maxEnrich": 30,
  "currency": "USD",
  "marketSummary": true
}
```

# Actor output Schema

## `listings` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "location": "Austin, TX"
};

// Run the Actor and wait for it to finish
const run = await client.actor("tactful_anvil/airbnb-market-intel-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "location": "Austin, TX" }

# Run the Actor and wait for it to finish
run = client.actor("tactful_anvil/airbnb-market-intel-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "location": "Austin, TX"
}' |
apify call tactful_anvil/airbnb-market-intel-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tactful_anvil/airbnb-market-intel-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/VkazniuEdTSdJJ8bJ/builds/q1XI2oZ8pzNkRMSIr/openapi.json
