# Airbnb Availability Scraper — Calendar & Open Dates (`thenetaji/airbnb-availability-scraper`) Actor

Export an Airbnb stay's booking calendar night by night. Paste one room link or a list and get up to a year of dates, each marked free or taken, with whether a stay can start or end on it and the minimum and maximum nights the host allows.

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

## Pricing

from $0.26 / 1,000 results

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

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

## What's an Apify Actor?

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

## How to integrate an Actor?

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

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

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

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

# README

## Airbnb Availability Scraper

The Actor exports an Airbnb stay's booking calendar, one row per night: whether the date is free,
whether it can actually be booked, whether a stay can start or end on it, and the minimum and
maximum nights the host allows. Up to twelve months are returned for each stay.

**This Actor returns availability, not prices.** Airbnb does not publish nightly rates on its
calendar to anyone who is not signed in, so no price column exists here. The **Airbnb Search
Scraper** returns a total price when given check-in and check-out dates, and that is where pricing
for a specific stay length comes from.

### Accepted input

`stay_ids` is required and takes one or more stays. Room page links and bare numeric stay IDs are
both accepted, and the two may be mixed in one list. A link is reduced to its `/rooms/<id>`
segment, so the tracking query string Airbnb appends to shared links can be left in place.

`months` sets how many months to return, from 1 to 12, and defaults to 12. Unlike the paging limits
on the other Airbnb Actors, this one carries no speed penalty: the whole window arrives in a single
request per stay, so twelve months take no longer to fetch than one and only affect how many rows
are written.

`calendarStart` sets which month to begin from and defaults to the current month. Airbnb's calendar
is month-granular — any date is accepted, and the whole month containing it is returned rather than
a window beginning on that day.

```json
{
  "stay_ids": [
    "https://www.airbnb.com/rooms/4518031",
    "1348596009084608060"
  ],
  "months": 12,
  "calendarStart": "2026-10-01"
}
```

### Response fields

Every row carries `stay_id`, `stay_url`, `date`, `available`, `bookable`, `available_for_checkin`,
`available_for_checkout`, `min_nights`, and `max_nights`.

`available` and `bookable` are not the same field twice. A night can be free while still being
impossible to book, because the stay it would form falls short of the host's minimum-nights rule.
Filtering on `available` alone will return dates that cannot be reserved.

`available_for_checkin` and `available_for_checkout` mark which nights can begin or end a stay.
Hosts commonly allow arrivals on some days of the week and not others, and a night that is free for
the middle of a stay is not necessarily one a booking can start on.

`min_nights` and `max_nights` are the host's stay-length rules for a booking beginning on that
night, and they vary across the calendar rather than being one setting for the listing.

```json
{
  "stay_id": "4518031",
  "stay_url": "https://www.airbnb.com/rooms/4518031",
  "date": "2026-10-14",
  "available": true,
  "bookable": true,
  "available_for_checkin": true,
  "available_for_checkout": true,
  "min_nights": 1,
  "max_nights": 7
}
```

### Why a stay can return nothing

Airbnb does not answer an unknown stay ID with a 404. It returns an ordinary response with an empty
calendar, and a stay that has been delisted or taken off the market behaves the same way. Nothing in
the response separates the two cases.

The Actor treats that as the real answer it is: the stay is logged as having no calendar and
skipped, and no rows are written. It is not reported as an error, because a listing being gone is a
legitimate outcome rather than a failure of the run.

The most common cause of an unexpected empty result is a `propertyId` used in place of a stay ID.
Both appear on Airbnb search results, both are long numbers, and only the stay ID resolves. The `id`
field returned by the Airbnb Search Scraper is always the correct one.

### How far ahead the calendar goes

Airbnb publishes a limited booking window and it is not the same for every listing. Asking for
twelve months does not guarantee twelve months back — a stay whose host has opened fewer will return
fewer, with no error and no indication in the data itself.

Each stay is therefore logged with the window that actually came back, and the first and last dates
present in the rows are the authoritative answer to how far the calendar reaches. The `months` input
is a ceiling, not a promise.

### Behaviour on partial results

A list input is processed to the end regardless of individual failures. A stay that cannot be
fetched, whether removed or erroring upstream, is logged and skipped while the remainder continue,
so one dead link in a list of fifty does not cost the other forty-nine.

Rows are therefore not guaranteed to cover every stay in the input list. Matching on the returned
`stay_id` is reliable; matching on position is not.

### Related Actors

The **Airbnb Search Scraper** finds stays by destination when no IDs are held, and its `id` output
feeds directly into this Actor's `stay_ids`. It is also where prices come from, given check-in and
check-out dates.

The **Airbnb Listing Scraper** returns the stay itself — description, amenities, host, and review
scores.

The **Airbnb Reviews Scraper** returns the individual guest reviews for the same stay.

# Actor input Schema

## `stay_ids` (type: `array`):

One or more stays to fetch. Paste room page links, or the numeric stay IDs the search scraper returns — both work, and you can mix them.

## `months` (type: `integer`):

How many months of the calendar to return for each stay, counting from the starting month. All twelve cost the same as one, so there is no reason to ask for fewer unless you want a smaller dataset.

## `calendarStart` (type: `string`):

Which month the calendar should start from. Any date works — the whole month containing it is returned, not a window beginning on that day. Leave empty to start from the current month.

## Actor input object example

```json
{
  "stay_ids": [
    "4518031"
  ],
  "months": 12,
  "calendarStart": "2026-10-01"
}
```

# Actor output Schema

## `dataset` (type: `string`):

All records scraped by this run

# 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 = {
    "stay_ids": [
        "https://www.airbnb.com/rooms/4518031"
    ],
    "months": 12
};

// Run the Actor and wait for it to finish
const run = await client.actor("thenetaji/airbnb-availability-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 = {
    "stay_ids": ["https://www.airbnb.com/rooms/4518031"],
    "months": 12,
}

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

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

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

```

## CLI example

```bash
echo '{
  "stay_ids": [
    "https://www.airbnb.com/rooms/4518031"
  ],
  "months": 12
}' |
apify call thenetaji/airbnb-availability-scraper --silent --output-dataset

```

## MCP server setup

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

```

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

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/x4XVbeFKdaX0kvbaw/builds/8r4FIDxac0y96d0rL/openapi.json
