# Airbnb Occupancy, Availability & Dynamic-Pricing Scraper (`xtracto/airbnb-occupancy`) Actor

Derive per-listing occupancy %, available/booked nights, min-nights and booking-pace from Airbnb's forward availability calendar — short-term-rental revenue intelligence (the AirDNA / AllTheRooms signal). By listing ID or search area.

- **URL**: https://apify.com/xtracto/airbnb-occupancy.md
- **Developed by:** [xtractoo](https://apify.com/xtracto) (community)
- **Categories:** E-commerce, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 results

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

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

## 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 Occupancy & Availability Scraper

Turn any Airbnb listing's forward calendar into occupancy %, booked vs. available nights, minimum-stay, and booking pace — the short-term-rental revenue signal that subscription tools sell. One result = one listing's calendar (plus an optional profile record).

### Why use this actor

- No account, no login, and no API key required
- Per-listing occupancy for the next 30 / 60 / 90 / 365 days, plus available-nights and minimum-stay
- Booking pace: how many nights got booked (or freed) since your last run
- Works from a list of listings or from a whole search area
- Optional listing profile (title, room type, location, rating, capacity) at no extra cost
- Stable JSON output suitable for pipelines, market analysis, or revenue modeling

### How it works

1. Give the actor either specific Airbnb listing IDs, or a search area (e.g. `Bali--Indonesia`).
2. For each listing it reads the forward availability calendar and works out the occupancy and pace metrics.
3. Results stream into your dataset, ready to download as JSON, CSV, or Excel.

You don't manage scrapers, browsers, or retries — the actor handles all of that.

### Input

```json
{
  "mode": "listing",
  "listingIds": ["983207483398233150"],
  "location": "Bali--Indonesia",
  "currency": "USD",
  "calendarMonths": 12,
  "computeOccupancy": true,
  "includeProfile": true,
  "maxListings": 500,
  "concurrency": 3,
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
````

| Field | Type | Description |
|---|---|---|
| `mode` | string | `listing` — scrape specific listing IDs. `searchArea` — find listings in an area first, then scrape them. |
| `listingIds` | array | Listing IDs (the number in `/rooms/<id>`) or full room URLs. Used in `listing` mode. |
| `location` | string | Search area slug as in `/s/<location>/homes`, e.g. `Bali--Indonesia`. Used in `searchArea` mode. |
| `currency` | string | Currency code for any returned prices. Default `USD`. |
| `calendarMonths` | integer | Forward months of availability to read (1–12). Default 12. |
| `computeOccupancy` | boolean | Add occupancy / booked-nights / pace metrics. Turn off for just the raw calendar. Default true. |
| `includeProfile` | boolean | Also output a listing profile record. Default true. |
| `maxListings` | integer | Hard cap on listings processed per run. Default 500. |
| `concurrency` | integer | How many listings to process in parallel. Default 3. |
| `proxyConfiguration` | object | Proxy settings. A residential pool is recommended. |

### Output

**Calendar + occupancy record** (`recordType: "LISTING_CALENDAR"`):

```json
{
  "_input": "983207483398233150",
  "_source": "S1-graphql-calendar",
  "_scrapedAt": "2026-06-03T10:00:00Z",
  "recordType": "LISTING_CALENDAR",
  "listing_id": "983207483398233150",
  "currency": "USD",
  "days": [
    { "calendarDate": "2026-06-10", "available": true, "bookable": true,
      "availableForCheckin": true, "minNights": 2, "maxNights": 365 }
  ],
  "occupancy_30d": 0.40, "booked_nights_30d": 12, "nights_counted_30d": 30,
  "occupancy_90d": 0.24, "occupancy_365d": 0.49,
  "available_nights_horizon": 184, "horizon_days": 364,
  "min_nights_mode": 1,
  "adr": null, "adr_source": null,
  "calendar_start": "2026-06-03", "calendar_end": "2027-05-31",
  "booking_pace": { "newly_booked_nights": 6, "newly_freed_nights": 1 }
}
```

**Profile record** (`recordType: "LISTING_PROFILE"`): `title`, `room_type`, `lat`, `lng`, `rating`, `reviews_count`, `person_capacity`, `bedrooms`, `listing_url`. Missing fields are omitted, never guessed.

| Field | Type | Description |
|---|---|---|
| `listing_id` | string | Airbnb listing ID. |
| `days` | array | The raw forward calendar (date, available, bookable, min/max nights). |
| `occupancy_30d` / `_90d` / `_365d` | number | Share of upcoming nights that are unavailable, per window (0–1). |
| `booked_nights_30d` / `nights_counted_30d` | number | Unavailable and total counted nights in the 30-day window. |
| `available_nights_horizon` | number | Bookable nights across the whole calendar horizon. |
| `min_nights_mode` | number | Most common minimum-stay across upcoming nights. |
| `booking_pace` | object | Nights booked / freed since the previous run for this listing. |
| `adr` | number | Average nightly price, when Airbnb exposes it (usually null for anonymous reads). |

A listing that can't be read returns an `_error` record instead of being dropped.

### How occupancy is calculated (please read)

- Occupancy = **unavailable upcoming nights ÷ counted upcoming nights** in each window (30 / 60 / 90 / 365 days). Only dates from today forward are counted.
- Airbnb does **not** say *why* a night is unavailable, so a night blocked by the host reads the same as a booked night. Occupancy here is therefore an **estimate** — the same limitation every calendar-based occupancy product has.
- **Booking pace** compares this run to your previous run for the same listing, so the first run has no pace yet.
- Per-night prices come back empty for anonymous reads, so `adr` and revenue are usually unavailable. Occupancy never depends on price.

### Notes

- A residential proxy is recommended for reliable results.
- In `searchArea` mode, coverage is roughly one page of listings per area — give specific areas (or use listing mode) for breadth.
- Availability and pace are point-in-time and change continuously.

# Actor input Schema

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

'listing' scrapes the calendars of specific listing IDs. 'searchArea' first resolves listing IDs from an area's search results, then scrapes their calendars.

## `listingIds` (type: `array`):

Airbnb listing IDs (the number in /rooms/<id>), e.g. '983207483398233150'. Full room URLs are also accepted. Required when mode = listing.

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

Airbnb search area slug as in the URL /s/<location>/homes, e.g. 'Bali--Indonesia' or 'Austin--TX'. Required when mode = searchArea.

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

ISO currency code for any returned prices (e.g. USD, EUR, GBP). Note: Airbnb returns null per-night calendar prices for anonymous requests, so ADR/revenue are usually unavailable — occupancy does not depend on price.

## `calendarMonths` (type: `integer`):

How many forward months of availability to request (1-12). Airbnb caps the horizon at ~12 months.

## `computeOccupancy` (type: `boolean`):

Derive occupancy\_30/60/90/365d, booked-nights, min-nights mode, and booking-pace deltas from the raw calendar. Turn off to emit only the raw days\[].

## `includeProfile` (type: `boolean`):

Also emit a LISTING\_PROFILE record (title, room type, lat/lng, rating, review count, capacity) harvested from the listing page. Adds no extra requests (uses the warm-up page).

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

Hard cap on listings processed in one run (applies to both modes).

## `concurrency` (type: `integer`):

How many listings to process in parallel. Keep low (1-4) to stay under Airbnb's rate limits.

## `logLevel` (type: `string`):

Set DEBUG for verbose troubleshooting output.

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

Residential proxy is strongly recommended — Airbnb fingerprints datacenter ASNs upstream of the TLS/header layer. Light runs may work without one.

## Actor input object example

```json
{
  "mode": "listing",
  "listingIds": [
    "983207483398233150"
  ],
  "location": "Bali--Indonesia",
  "currency": "USD",
  "calendarMonths": 12,
  "computeOccupancy": true,
  "includeProfile": true,
  "maxListings": 500,
  "concurrency": 3,
  "logLevel": "INFO",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# 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 = {
    "listingIds": [
        "983207483398233150"
    ],
    "location": "Bali--Indonesia",
    "currency": "USD"
};

// Run the Actor and wait for it to finish
const run = await client.actor("xtracto/airbnb-occupancy").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 = {
    "listingIds": ["983207483398233150"],
    "location": "Bali--Indonesia",
    "currency": "USD",
}

# Run the Actor and wait for it to finish
run = client.actor("xtracto/airbnb-occupancy").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 '{
  "listingIds": [
    "983207483398233150"
  ],
  "location": "Bali--Indonesia",
  "currency": "USD"
}' |
apify call xtracto/airbnb-occupancy --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Airbnb Occupancy, Availability & Dynamic-Pricing Scraper",
        "description": "Derive per-listing occupancy %, available/booked nights, min-nights and booking-pace from Airbnb's forward availability calendar — short-term-rental revenue intelligence (the AirDNA / AllTheRooms signal). By listing ID or search area.",
        "version": "0.1",
        "x-build-id": "mBaa1VAk6hc8JREKe"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/xtracto~airbnb-occupancy/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-xtracto-airbnb-occupancy",
                "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/xtracto~airbnb-occupancy/runs": {
            "post": {
                "operationId": "runs-sync-xtracto-airbnb-occupancy",
                "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/xtracto~airbnb-occupancy/run-sync": {
            "post": {
                "operationId": "run-sync-xtracto-airbnb-occupancy",
                "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",
                "required": [
                    "mode"
                ],
                "properties": {
                    "mode": {
                        "title": "Mode",
                        "enum": [
                            "listing",
                            "searchArea"
                        ],
                        "type": "string",
                        "description": "'listing' scrapes the calendars of specific listing IDs. 'searchArea' first resolves listing IDs from an area's search results, then scrapes their calendars.",
                        "default": "listing"
                    },
                    "listingIds": {
                        "title": "Listing IDs (listing mode)",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Airbnb listing IDs (the number in /rooms/<id>), e.g. '983207483398233150'. Full room URLs are also accepted. Required when mode = listing.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "location": {
                        "title": "Location / area (searchArea mode)",
                        "type": "string",
                        "description": "Airbnb search area slug as in the URL /s/<location>/homes, e.g. 'Bali--Indonesia' or 'Austin--TX'. Required when mode = searchArea."
                    },
                    "currency": {
                        "title": "Currency",
                        "type": "string",
                        "description": "ISO currency code for any returned prices (e.g. USD, EUR, GBP). Note: Airbnb returns null per-night calendar prices for anonymous requests, so ADR/revenue are usually unavailable — occupancy does not depend on price.",
                        "default": "USD"
                    },
                    "calendarMonths": {
                        "title": "Forward calendar months",
                        "minimum": 1,
                        "maximum": 12,
                        "type": "integer",
                        "description": "How many forward months of availability to request (1-12). Airbnb caps the horizon at ~12 months.",
                        "default": 12
                    },
                    "computeOccupancy": {
                        "title": "Compute occupancy metrics",
                        "type": "boolean",
                        "description": "Derive occupancy_30/60/90/365d, booked-nights, min-nights mode, and booking-pace deltas from the raw calendar. Turn off to emit only the raw days[].",
                        "default": true
                    },
                    "includeProfile": {
                        "title": "Include listing profile record",
                        "type": "boolean",
                        "description": "Also emit a LISTING_PROFILE record (title, room type, lat/lng, rating, review count, capacity) harvested from the listing page. Adds no extra requests (uses the warm-up page).",
                        "default": true
                    },
                    "maxListings": {
                        "title": "Max listings",
                        "minimum": 1,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Hard cap on listings processed in one run (applies to both modes).",
                        "default": 500
                    },
                    "concurrency": {
                        "title": "Concurrency",
                        "minimum": 1,
                        "maximum": 4,
                        "type": "integer",
                        "description": "How many listings to process in parallel. Keep low (1-4) to stay under Airbnb's rate limits.",
                        "default": 3
                    },
                    "logLevel": {
                        "title": "Log level",
                        "enum": [
                            "INFO",
                            "DEBUG"
                        ],
                        "type": "string",
                        "description": "Set DEBUG for verbose troubleshooting output.",
                        "default": "INFO"
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Residential proxy is strongly recommended — Airbnb fingerprints datacenter ASNs upstream of the TLS/header layer. Light runs may work without one.",
                        "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
