# Airbnb Scraper - Market Signals, Pricing Position & Monitor (`ryanclinton/airbnb-scraper`) Actor

Stateful Airbnb market monitoring engine. Each run returns a ranked attention queue - what changed, what matters, what to review - with comp-set pricing position, revenue estimates, and supply-surge detection. Drop-in compatible with tri\_angle/airbnb-scraper.

- **URL**: https://apify.com/ryanclinton/airbnb-scraper.md
- **Developed by:** [Ryan Clinton](https://apify.com/ryanclinton) (community)
- **Categories:** Travel, Real estate
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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 Scraper - Market Signals, Pricing Position & Monitor Mode

![Airbnb Scraper, a stateful Airbnb market monitoring engine that tells you what to reprice first, watches for price, supply and demand shifts, and remembers what changed across runs](https://apifyforge.com/readme-assets/ryanclinton-airbnb-scraper/hero.png)

### In one sentence

Airbnb Scraper is a stateful Airbnb market monitoring engine on Apify that scrapes a city, a set of listing URLs, or a market you track over time, and returns a ranked attention queue answering three questions: what changed, what matters, and what should I review.

**Category:** Airbnb scraper. STR (short-term rental) market monitoring. Vacation rental pricing and supply intelligence.
**Primary use case:** Rank a market's listings by where each sits in its comp set and what just moved, then schedule a daily run so the market memory compounds. Can also be used for one-shot comp-set pricing checks, multi-market comparison, and host-portfolio tracking.

**Also known as:** airbnb scraper, airbnb market monitor, str pricing tool, vacation rental data scraper, airbnb comp set analysis, airbnb revenue estimator

### What this actor does

- **What it is:** A stateful Airbnb market monitoring engine that turns a scrape into a ranked list of what to review first.
- **What it checks:** Where each listing sits in its comp set, what moved since the last run (price, supply, availability), and how the market is trending.
- **What it returns:** An attention queue per listing (`attentionIndex`, `watchStatus`, `whyNow`, `decisionRoute`, `recommendedAction`), a market profile, fenced revenue and occupancy estimates, and market memory that compounds every run.
- **What it does NOT do:** It does not provide licensed booking data like AirDNA, it does not measure real bookings (revenue and occupancy are estimates), and it performs no in-Airbnb actions (no booking, no messaging hosts, no setting platform prices).
- **Who it's for:** STR hosts, property managers, short-term rental investors, acquisition scouts, and market analysts.

### Overview

Airbnb Scraper is an Apify actor that answers a question raw scrapers leave on the table: of all these Airbnb listings, which ones should I look at first? Paste a city and the actor returns the top listings ranked by a single composite score, each row carrying a plain-English reason and a recommended action, in about 60 seconds. It functions as an Airbnb market intelligence API, not a row dump.

The moat is not the scrape. Airbnb Scraper accrues an interpretation history for every market you run, so the same input gets smarter over time. The first run finds your comp outliers. Run 3 unlocks price and supply trajectory. Run 10 unlocks persistent-signal classification, the structural read no one-shot scrape can give you. Every run compounds the market memory, and that memory clock cannot be backfilled.

To monitor an Airbnb market, paste a city, a list of `/rooms/<id>` URLs, or a market to track. You get back a ranked attention queue with comp-set pricing position, revenue estimates, supply-surge detection, and a recommended action per listing. Same input shape as `tri_angle/airbnb-scraper`, drop-in migration, and the decision layer that scrapers do not ship.

**In short:** Same input as a standard Airbnb scraper. Same output, plus what to do about it.

**The feel:** an Airbnb market command center. One screen tells you what changed, what matters, and what needs your attention now, so you stop scanning rows and start acting on the few that move.

**What it does** - Scrapes an Airbnb market and returns a ranked attention queue with a reason and action per listing.
**Best for** - Daily market monitoring, comp-set pricing checks, multi-market comparison, host-portfolio tracking.
**Speed** - A default market run returns its attention queue in about 60 seconds.
**Pricing** - $0.0015 per record ($1.50 per 1,000) plus $0.30 per market query. Platform compute is separate.
**Output** - JSON, CSV, or Excel. Attention queue, market profile, pricing position, fenced estimates, market memory.

**Key limitation:** Revenue and occupancy are estimates inferred from the public availability calendar, never measured bookings.
**What it is not:** Not a licensed STR database like AirDNA, not a booking tool, and not a replacement for legal or investment advice.
**Does not include:** Real booking counts, guest contact details, private host data, or any in-Airbnb action.
**Results may be incomplete when:** A market exceeds Airbnb's 240-result cap, anti-bot challenges trip the circuit breaker, or a listing is private or removed.

### Why this engine exists

Most Airbnb scrapers return rows. Most short-term-rental dashboards return charts. The stateful Airbnb market monitoring engine returns prioritized decisions with accumulated market memory.

It exists to answer three questions on every run:

- **What changed** in this market since the last run.
- **What matters** enough to need a human right now.
- **What should I review first**, with the reason and the action attached.

The market memory is the moat: it compounds every run and cannot be backfilled, so the longer the engine watches a market, the more it knows that a fresh scrape never can.

### What you get from one call

**Input:** `{ "market": "Austin, TX", "mode": "market", "rankBy": "attention", "enableMarketMemory": true }`
**Returns:**
- A ranked attention queue: each listing with `attentionIndex` (0-100), `watchStatus`, `whyNow`, `decisionRoute`, and `recommendedAction`
- A market record: `signalProfile` (archetype), `marketHealth` (direction), `marketConfidence` (grade), and `marketMemory`
- Per-listing `pricePosition` (comp band, percentile, label) and a fenced `revenueEstimate` (range band, marked as an estimate)
- A run summary with `runOutcome`, `dailyBriefing`, `topActions`, and `attentionBudget`

**Typical time to first result:** about 60 seconds for a default market run.
**Typical time to integrate:** minutes if you already read a standard Airbnb scraper's output, since the substrate fields match.

![The intelligence stack: from a pasted city or listing URLs, through public Airbnb substrate, comp-set pricing position, signal detection, trust grading, and market memory, to a ranked attention queue](https://apifyforge.com/readme-assets/ryanclinton-airbnb-scraper/intelligence-layers.png)

### What makes this different

- **Pricing position, not a row dump** - every listing arrives ranked by where it sits in its comp set, with a band and a percentile.
- **Market memory that compounds** - Airbnb Scraper accrues per-market interpretation history across runs, so trajectory and persistent-signal classification unlock as you keep running it.
- **An honest decision layer** - every listing carries a reason (`whyNow`) and a recommended action, and every inferred metric travels with its believability grade.

If you were building this yourself, you would need a comp-set engine, a cross-run state store keyed per market, a signal-detection layer, an attention-scoring model, and a trust layer that fences estimates from observations. The stateful Airbnb market monitoring engine produces decisions for pricing reviews, supply monitoring, and market selection.

### Jobs the Airbnb market monitoring engine solves

Each job below maps to a mode and the fields you read for the answer.

#### Reprice Airbnb listings faster
Run market mode with `rankBy: "pricingOpportunity"`. Each listing returns `pricePosition` with a band, a percentile, and an underpriced or overpriced label versus genuinely comparable units.

#### Detect Airbnb market saturation before competitors
Run monitor mode daily. The engine detects `new_listing_surge` and `market_saturation` against prior runs and reports `marketShiftClassification` once memory matures.

#### Compare short-term-rental markets side by side
Run compare mode across 2 or more cities. One ranked record carries archetype (`signalProfile`), direction (`marketHealth`), and confidence (`marketConfidence.grade`) per market.

#### Monitor Airbnb supply growth over time
Run monitor mode on a city with `enableMarketMemory: true`. Supply trajectory unlocks at run 3; you get back only what changed since the last run.

#### Build an Airbnb comp set automatically
Run market or listings mode. The engine groups comparable listings by market, room type, and capacity, and shows the comp set with `compSetAudit`.

#### Estimate Airbnb revenue from public data
Enable `estimateRevenue` (on by default). Each listing returns a fenced `revenueEstimate` with a range band, marked `metricClass: estimated` and `measuredByAirbnb: false`. It is a directional proxy, never a booking ledger.

#### Track competitor hosts
Run host mode. Each host returns `hostMomentum` (scaling or contracting) and superhost positioning.

#### Route only important market changes to humans
Branch your automation on `decisionRoute` and `watchStatus`. Only `attention-required`, `urgent`, and `critical` rows need a human; the rest are suppressed and counted in `attentionBudget`.

### Which mode should I use?

| Need | Best mode |
|------|-----------|
| Reprice listings against the comp set | `market` |
| Track a market for deterioration over time | `monitor` |
| Compare candidate cities | `compare` |
| Audit specific listing URLs | `listings` |
| Track competing host portfolios | `host` |

### Quick answers

**What is it?** Airbnb Scraper is a stateful Airbnb market monitoring engine that ranks a market's listings by what to review first and tracks how the market moves across runs.
**How do I monitor an Airbnb market over time?** Run Airbnb Scraper on a city with `enableMarketMemory: true` (the default), then schedule a daily run. Each run returns what changed and compounds the market memory.
**What makes it different?** It ships a decision layer on top of the scrape: comp-set pricing position, signal detection, an attention queue, and accumulated market memory, instead of raw rows.
**What data sources does it use?** Public Airbnb search pages, room pages, and host pages, fetched over residential proxies. It uses no login and accesses no private data.
**What does it return?** An attention queue per listing, a market profile, comp-set pricing position, fenced revenue and occupancy estimates, and market memory, in JSON, CSV, or Excel.
**How much does it cost?** $0.0015 per emitted record ($1.50 per 1,000) plus $0.30 per market query. Apify's free tier ($5 in monthly credits) covers roughly 3,300 records.
**Is it a drop-in replacement for an existing Airbnb scraper?** Yes. It accepts the same `locationQueries` input and ships the same output substrate; the signal layer is additive.

### At a glance

**Quick facts:**
- **Input:** A city (`market`), a list of `/rooms/<id>` URLs (`listings`), host URLs (`hosts`), or multiple cities (`markets`).
- **Output:** Attention queue, market profile, pricing position, fenced revenue estimate, market memory, run summary.
- **Pricing:** $0.0015 per record ($1.50/1k) plus $0.30 per market query.
- **Batch size:** Up to 240 listings per market (Airbnb's own result cap); `coverage.marketRepresentativeness` reports the sample fraction.
- **Modes:** market, monitor, listings, host, compare.
- **Output profiles:** signals (default), compat, agent, minimal, debug.
- **Personas:** generic, host, investor, analyst.
- **Data source:** Public Airbnb pages over residential proxies. No login.

**Input to output:**
- Input: a market, listing URLs, or host URLs.
- Process: scrape substrate, build comp sets, detect signals against prior runs, score attention, fence estimates, persist market memory.
- Output: a ranked attention queue plus a market profile and a run summary.

**Best fit:** Daily Airbnb market monitoring, comp-set pricing reviews, multi-market selection, host-portfolio momentum.
**Not ideal for:** Licensed booking-volume data, guest PII, in-Airbnb actions, or markets where you need a full census above 240 listings.
**Does not include:** Real booking counts, measured occupancy, private data, or investment verdicts.

**Problems this solves:**
- How to rank Airbnb listings by pricing opportunity instead of Airbnb's native sort.
- How to detect when a market's supply surges or availability tightens.
- How to estimate Airbnb revenue and occupancy from public data, honestly fenced.
- How to monitor an Airbnb market over time and get back only what changed.

**Data trust:** Substrate fields (`price.amount`, `rating.*`, `isSuperHost`) are observed. Comp metrics are derived. Revenue and occupancy are estimated from the public availability calendar and always carry `metricClass: estimated`, `measuredByAirbnb: false`, and a range band. A blocked night may be a booking or a host block; the two are indistinguishable from public data.

### Lead with the three questions

Sophisticated machinery, simple surface. Airbnb Scraper exists to answer three buyer questions on every run:

- **What changed?** Signal events fire when a listing's price moves, a market's supply surges, or availability tightens versus the prior run.
- **What matters?** A composite `attentionIndex` (0-100) and a `watchStatus` rank the noise down to the handful of rows that need a human.
- **What should I review?** Each row carries a `decisionRoute` (a flat enum your automation can branch on) and a plain-English `recommendedAction`.

The percentiles, comp-set math, and trajectory models live under the hood. The surface is five rows that answer the question you came with.

### Why suppression matters

Most monitoring tools create more alerts. The stateful Airbnb market monitoring engine suppresses weak signals and surfaces only what deserves human attention. **Suppression is the feature, not more alerts.**

Every run reports an `attentionBudget`: how many signals were evaluated, how many were suppressed as noise, and the resulting attention-reduction percentage. A price wobble inside a market's normal volatility is filtered out with a reason; a structural shift is escalated. The point of the engine is less cognitive load, not another dashboard to scan.

### Drop-in migration from tri_angle/airbnb-scraper

Switching from `tri_angle/airbnb-scraper` is frictionless because three things hold:

1. **Same input shape.** Paste your existing `locationQueries` JSON with the same filters and it runs. Airbnb Scraper maps `locationQueries` to market mode automatically.
2. **Same output substrate.** Every field a standard Airbnb scraper ships (`id`, `url`, `coordinates`, `roomType`, `isSuperHost`, `personCapacity`, the 7-axis `rating` block, `host`, `price.breakDown`, `amenities`) ships here with identical name and type. Code reading `item.price.amount` works unchanged.
3. **The signal layer is additive.** The default `outputProfile: "signals"` adds pricing position, revenue estimates, signals, and routing on top. If you want the exact original field set with validated URLs and resolvable IDs, set `outputProfile: "compat"`.

Same input, same output, plus what to do about it.

### Choose your output

The `outputProfile` input controls how much of the envelope each record carries:

| Profile | What it returns | Best for |
|---------|-----------------|----------|
| `signals` (default) | Full envelope: substrate + pricing position + revenue estimate + signals + attention routing + market profile + delta | Most users who want the decision layer |
| `compat` | Exact original tri_angle field set, validated URLs and IDs, no signal fields | Verifying migration parity |
| `agent` | `agentContract` + `attentionIndex` + `whyNow` + pricing summary, diagnostics stripped | MCP, AI agents, and pricing tools that want decisions |
| `minimal` | IDs, URLs, and nightly price only | Lightweight pulls |
| `debug` | Full diagnostics, parsing detail, `partialOutputPolicy`, skip reasons | Debugging |

### The market memory moat

The reason buyers stay is the accumulated interpretation history. With `enableMarketMemory: true` (the default for market and monitor modes), Airbnb Scraper creates and updates a named market-memory store on every run, keyed per market. The state compounds:

- **Run 1** finds your comp outliers and the current market profile.
- **Run 3** unlocks price and supply trajectory (`signalTrajectory`, `marketHealth` direction).
- **Run 10** unlocks persistent-signal classification (`persistenceClass`), the structural read no one-shot scrape can give you.

Every run compounds the market memory, and the clock cannot be backfilled. The `marketMemory` block reports its own depth honestly (`memoryDepth`, `runsObserved`, `availableSignals`, `notYetAvailable`), so you always know what the current history can and cannot support. Schedule a daily run to build it.

### The five modes

One actor, five entry points. Pick a mode and one set of targets.

#### Mode: market (default)
Rank a city's listings by pricing and revenue opportunity. The 10-second first run:
```json
{ "market": "Austin, TX", "mode": "market", "rankBy": "attention", "enableMarketMemory": true }
````

#### Mode: monitor

Track a market over time and get back only what changed. The retention mode.

```json
{ "mode": "monitor", "market": "Austin, TX", "trackListings": ["14926879"], "watchlistName": "austin-portfolio", "deltaWindowDays": 7, "lastReviewedAt": "2026-05-18T09:00:00Z" }
```

#### Mode: listings

Explain where specific room URLs sit versus their comp set.

```json
{ "mode": "listings", "listings": ["https://www.airbnb.com/rooms/14926879"], "estimateRevenue": true }
```

#### Mode: host

Surface host-portfolio momentum and superhost positioning.

```json
{ "mode": "host", "hosts": ["https://www.airbnb.com/users/show/82436841"], "maxListings": 50 }
```

#### Mode: compare

Rank 2 or more markets side by side on revenue, occupancy, supply, and ADR.

```json
{ "mode": "compare", "markets": ["Austin, TX", "Nashville, TN", "Savannah, GA"], "rankBy": "revenue" }
```

### Revenue and occupancy estimates (clearly fenced)

Airbnb does not publish booking data. When `estimateRevenue` is on (the default), each listing carries a `revenueEstimate` block derived from the public availability calendar. This is honest about its own limits:

- It always carries `metricClass: "estimated"` and `measuredByAirbnb: false`. It is never presented as measured fact.
- It returns a range band (`estimatedRevenueRangeUsd`), never a single false-precision number.
- A blocked night may be a real booking or a host block. The two are indistinguishable from public data, so occupancy is a proxy for demand, not a count.
- Each estimate carries a `confidenceGrade`, `confidenceReasons`, and `limitations`.

Revenue estimation is a supporting feature, not the headline. The headline is the attention queue. Treat the estimate as a directional signal you sanity-check, not a booking ledger.

### How the Airbnb market monitoring engine handles uncertainty

Most STR tools blur inference into fact. This one makes uncertainty visible on every field, which is what lets you trust the numbers it does assert.

**Revenue and occupancy are estimates inferred from public availability data, not measured bookings.** A blocked night may be a real booking or a host block, and the two are indistinguishable from public data.

Every analytical field declares its source class with `metricClass`:

- **observed** - read directly from the Airbnb page (`price.amount`, `rating.*`, `isSuperHost`).
- **derived** - computed deterministically from observed values (comp-set median, `pricePosition`).
- **estimated** - inferred via a proxy, never measured (`revenueEstimate`, `occupancyRateEstimate`). Always paired with `measuredByAirbnb: false` and a range band.
- **historical** - from accumulated cross-run memory (`marketMemory`, `signalTrajectory`).
- **insufficient** - not enough data yet; the field says so rather than guessing.

Every estimate also carries a `confidenceGrade` (a data-sufficiency grade from comp-set size, calendar depth, and coverage, not a backtested accuracy claim), `confidenceReasons`, and `limitations`. The run grades its own reliability in `runReliability`, and `coverage.marketRepresentativeness` reports the sampled fraction of a market. Nothing is presented as more certain than the public data supports.

### Reranking and market comparison

Airbnb's native sort is not what buyers want. Hosts want comp outliers; investors want revenue leaders; analysts want supply movers. The `rankBy` input reorders the attention queue by `attention` (composite), `pricingOpportunity`, `revenue`, `occupancy`, `rating`, or `relevance`. Each listing carries `airbnbSortRank`, `rerankedRank`, a `rerankReason`, and a full `rerankAxes` block so you can see where it sits on every axis at once.

In `compare` mode, the same engine runs across multiple markets and emits one ranked comparison record carrying both the static archetype (`signalProfile`) and the direction it is moving (`marketHealth`). An investor reads "this market is emerging and improving, at B confidence" in a single row.

![Four features: ranked attention queue not a row dump, market memory that compounds run 1 to run 10, estimates tagged observed versus estimated and never faked, and noise suppression so the queue is only what deserves a look](https://apifyforge.com/readme-assets/ryanclinton-airbnb-scraper/feature-callouts.png)

### Features

The stateful Airbnb market monitoring engine layers a five-part intelligence envelope on a faithful Airbnb substrate. The substrate matches a standard Airbnb scraper field-for-field; the layers below add the decisions. Each layer has its own section so you can jump to the one you need.

#### Scrapes a faithful Airbnb substrate

- **Faithful substrate:** `id`, validated `url`, `coordinates`, `roomType`, `isSuperHost`, `personCapacity`, `bedrooms`, the 7-axis `rating` block, `host`, `price` with `breakDown`, `amenities`, `availability`.
- **Validated links:** no broken or mismatched rows. A listing whose URL does not resolve to its `id` is dropped, not emitted.
- **locationQueries alias:** accepts the original `tri_angle/airbnb-scraper` input field and maps it to market mode.

#### Ranks listings by comp-set pricing position

- **Comp-set pricing position** per listing: `pricingBand` (low, median, high), `marketPercentile`, `positionLabel` (underpriced, market-aligned, premium, overpriced), and `deltaVsMedianPct`.
- **compSetAudit** shows exactly which listings were included or excluded from the comp set, so the percentile is auditable, not a black box.

#### Detects market shifts as typed signals

- **11 signal event types:** price drop, price surge, market price shift, new listing surge, market saturation, occupancy tightening or loosening, revenue outlier, superhost emergence, rating decline or surge. Each detects a shift across runs and carries evidence and a decay status.
- **9 market archetypes** (`signalProfile`, market records only): emerging-market, premium-stable, oversupplied, saturated, cooling, and more.

#### Routes attention to the few rows that matter

- **Composite attention index:** a single 0-100 score per record with a `breakdown` and the top 3 `drivers`. This is the sort column for the queue.
- **Decision route:** a flat enum (`review-pricing`, `investigate-revenue`, `monitor-supply`, `benchmark-market`, `review-data-quality`, `no-action`) your automation branches on, plus a human `recommendedAction`.

#### Suppresses noise and reports how much

- **Noise suppression:** weak or noisy signals move to `suppressedSignals` with a reason instead of cluttering the queue.
- **attentionBudget:** the run summary reports how many signals were evaluated, how many were suppressed, and the attention-reduction percentage. Suppression is the feature, not more alerts.

#### Accumulates market memory across runs

- **Market memory:** per-market interpretation history that compounds every run, keyed per market.
- **Persistence classification:** signals are classed transient, recurring, persistent, or dormant once memory matures.

#### Grades its own trust and reliability

- **metricClass discipline:** every analytical block declares whether it is observed, derived, estimated, historical, or insufficient.
- **Coverage and data quality:** `coverage.marketRepresentativeness`, `coverageGrade`, and a per-record `dataQuality` contract.
- **Run reliability:** the run grades itself (`runReliability`) and emits partial output before any hard timeout (`partialOutputPolicy`).

### Use cases for Airbnb market monitoring

#### Best for daily market monitoring

Use when you manage listings or capital in one or more cities and need to know each morning what moved. Schedule a daily run in monitor mode; the `dailyBriefing` and `topActions` give you a five-second read, and STR hosts use the queue to decide which listings to reprice first. Key outputs: `runOutcome`, `dailyBriefing`, `topActions`, `sinceLastReview`.

#### Best for comp-set pricing reviews

Use when you want to know whether a listing is underpriced or overpriced versus genuinely comparable units. Run market or listings mode; each listing carries `pricePosition` with a band, a percentile, and a label. Key outputs: `pricePosition.positionLabel`, `pricingBand`, `deltaVsMedianPct`, `compSetAudit`.

#### Best for short-term rental market selection

Use when an investor or acquisition scout is choosing between cities. Run compare mode across 2 or more markets and read archetype plus direction plus confidence in one ranked record. Key outputs: `signalProfile`, `marketHealth.direction`, `marketConfidence.grade`, `revenueEstimate`.

#### Best for supply and saturation tracking

Use when you need early warning that a market is filling up. Airbnb Scraper detects `new_listing_surge` and `market_saturation` against prior runs. Key outputs: `signalEvents`, `marketHealth`, `marketShiftClassification`.

#### Best for host-portfolio tracking

Use when you watch competing operators. Host mode surfaces whether a portfolio is scaling or contracting and its superhost positioning. Key outputs: `hostMomentum.classification`, `listingCountTrend`, `superhostStatus`.

### When to use Airbnb Scraper

**Best for:**

- Monitoring 1 to a handful of markets daily or weekly and acting on what changed.
- Repricing decisions where comp-set position matters more than a raw price list.
- Choosing between candidate STR markets on revenue, occupancy, supply, and ADR.
- Feeding an AI agent or pricing tool decisions via `outputProfile: "agent"`.

**Not ideal for:**

- Licensed booking-volume data with measured occupancy. Use a paid STR database for that.
- A full census of a market above 240 listings; Airbnb caps the sample and the actor reports the fraction honestly.
- Guest contact data or any private field; this actor reads public content only.

### How to monitor an Airbnb market

1. **Enter your target** - type a city in the `market` field (for example, `Austin, TX`), or paste `/rooms/<id>` URLs for specific listings.
2. **Configure options** - leave `mode` as `market` and `enableMarketMemory` as `true` for the recommended first run; optionally set `rankBy` to `pricingOpportunity` or `revenue`.
3. **Run the actor** - click Start. A default market run returns its attention queue in about 60 seconds.
4. **Download results** - open the Dataset tab and export JSON, CSV, or Excel. The default view is the attention queue, sorted by `attentionIndex`.

### First run tips

- **Start with the demo market** - leave the fields empty or paste `{ "market": "Austin, TX", "mode": "market", "rankBy": "attention", "enableMarketMemory": true }` to see a ranked queue before you scale.
- **Keep market memory on** - `enableMarketMemory` defaults to true; leaving it on means the moat starts compounding from run 1 without touching watchlists. Turning it off forfeits trajectory and persistence reads.
- **Don't expect trajectory on run 1** - `signalTrajectory` and `persistenceClass` need history. Run 1 gives you comp outliers; the deeper reads unlock at run 3 and run 10. The `marketMemory.notYetAvailable` list tells you what is still locked.
- **Treat revenue as an estimate** - the `revenueEstimate` block is a fenced proxy with a range band, not a booking figure. Read its `limitations`.
- **Cap spend with maxResults** - a market emits up to 240 records; lower `maxResults` to control the per-run record charge while testing.

### Typical performance

Observed in internal testing (May 2026, small sample). Values vary by market size, filters, and Airbnb anti-bot conditions.

| Metric | Typical value |
|--------|---------------|
| Records per market run | 1 market record plus up to 240 listing records |
| Run time (default market) | about 60 seconds to first attention queue |
| Run time (240-listing market) | a few minutes |
| Market sample fraction when capped | reported in `coverage.marketRepresentativeness` |
| Cost per default market run (100 records) | about $0.45 ($0.15 records + $0.30 query) |

### Input parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `mode` | string | No | `market` | Entry point: `market`, `monitor`, `listings`, `host`, or `compare`. |
| `market` | string | Conditional | `Austin, TX` (prefill) | City or destination for market and monitor modes. |
| `markets` | array | Conditional | `[]` | 2+ cities for compare mode. |
| `listings` | array | Conditional | `[]` | Airbnb `/rooms/<id>` URLs for listings mode. |
| `hosts` | array | Conditional | `[]` | Airbnb `/users/show/<id>` URLs for host mode. |
| `rankBy` | string | No | `attention` | Sort axis: `attention`, `pricingOpportunity`, `revenue`, `occupancy`, `rating`, `relevance`. |
| `maxResults` | integer | No | `100` | Max listings per market (Airbnb caps a market at 240). |
| `roomType` | string | No | `any` | `any`, `entire_home`, `private_room`, `shared_room`, `hotel_room`. |
| `minBedrooms` | integer | No | `0` | Minimum bedrooms. |
| `minPrice` | integer | No | `0` | Lower nightly price bound. |
| `maxPrice` | integer | No | `0` | Upper nightly price bound. |
| `adults` | integer | No | `2` | Guests used to size the search (1-16). |
| `estimateRevenue` | boolean | No | `true` | Add a fenced revenue and occupancy estimate per listing. |
| `enableMarketMemory` | boolean | No | `true` | Accrue per-market interpretation history across runs. |
| `watchlistName` | string | No | `""` | Stable name for a monitor-mode watchlist; renaming resets the memory clock. |
| `trackListings` | array | No | `[]` | Listing IDs to track over time in monitor mode. |
| `deltaWindowDays` | integer | No | `7` | Comparison window for delta intelligence (1-90). |
| `lastReviewedAt` | string | No | `""` | ISO timestamp your dashboard last surfaced this market; drives `sinceLastReview`. |
| `persona` | string | No | `generic` | Buyer lens: `generic`, `host`, `investor`, `analyst`. |
| `outputProfile` | string | No | `signals` | `signals`, `compat`, `agent`, `minimal`, `debug`. |
| `analysisDepth` | string | No | `standard` | `fast`, `standard`, `deep`. |
| `explainability` | string | No | `standard` | `standard` or `full` diagnostics. |
| `calendarDepthDays` | integer | No | `90` | Forward calendar days used for the occupancy proxy (7-365). |
| `maxRuntimeSeconds` | integer | No | `3600` | Soft runtime budget; auto-clamps and emits partial output before timeout. |
| `locationQueries` | array | No | `[]` | Drop-in migration alias; mapped to market mode. |
| `proxyConfiguration` | object | No | RESIDENTIAL | Apify proxy; residential is required for Airbnb. |

#### Input examples

- **Recommended first run (market):** `{ "market": "Austin, TX", "mode": "market", "rankBy": "attention", "enableMarketMemory": true }`
- **Scheduled monitor:** `{ "mode": "monitor", "market": "Austin, TX", "watchlistName": "austin-portfolio", "deltaWindowDays": 7, "rankBy": "attention" }`
- **Minimal listings check:** `{ "mode": "listings", "listings": ["https://www.airbnb.com/rooms/14926879"], "outputProfile": "minimal" }`

#### Input tips

- **Start with defaults** - market mode with market memory on covers most pricing and monitoring needs.
- **Name your watchlist consistently** - monitor mode keys state on `watchlistName`; a stable name keeps the memory clock running, a rename starts a fresh one.
- **Lower maxResults to control cost** - fewer records means a smaller per-run record charge while you test.
- **Use the agent profile for tools** - `outputProfile: "agent"` returns decisions without the full diagnostic envelope.

### Output example

A single listing record from a market run (default `signals` profile, abbreviated):

```json
{
  "schemaVersion": "1.0",
  "recordType": "listing",
  "eventId": "14926879",
  "id": "14926879",
  "url": "https://www.airbnb.com/rooms/14926879",
  "title": "Bright East Austin bungalow",
  "isSuperHost": true,
  "price": { "amount": 116, "currency": "USD", "breakDown": { "basePriceUsd": 116, "cleaningFeeUsd": 65, "serviceFeeUsd": 41, "totalBeforeTaxesUsd": 222, "nightsInQuote": 1 } },
  "rating": { "guestSatisfaction": 4.91, "cleanliness": 4.95, "value": 4.78, "reviewsCount": 184 },
  "attentionIndex": { "value": 87, "breakdown": { "activeSignals": 2, "pricingOpportunity": 0.45, "revenueOutlier": 0.0, "supplyShift": 0.0, "marketMomentum": 0.12 }, "drivers": ["Underpriced 18% vs comp median", "Price dropped this week", "Market tightening on availability"] },
  "watchStatus": "attention-required",
  "whyNow": ["Listing nightly price fell 18% ($142 to $116) vs comp-set median ADR.", "Estimated availability density tightened across the comp set."],
  "decisionRoute": "review-pricing",
  "recommendedAction": "Review this listing's nightly price; it sits below comp-set median while demand is tightening.",
  "pricePosition": { "metricClass": "derived", "compSetSize": 41, "compSetBasis": "same-market-roomType-capacity", "nightlyPriceUsd": 116, "pricingBand": { "lowUsd": 98, "medianUsd": 142, "highUsd": 205, "listingUsd": 116, "label": "below-market" }, "marketPercentile": 22, "positionLabel": "underpriced", "deltaVsMedianPct": -18.3, "confidenceGrade": "B", "limitations": ["Comp set capped at 240 per Airbnb."] },
  "revenueEstimate": { "status": "estimated", "metricClass": "estimated", "measuredByAirbnb": false, "basis": "availability-calendar-proxy", "method": "availability-proxy-v1", "estimateBasis": "heuristic", "occupancyRateEstimate": 0.59, "avgNightlyRateUsd": 116, "estimatedMonthlyRevenueUsd": 2050, "estimatedRevenueRangeUsd": [1640, 2460], "confidenceGrade": "C", "limitations": ["A blocked night may be a booking or a host block; the two are indistinguishable from public data."] },
  "signalEvents": [{ "type": "price_drop", "signalStrength": 0.88, "active": true, "decayStatus": "fresh", "metricClass": "observed", "reason": "Listing nightly price fell 18% vs comp-set median ADR.", "evidence": { "priceBefore": 142, "priceAfter": 116, "windowDays": 7 } }],
  "dataQuality": { "status": "clean", "urlValidated": true, "idMatchesUrl": true, "priceParsed": true, "calendarParsed": true, "issues": [] },
  "freshness": { "lastObservedAt": "2026-05-21T09:00:00Z", "stalenessHours": 0, "recommendedRecheckIntervalHours": 24 }
}
```

The market record adds `signalProfile`, `marketHealth`, `marketConfidence`, `marketFingerprint`, and `marketMemory`. The run summary adds `runOutcome`, `dailyBriefing`, `topActions`, `attentionBudget`, `runReliability`, and `coverage`.

![Sample attention queue output: each listing with its comp-set pricing position, attentionIndex, watchStatus, and a recommended action, ranked so the listings to reprice first are at the top](https://apifyforge.com/readme-assets/ryanclinton-airbnb-scraper/output-table.png)

### Output fields

| Field | Type | Description |
|-------|------|-------------|
| `recordType` | string | `listing`, `market`, `host`, `comparison`, `summary`, or `error`. |
| `attentionIndex.value` | number | Composite 0-100 score; the queue sort column. |
| `attentionIndex.drivers` | array | Top 3 paste-ready reasons for the score. |
| `watchStatus` | string | `no-action`, `monitor`, `attention-required`, `urgent`, `critical`. |
| `whyNow` | array | Plain-English reasons this record needs attention now. |
| `decisionRoute` | string | Flat enum for automation to branch on. |
| `recommendedAction` | string | Human-readable next step. |
| `pricePosition.positionLabel` | string | `underpriced`, `market-aligned`, `premium`, `overpriced`, `unclassified`. |
| `pricePosition.pricingBand` | object | Comp-set low, median, high, and this listing's price. |
| `pricePosition.deltaVsMedianPct` | number | Percent above or below comp-set median. |
| `revenueEstimate.metricClass` | string | Always `estimated` (or `insufficient`); the fabrication fence. |
| `revenueEstimate.estimatedRevenueRangeUsd` | array | Honest range band, never a single false number. |
| `revenueEstimate.measuredByAirbnb` | boolean | Hard-wired `false`; Airbnb does not publish this. |
| `signalEvents` | array | Typed, evidenced shift events with strength and decay. |
| `signalProfile` | string | Market archetype (market records only). |
| `marketHealth.direction` | string | `weakening`, `stable`, `improving`, `mixed`, `unknown`. |
| `marketConfidence.grade` | string | A-F confidence in the market read. |
| `marketMemory.memoryDepth` | string | `insufficient`, `building`, or `mature`. |
| `marketMemory.runsObserved` | number | How many runs of history this market has. |
| `coverage.marketRepresentativeness` | number | Scraped fraction of the estimated market (0-1). |
| `dataQuality.status` | string | `clean`, `minor-issue`, or `conflicted`. |
| `freshness.recommendedRecheckIntervalHours` | number | When to run again. |

### How much does it cost to scrape and monitor an Airbnb market?

Airbnb Scraper uses **pay-per-event pricing** - you pay **$0.0015 per emitted record** ($1.50 per 1,000) plus **$0.30 per market query** (one charge per market, monitor, or compare execution, regardless of result count). Apify platform compute is billed separately by Apify and is not included in these event prices. Every record carries the full signal layer at that price; there is no host add-on or per-signal upsell.

| Scenario | Records | Market queries | Total event cost |
|----------|---------|----------------|------------------|
| Quick test | 10 | 1 | $0.32 |
| Small market | 50 | 1 | $0.38 |
| Default market | 100 | 1 | $0.45 |
| Full market | 240 | 1 | $0.66 |
| Compare 3 markets | 720 | 3 | $1.98 |

Set a spending limit on the actor to cap costs; the actor stops emitting once the limit is reached and logs why. Apify's free tier ($5 in monthly credits) runs roughly 3,300 records here. A migrator running 50,000 records pays $75 plus query charges and gets the decision layer included.

### Scrape Airbnb using the API

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")

run = client.actor("ryanclinton/airbnb-scraper").call(run_input={
    "market": "Austin, TX",
    "mode": "market",
    "rankBy": "attention",
    "enableMarketMemory": True,
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    if item.get("recordType") == "listing":
        ai = item.get("attentionIndex", {})
        print(f"{item.get('title')}: attention={ai.get('value')} action={item.get('recommendedAction')}")
```

#### JavaScript

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

const client = new ApifyClient({ token: "YOUR_API_TOKEN" });

const run = await client.actor("ryanclinton/airbnb-scraper").call({
    market: "Austin, TX",
    mode: "market",
    rankBy: "attention",
    enableMarketMemory: true,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const item of items) {
    if (item.recordType === "listing") {
        console.log(`${item.title}: attention=${item.attentionIndex?.value} action=${item.recommendedAction}`);
    }
}
```

#### cURL

```bash
curl -X POST "https://api.apify.com/v2/acts/ryanclinton~airbnb-scraper/runs?token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "market": "Austin, TX", "mode": "market", "rankBy": "attention", "enableMarketMemory": true }'

curl "https://api.apify.com/v2/datasets/DATASET_ID/items?token=YOUR_API_TOKEN&format=json"
```

### How Airbnb Scraper works

**Mental model:** Airbnb pages to substrate, substrate to comp sets, comp sets to signals against prior runs, signals to an attention score, score to a routed decision, all wrapped in a trust layer.

#### 1. Fetch the substrate

Airbnb Scraper fetches public search, room, and host pages over residential proxies (required for Airbnb's anti-bot layer). It parses each listing into the faithful substrate, validates that every `url` resolves to its `id`, and drops any record with an unresolvable link rather than emitting a broken row.

#### 2. Build comp sets and pricing position

For each market it groups comparable listings (same market, room type, capacity), computes the comp-set band and median, and derives each listing's `pricePosition` with a percentile, a label, and a `compSetAudit` of what was included or excluded.

#### 3. Detect signals against history

When market memory is active, Airbnb Scraper loads the prior snapshot for each market and listing from a named state store and detects shifts: price moves, market price shifts, supply surges, saturation, and availability changes. Weak or noisy signals are suppressed and reported in the `attentionBudget`.

#### 4. Score attention and route a decision

Each record gets a composite `attentionIndex`, a `watchStatus`, an `attentionWindow`, a flat `decisionRoute`, and a human `recommendedAction`. Persona weights reshape what escalates. The market memory and snapshots are then persisted for the next run.

### Tips for best results

1. **Schedule a daily run.** Market memory only compounds if you run it. A daily cadence unlocks trajectory by run 3 and persistence by run 10.
2. **Pick rankBy to match the job.** Use `pricingOpportunity` for repricing, `revenue` for acquisition scouting, `occupancy` for demand reads.
3. **Set a persona.** `investor` weights revenue and occupancy; `host` weights pricing position and price moves; `analyst` weights supply and saturation.
4. **Read coverage before trusting a market read.** `coverage.marketRepresentativeness` tells you how much of the market the sample covers.
5. **Combine with monitoring.** Pipe the attention queue into the actors below to push only the rows that need a human into a CRM, sheet, or alert.

### Combine with other Apify actors

| Actor | How to combine |
|-------|---------------|
| [Website Change Monitor](https://apify.com/ryanclinton/website-change-monitor) | Track host websites alongside the Airbnb attention queue. |
| [Website Contact Scraper](https://apify.com/ryanclinton/website-contact-scraper) | Enrich host portfolios with contact details from their own sites. |
| [Company Deep Research](https://apify.com/ryanclinton/company-deep-research) | Research the operator behind a scaling host portfolio. |
| [Trustpilot Review Analyzer](https://apify.com/ryanclinton/trustpilot-review-analyzer) | Pull sentiment on property managers surfaced in host mode. |
| [HubSpot Lead Pusher](https://apify.com/ryanclinton/hubspot-lead-pusher) | Push attention-flagged listings or hosts into your CRM. |
| [WHOIS Domain Lookup](https://apify.com/ryanclinton/whois-domain-lookup) | Resolve ownership of host-linked domains. |

### What this does NOT do

- **Not a licensed STR database.** Airbnb Scraper uses public Airbnb data only. It is not AirDNA or Mashvisor and does not provide their licensed, modelled booking datasets.
- **Revenue and occupancy are estimates, not measured bookings.** They are inferred from the public availability calendar, always fenced with a range band, and never presented as fact.
- **No in-Airbnb actions.** It does not book, message hosts, leave reviews, or set platform prices. It is a read-only actor.
- **Descriptive, not advisory.** It describes market state. It does not give investment advice or guarantee returns; consult a professional for financial decisions.
- **No private data.** No login, no CAPTCHA bypass, no guest PII, no access to anything behind authentication.

### Why use Airbnb Scraper instead of a spreadsheet or a closed dashboard?

Pricing a market by hand means scraping rows, building comp sets in a spreadsheet, and re-checking weekly. It is slow, it goes stale, and the comp logic lives in one analyst's head. Closed dashboards like AirDNA and Mashvisor solve the analysis but cost $50-200 per month, lock the data behind their UI, and are built for human-driven browsing rather than automation. Pricing tools handle one narrow job and keep no memory across checks.

The real competitor is not another scraper. It is the spreadsheet, or your AirDNA seat. Airbnb Scraper is built for automation-first workflows: it returns finished, structured decisions with accumulated market memory, priced per record and per query rather than per seat.

**Key difference: Airbnb Scraper ships the decision layer and the accumulated market memory that raw scrapers and closed dashboards do not put in your pipeline.**

| Feature | Airbnb Scraper | Raw Airbnb scrapers | AirDNA / Mashvisor |
|---------|----------------|---------------------|--------------------|
| Data source | Public Airbnb pages | Public Airbnb pages | Licensed, modelled datasets |
| Comp-set pricing position | Yes, per listing | No | Yes, in dashboard |
| Attention queue and routing | Yes | No | Not a core feature |
| Revenue and occupancy | Estimated, fenced with a band | Not a core feature | Modelled, often presented as figures |
| Cross-run market memory | Yes, compounds every run | No | Internal to the product |
| Output format | JSON, CSV, Excel, API | Raw rows | Dashboard, varies by plan |
| Automation and scheduling | Native on Apify | Varies | Limited, UI-first |
| Pricing | $1.50/1k records + $0.30/query | Varies | Roughly $50-200/mo, varies by plan |
| Best for | Automated monitoring and repricing | Bulk row collection | Human-driven analysis |

*Pricing and features based on publicly available information as of May 2026 and may change.*

#### Why use this instead of AirDNA?

AirDNA is better for licensed historical booking datasets and dashboard-driven exploration. The Airbnb market monitoring engine is better for automation-first workflows: scheduled monitoring, machine-readable routing (`decisionRoute`), and market memory that compounds, priced per record and query rather than per seat. It uses public data and fenced estimates, not licensed datasets, so reach for it where automatable, honest reads beat a per-seat dashboard.

#### Why use this instead of PriceLabs or Beyond?

Dynamic-pricing tools automate one narrow job, set a nightly rate, and keep no cross-run market memory. This engine is the layer above: it tells you where a listing sits in its comp set and how the whole market is moving, then routes the few rows that need a human. Feed its `pricePosition` into your pricing tool; it does not replace the pricing engine, it informs it.

#### Why use this instead of a raw Airbnb scraper?

A raw scraper returns rows; you still build the comp sets, the monitoring, and the triage by hand. This engine ships those as output: comp-set pricing position, an attention queue, signal detection, and market memory. Same input shape and same substrate fields, plus the decision layer.

#### Why use this instead of manual comp analysis?

Manual comp analysis lives in one analyst's spreadsheet, goes stale between checks, and cannot watch a market while you sleep. The engine rebuilds the comp set every run, detects what changed since the last one, and accumulates a market memory the spreadsheet cannot.

**Best for:** automation-first workflows, scheduled market monitoring, comp-set pricing analysis, machine-readable routing into CRMs and pricing tools.
**Reach for a licensed product instead when:** you need measured historical booking volumes, modelled occupancy, or a full census above Airbnb's 240-per-market cap.

### Responsible use

- Airbnb Scraper extracts publicly available listing, market, and host data from Airbnb. It does not bypass authentication, CAPTCHAs, or access restricted content, and it performs no in-platform actions.
- Users are responsible for ensuring their use complies with applicable laws and platform terms, including data protection regulations in their jurisdiction.
- Revenue and occupancy figures are estimates from public availability data, not measured bookings; do not present them as fact or use them as the sole basis for a financial decision.
- For guidance on web scraping legality, see [Apify's guide](https://blog.apify.com/is-web-scraping-legal/).

### Limitations

- **Public data only.** No login, no private host or guest data, no booking history.
- **Revenue and occupancy are estimates.** A blocked night may be a booking or a host block; the two cannot be told apart from public data.
- **Market sample caps at 240.** Airbnb limits results per market; `coverage.marketRepresentativeness` reports the fraction sampled.
- **Trajectory needs history.** `signalTrajectory` and `persistenceClass` require multiple runs; they return insufficient until memory matures.
- **Anti-bot conditions vary.** Heavy challenge rates can trip the circuit breaker; the run emits partial output and flags it in `truncatedReason`.
- **Renaming a watchlist resets memory.** State is keyed on `watchlistName`; a new name starts a fresh memory clock.
- **No seasonal reads in v1.0.** Seasonality and cyclical classification are reserved and return as not-yet-available.

### Integrations

- [Zapier](https://apify.com/integrations/zapier) - schedule a daily market run so the market memory compounds, and route the attention queue onward.
- [Make](https://apify.com/integrations/make) - branch on `decisionRoute` to fire alerts only for rows that need a human.
- [Google Sheets](https://apify.com/integrations/google-sheets) - append the daily attention queue to a tracking sheet.
- [Apify API](https://docs.apify.com/api/v2) - run Airbnb Scraper from any HTTP client and read the dataset.
- [Webhooks](https://docs.apify.com/platform/integrations/webhooks) - push run completion into your own pipeline.
- [LangChain / LlamaIndex](https://docs.apify.com/platform/integrations) - feed the `agent` output profile to an AI agent or pricing tool.

### Common Airbnb market-monitoring questions

#### How do I detect underpriced Airbnb listings?

Run market mode with `rankBy: "pricingOpportunity"`. Each listing returns `pricePosition.positionLabel` (underpriced, market-aligned, premium, overpriced) and `deltaVsMedianPct` versus its comp set.

#### How do I monitor Airbnb supply growth?

Run monitor mode on a city daily with `enableMarketMemory: true`. The engine fires `new_listing_surge` and `market_saturation` when active listing counts rise across runs.

#### How do I estimate Airbnb revenue from public data?

Enable `estimateRevenue` (on by default). Each listing returns a fenced `revenueEstimate` with an `estimatedRevenueRangeUsd` band, `metricClass: estimated`, and `measuredByAirbnb: false`.

#### How do I compare two Airbnb markets?

Run compare mode with a list of `markets`. One ranked record returns archetype, direction, and confidence per city, charged as one market query each.

#### How do I track a competitor's Airbnb listings?

Run host mode with the host's `/users/show/<id>` URL, or monitor mode with the listing IDs in `trackListings`. You get `hostMomentum` and per-listing deltas across runs.

#### How do I get only what changed since my last check?

Run monitor mode with a stable `watchlistName`, and optionally pass `lastReviewedAt`. The record's `sinceLastReview` and `changeFlags` report new and resolved signals since that point.

#### How do I send Airbnb market alerts to Slack or a CRM?

Use the `agent` output profile and branch your Zapier, Make, or webhook flow on `decisionRoute` so only `attention-required` and above fire an alert.

### FAQ

**What is the difference between an Airbnb scraper and an Airbnb market monitor?** A scraper returns raw rows. Airbnb Scraper runs as a market monitoring engine: it ranks listings by what to review first, detects what changed across runs, and accumulates market memory, so you get a decision rather than a dataset.

**How do I monitor an Airbnb market over time?** Run market or monitor mode with `enableMarketMemory: true`, give a monitor run a stable `watchlistName`, and schedule a daily run. Each run returns what changed and compounds the history.

**Can I use Airbnb Scraper to find underpriced listings?** Yes. Set `rankBy: "pricingOpportunity"`; each listing carries `pricePosition` with a `positionLabel` of underpriced, market-aligned, premium, or overpriced versus its comp set.

**Does this actor measure real bookings?** No. Revenue and occupancy are estimates inferred from the public availability calendar, always carrying `metricClass: estimated` and `measuredByAirbnb: false`, with a range band. A blocked night may be a booking or a host block.

**What does the attention queue actually contain?** Each row carries a composite `attentionIndex` (0-100), a `watchStatus`, the reasons (`whyNow`), a `decisionRoute` your automation can branch on, and a human `recommendedAction`.

**How is Airbnb Scraper a practical alternative to AirDNA for market selection?** AirDNA is a closed, paid dashboard built for human browsing. Airbnb Scraper returns structured market reads (archetype, direction, confidence) per query, in JSON or CSV, for automation-first workflows, with market memory that compounds. It uses public data and estimates, not licensed datasets, so use it where automatable, fenced reads beat a per-seat dashboard.

**Can I migrate from my existing Airbnb scraper without changing my code?** Yes. Paste your `locationQueries` input and set `outputProfile: "compat"` for the exact original field set with validated URLs. The signal layer is additive on the default profile.

**What is market memory and why does it matter?** It is the per-market interpretation history that accrues every run. Run 1 finds comp outliers; run 3 unlocks trajectory; run 10 unlocks persistent-signal classification. The clock cannot be backfilled, so the value compounds the longer you run it.

**Can I use it for multiple cities at once?** Yes. Use compare mode with a list of `markets` to rank cities side by side on revenue, occupancy, supply, and ADR, each charged as one market query.

**How much does a typical run cost?** A default 100-record market run costs about $0.45 ($0.15 in records plus the $0.30 market query), separate from Apify platform compute.

**What happens if a run hits the timeout?** The actor reserves emit time and pushes partial output before any hard kill, flagging it in `partialOutputPolicy` and `truncatedReason` so a timed-out run is still usable and diagnosable.

**Is it legal to scrape Airbnb data?** Airbnb Scraper accesses only public content and performs no in-platform actions. Whether your specific use is permitted depends on your jurisdiction and intended use, including data protection rules; consult legal counsel for your situation. See [Apify's guide on scraping legality](https://blog.apify.com/is-web-scraping-legal/).

### Recent updates

- **Cost-transparency logging** - runs now log per-event charge counts and note that platform compute is separate.
- **Canonical run-plan diagnostics** - a run-plan line is logged before heavy work so timed-out runs stay diagnosable.
- **Large-input guardrail** - runs warn when a high record volume could be emitted and charged, so you can cap spend.
- **Explicit PPE charge summary** - the completion message reports charged records and market queries.

### Help us improve

If you encounter issues, you can help us debug faster by enabling run sharing in your Apify account:

1. Go to [Account Settings > Privacy](https://console.apify.com/account/privacy)
2. Enable **Share runs with public Actor creators**

This lets us see your run details when something goes wrong, so we can fix issues faster. Your data is only visible to the actor developer, not publicly.

### Support

Found a bug or have a feature request? Open an issue in the Issues tab on this actor's page. For custom solutions or enterprise integrations, reach out through the Apify platform.

# Actor input Schema

## `mode` (type: `string`):

Entry point. 'market' (default) ranks listings in a city by pricing/revenue opportunity. 'monitor' tracks a market over time and returns only what changed (the killer mode). 'listings' explains where specific room URLs sit vs their comp set. 'host' surfaces host-portfolio momentum. 'compare' ranks 2+ markets side by side. Leave fields below empty to use the market demo (Austin, TX).

## `market` (type: `string`):

Market mode / monitor mode: a city or destination, e.g. 'Austin, TX'. The actor ranks the listings by where they sit in their comp set and how the market is moving.

## `markets` (type: `array`):

Compare mode: 2+ cities to rank side by side on revenue / occupancy / supply / ADR axes. Example: \["Austin, TX", "Nashville, TN", "Savannah, GA"].

## `listings` (type: `array`):

Listings mode: Airbnb /rooms/<id> URLs to analyse. Each result carries its pricing position vs its market plus a fenced revenue estimate.

## `hosts` (type: `array`):

Host mode: Airbnb /users/show/<id> URLs. Each result carries hostMomentum (listing-count trend + superhost positioning).

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

Filter listings by room type. 'any' includes all.

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

Only include listings with at least this many bedrooms.

## `minPrice` (type: `integer`):

Lower bound on nightly price.

## `maxPrice` (type: `integer`):

Upper bound on nightly price.

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

Number of guests used to size the search.

## `rankBy` (type: `string`):

How to order the attention queue. 'attention' uses the composite attentionIndex. 'pricingOpportunity' surfaces comp outliers. 'revenue' surfaces estimated revenue leaders. 'occupancy' surfaces tightest-demand listings.

## `maxResults` (type: `integer`):

Maximum listings to scrape per market (Airbnb caps a market at ~240; coverage.marketRepresentativeness reports the sample fraction honestly).

## `estimateRevenue` (type: `boolean`):

When on, each listing carries a fenced revenue/occupancy estimate from the public availability calendar (metricClass: estimated, measuredByAirbnb: false, with a range band + limitations). This is an estimate, never a measured booking figure.

## `enableMarketMemory` (type: `boolean`):

When on (default for market/monitor modes), the actor accrues a per-market interpretation history across runs - the moat. Run it daily: run 1 finds comp outliers, run 3 unlocks trajectory, run ~10 unlocks structural reads. The memory clock cannot be backfilled.

## `watchlistName` (type: `string`):

Monitor mode: a stable name for this watchlist. State (price/supply/occupancy history, signal recurrence) persists in a named store keyed on this name across runs. Rename = a fresh memory clock (memoryResetReason: watchlist-renamed).

## `trackListings` (type: `array`):

Monitor mode: specific listing IDs to track over time alongside the market.

## `deltaWindowDays` (type: `integer`):

The comparison window for delta intelligence (what changed since the prior run).

## `lastReviewedAt` (type: `string`):

Optional. The timestamp your dashboard/automation last surfaced this market to a human. Drives sinceLastReview ('what changed since YOU last looked'). If omitted, the actor falls back to since-last-run - it never fabricates knowledge of when a human looked.

## `persona` (type: `string`):

Reshapes materiality weights and which signals escalate. 'host' weights pricing position + price moves; 'investor' weights revenue + occupancy; 'analyst' weights supply/saturation. Orthogonal to mode and rankBy.

## `outputProfile` (type: `string`):

'signals' (default) = full envelope: pricing position + revenue estimate + signals + attention routing + market profile + delta. 'compat' = exact tri\_angle field set with validated URLs/IDs, no signal fields (migration parity). 'agent' = decision surface for MCP / pricing tools. 'minimal' = IDs + URL + price only. 'debug' = full diagnostics.

## `analysisDepth` (type: `string`):

'fast' = substrate + pricing position. 'standard' (default) = + signals. 'deep' = + full revenue suite and trajectory.

## `explainability` (type: `string`):

'standard' trims the heaviest diagnostic blocks (signalLineage, materialityDrivers). 'full' keeps everything.

## `calendarDepthDays` (type: `integer`):

How many forward days of the availability calendar to use for the occupancy/revenue proxy.

## `maxRuntimeSeconds` (type: `integer`):

Soft runtime budget. The actor auto-clamps against the Apify timeout and emits partial output before a hard kill (partialOutputPolicy).

## `locationQueries` (type: `array`):

Drop-in migration: the tri\_angle/airbnb-scraper input field. City/destination names; mapped to market mode automatically. Use 'market' / 'markets' for new runs.

## `proxyConfiguration` (type: `object`):

Apify proxy. Defaults to RESIDENTIAL (required for Airbnb's anti-bot layer). Leave as default unless you have a reason to change it.

## Actor input object example

```json
{
  "mode": "market",
  "market": "Austin, TX",
  "markets": [],
  "listings": [],
  "hosts": [],
  "roomType": "any",
  "minBedrooms": 0,
  "minPrice": 0,
  "maxPrice": 0,
  "adults": 2,
  "rankBy": "attention",
  "maxResults": 100,
  "estimateRevenue": true,
  "enableMarketMemory": true,
  "watchlistName": "",
  "trackListings": [],
  "deltaWindowDays": 7,
  "lastReviewedAt": "",
  "persona": "generic",
  "outputProfile": "signals",
  "analysisDepth": "standard",
  "explainability": "standard",
  "calendarDepthDays": 90,
  "maxRuntimeSeconds": 3600,
  "locationQueries": [],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `summary` (type: `string`):

No description

## `attentionQueueKey` (type: `string`):

No description

## `marketMemory` (type: `string`):

No description

## `manifest` (type: `string`):

No description

## `attentionQueue` (type: `string`):

No description

## `results` (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 = {
    "market": "Austin, TX"
};

// Run the Actor and wait for it to finish
const run = await client.actor("ryanclinton/airbnb-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 = { "market": "Austin, TX" }

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

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

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

```

## CLI example

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=ryanclinton/airbnb-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Airbnb Scraper - Market Signals, Pricing Position & Monitor",
        "description": "Stateful Airbnb market monitoring engine. Each run returns a ranked attention queue - what changed, what matters, what to review - with comp-set pricing position, revenue estimates, and supply-surge detection. Drop-in compatible with tri_angle/airbnb-scraper.",
        "version": "1.0",
        "x-build-id": "aitdTCSdhvsyb7kRH"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/ryanclinton~airbnb-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-ryanclinton-airbnb-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/ryanclinton~airbnb-scraper/runs": {
            "post": {
                "operationId": "runs-sync-ryanclinton-airbnb-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/ryanclinton~airbnb-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-ryanclinton-airbnb-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "mode": {
                        "title": "Mode",
                        "enum": [
                            "market",
                            "monitor",
                            "listings",
                            "host",
                            "compare"
                        ],
                        "type": "string",
                        "description": "Entry point. 'market' (default) ranks listings in a city by pricing/revenue opportunity. 'monitor' tracks a market over time and returns only what changed (the killer mode). 'listings' explains where specific room URLs sit vs their comp set. 'host' surfaces host-portfolio momentum. 'compare' ranks 2+ markets side by side. Leave fields below empty to use the market demo (Austin, TX).",
                        "default": "market"
                    },
                    "market": {
                        "title": "Market (city / destination)",
                        "type": "string",
                        "description": "Market mode / monitor mode: a city or destination, e.g. 'Austin, TX'. The actor ranks the listings by where they sit in their comp set and how the market is moving.",
                        "default": ""
                    },
                    "markets": {
                        "title": "Markets (compare mode)",
                        "type": "array",
                        "description": "Compare mode: 2+ cities to rank side by side on revenue / occupancy / supply / ADR axes. Example: [\"Austin, TX\", \"Nashville, TN\", \"Savannah, GA\"].",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "listings": {
                        "title": "Listing URLs",
                        "type": "array",
                        "description": "Listings mode: Airbnb /rooms/<id> URLs to analyse. Each result carries its pricing position vs its market plus a fenced revenue estimate.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "hosts": {
                        "title": "Host URLs",
                        "type": "array",
                        "description": "Host mode: Airbnb /users/show/<id> URLs. Each result carries hostMomentum (listing-count trend + superhost positioning).",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "roomType": {
                        "title": "Room type",
                        "enum": [
                            "any",
                            "entire_home",
                            "private_room",
                            "shared_room",
                            "hotel_room"
                        ],
                        "type": "string",
                        "description": "Filter listings by room type. 'any' includes all.",
                        "default": "any"
                    },
                    "minBedrooms": {
                        "title": "Minimum bedrooms",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Only include listings with at least this many bedrooms.",
                        "default": 0
                    },
                    "minPrice": {
                        "title": "Minimum nightly price (USD)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Lower bound on nightly price.",
                        "default": 0
                    },
                    "maxPrice": {
                        "title": "Maximum nightly price (USD)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Upper bound on nightly price.",
                        "default": 0
                    },
                    "adults": {
                        "title": "Guests (adults)",
                        "minimum": 1,
                        "maximum": 16,
                        "type": "integer",
                        "description": "Number of guests used to size the search.",
                        "default": 2
                    },
                    "rankBy": {
                        "title": "Rank by",
                        "enum": [
                            "attention",
                            "pricingOpportunity",
                            "revenue",
                            "occupancy",
                            "rating",
                            "relevance"
                        ],
                        "type": "string",
                        "description": "How to order the attention queue. 'attention' uses the composite attentionIndex. 'pricingOpportunity' surfaces comp outliers. 'revenue' surfaces estimated revenue leaders. 'occupancy' surfaces tightest-demand listings.",
                        "default": "attention"
                    },
                    "maxResults": {
                        "title": "Max results per market",
                        "minimum": 1,
                        "maximum": 240,
                        "type": "integer",
                        "description": "Maximum listings to scrape per market (Airbnb caps a market at ~240; coverage.marketRepresentativeness reports the sample fraction honestly).",
                        "default": 100
                    },
                    "estimateRevenue": {
                        "title": "Estimate revenue & occupancy",
                        "type": "boolean",
                        "description": "When on, each listing carries a fenced revenue/occupancy estimate from the public availability calendar (metricClass: estimated, measuredByAirbnb: false, with a range band + limitations). This is an estimate, never a measured booking figure.",
                        "default": true
                    },
                    "enableMarketMemory": {
                        "title": "Enable market memory",
                        "type": "boolean",
                        "description": "When on (default for market/monitor modes), the actor accrues a per-market interpretation history across runs - the moat. Run it daily: run 1 finds comp outliers, run 3 unlocks trajectory, run ~10 unlocks structural reads. The memory clock cannot be backfilled.",
                        "default": true
                    },
                    "watchlistName": {
                        "title": "Watchlist name (monitor mode)",
                        "type": "string",
                        "description": "Monitor mode: a stable name for this watchlist. State (price/supply/occupancy history, signal recurrence) persists in a named store keyed on this name across runs. Rename = a fresh memory clock (memoryResetReason: watchlist-renamed).",
                        "default": ""
                    },
                    "trackListings": {
                        "title": "Tracked listing IDs (monitor mode)",
                        "type": "array",
                        "description": "Monitor mode: specific listing IDs to track over time alongside the market.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "deltaWindowDays": {
                        "title": "Delta window (days)",
                        "minimum": 1,
                        "maximum": 90,
                        "type": "integer",
                        "description": "The comparison window for delta intelligence (what changed since the prior run).",
                        "default": 7
                    },
                    "lastReviewedAt": {
                        "title": "Last reviewed at (ISO timestamp)",
                        "type": "string",
                        "description": "Optional. The timestamp your dashboard/automation last surfaced this market to a human. Drives sinceLastReview ('what changed since YOU last looked'). If omitted, the actor falls back to since-last-run - it never fabricates knowledge of when a human looked.",
                        "default": ""
                    },
                    "persona": {
                        "title": "Persona",
                        "enum": [
                            "generic",
                            "host",
                            "investor",
                            "analyst"
                        ],
                        "type": "string",
                        "description": "Reshapes materiality weights and which signals escalate. 'host' weights pricing position + price moves; 'investor' weights revenue + occupancy; 'analyst' weights supply/saturation. Orthogonal to mode and rankBy.",
                        "default": "generic"
                    },
                    "outputProfile": {
                        "title": "Output profile",
                        "enum": [
                            "signals",
                            "compat",
                            "agent",
                            "minimal",
                            "debug"
                        ],
                        "type": "string",
                        "description": "'signals' (default) = full envelope: pricing position + revenue estimate + signals + attention routing + market profile + delta. 'compat' = exact tri_angle field set with validated URLs/IDs, no signal fields (migration parity). 'agent' = decision surface for MCP / pricing tools. 'minimal' = IDs + URL + price only. 'debug' = full diagnostics.",
                        "default": "signals"
                    },
                    "analysisDepth": {
                        "title": "Analysis depth",
                        "enum": [
                            "fast",
                            "standard",
                            "deep"
                        ],
                        "type": "string",
                        "description": "'fast' = substrate + pricing position. 'standard' (default) = + signals. 'deep' = + full revenue suite and trajectory.",
                        "default": "standard"
                    },
                    "explainability": {
                        "title": "Explainability",
                        "enum": [
                            "standard",
                            "full"
                        ],
                        "type": "string",
                        "description": "'standard' trims the heaviest diagnostic blocks (signalLineage, materialityDrivers). 'full' keeps everything.",
                        "default": "standard"
                    },
                    "calendarDepthDays": {
                        "title": "Calendar depth (days forward)",
                        "minimum": 7,
                        "maximum": 365,
                        "type": "integer",
                        "description": "How many forward days of the availability calendar to use for the occupancy/revenue proxy.",
                        "default": 90
                    },
                    "maxRuntimeSeconds": {
                        "title": "Max runtime (seconds)",
                        "minimum": 60,
                        "maximum": 7200,
                        "type": "integer",
                        "description": "Soft runtime budget. The actor auto-clamps against the Apify timeout and emits partial output before a hard kill (partialOutputPolicy).",
                        "default": 3600
                    },
                    "locationQueries": {
                        "title": "Location queries (compat alias)",
                        "type": "array",
                        "description": "Drop-in migration: the tri_angle/airbnb-scraper input field. City/destination names; mapped to market mode automatically. Use 'market' / 'markets' for new runs.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Apify proxy. Defaults to RESIDENTIAL (required for Airbnb's anti-bot layer). Leave as default unless you have a reason to change it.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ]
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
