# Airbnb Listings Scraper & Airbnb API: Prices & Calendar Data (`openclawai/airbnb-scraper`) Actor

Airbnb scraper and Airbnb API: Airbnb listings, Airbnb data, Airbnb prices and calendar availability, reviews, hosts and Experiences by search URL, map area, room URL or host ID. Pay per delivered record; empty or failed runs bill no records. JSON for STR analytics and AI agents (MCP).

- **URL**: https://apify.com/openclawai/airbnb-scraper.md
- **Developed by:** [Pika Choo](https://apify.com/openclawai) (community)
- **Categories:** Travel, Real estate, E-commerce
- **Features:** Limited permissions
- **Stats:** 103 total users, 39 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.50 / 1,000 listings

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Airbnb Scraper & Airbnb API — Listings, Prices, Reviews, Calendar & Hosts

Airbnb scraper and Airbnb API for Airbnb listings and Airbnb data: nightly prices, reviews, calendar availability, host portfolios and Experiences for $0.0005 per record ($0.50 per 1,000). Search by Airbnb URL, map bounding box, room URL or host ID and get flat, structured JSON with no API key, no browser and no per-run minimum. Empty and failed runs bill no records.

Built for short-term rental (STR) analytics, dynamic pricing engines, property underwriting and travel market research. Works from the Apify Console, the REST API, the Python and JavaScript clients, and as a tool for AI agents over MCP.

***

### ⚡ Why this Airbnb scraper

- **$0.0005 per record, every mode.** Listings, room details, reviews, calendar months, host portfolio items and Experiences all bill at the same flat rate. 1,000 listings cost about fifty cents.
- **No record charges for empty or failed runs.** You pay only for rows that actually land in the dataset, plus the small actor start fee. Listings that Airbnb repeats across result pages are saved and billed once.
- **Whole searches, not just page one.** Searches page through every result page and split big areas into smaller map areas with the same filters until `maxResults` unique listings are found (up to 5,000).
- **Five ways in.** Search URL, map bounding box, room URL, host ID or Experience place name. Mix and match across runs.
- **Seven modes, one actor.** Listings, room details, reviews, calendar, host portfolios and Experiences without juggling separate tools.
- **Clean, flat output.** One record per row with a `record_type` tag, ready for spreadsheets, BI dashboards, SQL or LLM and RAG pipelines.
- **Residential proxy on by default.** Airbnb fingerprints datacenter IPs hard; the default residential proxy keeps results flowing, with automatic IP rotation and retries on room pages.

***

### 👥 Who uses this

- **STR analytics and revenue managers** tracking supply, nightly rates and occupancy proxies in a market.
- **Dynamic pricing tools** feeding live comparable listings into a pricing engine.
- **Property investors and underwriters** comping a neighborhood before buying or converting a unit.
- **Travel agencies and relocation services** surfacing options for clients in seconds.
- **Market researchers and journalists** measuring shifts in supply, prices, Superhost share and host concentration.
- **AI agents** that need live Airbnb data as a tool call rather than a browser session.

***

### 📦 What you get

Every record carries a `record_type` field: `listing`, `room`, `review`, `calendar`, `host_listing`, `experience`, plus `info` and `error` rows for diagnostics. The main fields per record type:

| Field | Type | Present on | Meaning |
|---|---|---|---|
| `room_id`, `room_url` | string | listing, room, calendar, host_listing | Airbnb room ID and canonical `airbnb.com/rooms/<id>` URL |
| `title` | string | listing | Card title with property type and area, e.g. "Apartment in Lisbon" |
| `name` | string | listing, room, host_listing | Listing name set by the host |
| `room_type` | string | room, host_listing | Entire home/apt, Private room, Shared room or Hotel room |
| `person_capacity` | number | room | Maximum guests |
| `bedrooms`, `beds`, `bathrooms` | number | listing | Layout shown on the search card |
| `rating`, `review_count` | number | listing, room, host_listing | Average rating and number of reviews |
| `is_superhost` | boolean | listing, room, host_listing | Superhost host. A search card shows one badge, so it is left out when the card shows Guest favorite |
| `is_guest_favorite` | boolean | listing, room | Guest favorite listing |
| `free_cancellation` | boolean | listing | Free cancellation offered |
| `price_total` | number | listing, room | Total for the stay: your dates, or 5 nights when the search URL has no dates |
| `price_per_night`, `price_per_night_original` | number | listing (room: `price_per_night`) | Nightly price after and before discounts (`price_total` ÷ nights) |
| `price_unit_qualifier` | string | listing, room | What the price covers, e.g. "for 3 nights" |
| `price_currency_symbol`, `price_currency` | string | listing, room (`price_currency`: room) | Currency symbol of the prices; ISO code of the room quote |
| `latitude`, `longitude` | number | listing, room, experience | Coordinates for mapping and geofencing |
| `host_id`, `host_url` | string | room, host_listing (`host_url`: room) | Host ID and profile URL |
| `description` | string | room | Listing description |
| `images` | array | listing, room, host_listing, experience | Photo URLs |
| `reviews`, `calendar` | array | room, calendar | Embedded reviews and month-by-month availability |
| `review_id`, `rating`, `comment`, `language`, `created_at`, `reviewer_name`, `reviewer_location` | mixed | review | One review per row |
| `experience_id`, `place`, `title`, `duration` | string | experience | Experience ID, the place you searched, title and duration |
| `scraped_at` | string | all | ISO 8601 UTC timestamp |

Fields that Airbnb does not return for a given listing are omitted rather than filled with placeholders, so downstream schemas stay honest.

***

### 📥 Input and modes

Pick a `mode`, then fill in the inputs for that mode. Every field on the form has inline help.

| Mode | Required | Optional |
|---|---|---|
| `search_by_url` | `searchUrl` | `currency`, `language`, `maxResults` |
| `search_by_bbox` | `neLat`, `neLng`, `swLat`, `swLng` | `checkIn`, `checkOut`, `priceMin`, `priceMax`, `placeType`, `amenities`, `freeCancellation`, `zoom`, `currency`, `language`, `maxResults` |
| `room_details` | `roomUrls` | `checkIn`, `checkOut`, `adults`, `currency`, `language` |
| `room_reviews` | `roomUrls` | `language`, `maxResults` |
| `room_calendar` | `roomUrls` | none |
| `host_listings` | `hostId` | `currency`, `language` |
| `experience_search` | `experiencePlace` (or `experiencePlaceId`) | `checkIn`, `checkOut`, `currency`, `language`, `maxResults` |

**Search by URL** is the fastest way to reproduce exactly what you see on airbnb.com: apply dates, price, amenity and map filters in your browser, copy the URL and paste it in. Location segments such as `airbnb.com/s/Paris--France/homes` or `New-York--NY--United-States` are honored. Airbnb shows about 250 listings per search, so for a larger `maxResults` the actor splits the area into smaller map areas with the same filters and keeps going.

**Search by bounding box** takes north-east and south-west coordinates plus optional dates, price range, place type, amenity IDs and a free-cancellation flag. Set both `checkIn` and `checkOut` if you want nightly prices back.

**Room details** accepts up to 100 room URLs per run, fetches them in parallel and returns the listing page: name, description, room type, guest capacity, rating, host ID, coordinates, photos, embedded reviews and calendar, plus a price quote for your dates and guest count. When those dates are not available the listing still ships without the price fields, so you keep name, rating, host and photos.

**Room reviews** and **room calendar** target the same URLs and return one row per review, or one row per room with a month-by-month `calendar` array.

**Host listings** takes the numeric host ID from `airbnb.com/users/show/<id>` and returns every active listing in that host's portfolio with name, room type, rating, review count, Superhost flag and cover photo.

**Experiences** searches Airbnb Experiences for a city or place name such as "Amsterdam".

Example input for a map search:

```json
{
  "mode": "search_by_bbox",
  "neLat": 38.78,
  "neLng": -9.10,
  "swLat": 38.69,
  "swLng": -9.23,
  "checkIn": "2026-06-10",
  "checkOut": "2026-06-15",
  "placeType": "Entire home/apt",
  "currency": "EUR",
  "maxResults": 500
}
```

***

### 📤 Sample output

A `listing` row from a search:

```json
{
  "record_type": "listing",
  "room_id": "12345678",
  "room_url": "https://www.airbnb.com/rooms/12345678",
  "title": "Apartment in Lisbon",
  "name": "Bright 2BR apartment near Alfama",
  "bedrooms": 2,
  "beds": 2,
  "bathrooms": 1,
  "rating": 4.89,
  "review_count": 212,
  "is_superhost": true,
  "is_guest_favorite": false,
  "free_cancellation": false,
  "price_per_night": 138,
  "price_per_night_original": 155,
  "price_total": 690,
  "price_unit_qualifier": "for 5 nights",
  "price_currency_symbol": "€",
  "latitude": 38.7139,
  "longitude": -9.1334,
  "images": ["https://a0.muscache.com/im/pictures/....jpg"],
  "scraped_at": "2026-08-29T05:02:22+00:00"
}
```

A `review` row:

```json
{
  "record_type": "review",
  "room_url": "https://www.airbnb.com/rooms/12345678",
  "review_id": "987654321",
  "rating": 5,
  "comment": "Great location and a very responsive host.",
  "language": "en",
  "created_at": "2026-05-02T10:14:00Z",
  "reviewer_name": "Anna",
  "reviewer_location": "Berlin, Germany",
  "scraped_at": "2026-08-29T05:02:22+00:00"
}
```

Use the dataset tabs (Overview, Hosts, Full Data) in the Console to browse, or export as JSON, CSV, Excel, XML or RSS from the dataset.

***

### 💵 Pricing — pay only for delivered records

| Event | Price | When |
|---|---|---|
| `listing-scraped` | $0.0005 | per search result (URL or map search) |
| `room-details-scraped` | $0.0005 | per full room detail page |
| `review-scraped` | $0.0005 | per review row |
| `calendar-month-scraped` | $0.0005 | per calendar month returned |
| `host-listing-scraped` | $0.0005 | per host portfolio item |
| `experience-scraped` | $0.0005 | per Experience result |

**Worked example.** Scraping 1,000 listings from a Lisbon search URL bills 1,000 × $0.0005 = **$0.50**. Pulling full room details for 200 of them adds 200 × $0.0005 = $0.10. A run that returns zero rows bills zero record events. The only fixed cost is the Apify actor start fee of $0.00005 per GB of memory, about $0.0002 per run at the default 4 GB, so the 1,000-listing run lands at roughly $0.50 all in.

Use `maxResults` to cap large searches and avoid surprises. Apify's free plan credit is enough for several thousand records per month.

***

### ❓ FAQ

#### Does Airbnb have an official API?

Airbnb has no public data API. The partner API is restricted to approved property management software. This actor reads the same public listing, search, review and calendar pages a visitor sees and turns them into structured JSON, so you get Airbnb data without an API key or a partner agreement.

#### How much does it cost to scrape 1,000 Airbnb listings?

$0.50 in record events plus about $0.0002 for the actor start. 10,000 listings cost about $5. Room details, reviews, calendar months and host listings bill at the same $0.0005 per record.

#### Can I get Airbnb prices for specific dates?

Yes. In `search_by_bbox` set `checkIn` and `checkOut` to receive nightly and total prices in your chosen `currency`. In `room_details` set the dates and `adults` to get a live quote for that exact stay. `search_by_url` picks dates up from the URL you paste.

#### How fast is it and what are the limits?

Searches page through every result page Airbnb shows (about 250 listings per search) and, when you ask for more, split the area into smaller map areas with the same filters until `maxResults` unique listings are found (up to 5,000) or the area runs out of listings. Room details accept up to 100 URLs per run and fetch 8 pages in parallel with up to 5 retries and a fresh residential IP per retry. A 100-listing search typically finishes in well under a minute.

#### Is scraping Airbnb legal?

Scraping publicly available data is generally lawful in most jurisdictions, but you are responsible for how you use it. Do not collect personal data beyond what you need, respect Airbnb's terms and local privacy law (GDPR, CCPA), and consult a lawyer for commercial use at scale.

#### Which output formats can I export?

JSON, CSV, Excel, XML, HTML table and RSS, straight from the dataset in the Console or through the API. Every row is flat, so CSV opens cleanly in Excel or Google Sheets.

#### How does this compare to other Airbnb scrapers?

Most alternatives charge per result with different prices per mode, or bill by compute time so a blocked run still costs money. This actor bills $0.0005 for every record type, bills no records for empty or failed runs, and handles listings, room details, reviews, calendar, host portfolios and Experiences in one tool.

#### Why did some room URLs come back as `error` rows?

Airbnb applies aggressive anti-bot checks to room pages. When a page is blocked after all retries the actor returns the successful rows, an `info` row summarizing how many succeeded, and one `error` row per failed URL. Retry the failed URLs a few minutes later; failed rows are not billed.

***

### 🤖 Use with AI agents and MCP

Add the actor as a tool in Claude, Cursor, VS Code, or any MCP-compatible agent through the Apify MCP server:

```
https://mcp.apify.com/?tools=fetch-actor-details,openclawai/airbnb-scraper
```

Your agent can then call `openclawai/airbnb-scraper` with the same input JSON shown above and read the dataset back as tool output. A step-by-step guide with prompts and agent recipes is at [datapika.com/actors/airbnb-scraper](https://datapika.com/actors/airbnb-scraper).

***

### 🔌 Integrations

- **REST API**: `POST https://api.apify.com/v2/acts/openclawai~airbnb-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN` with the input JSON as the body.
- **Python**: `apify-client` package, `client.actor("openclawai/airbnb-scraper").call(run_input={...})`.
- **JavaScript / TypeScript**: `apify-client` package, `client.actor("openclawai/airbnb-scraper").call({...})`.
- **No-code**: Apify integrations for Zapier, Make, n8n, Google Sheets, Slack and webhooks work out of the box.
- **Scheduling**: run on a cron schedule from the Console to track prices and availability over time.

***

### ⚠️ Notes

- For bounding-box search to return prices, set both `checkIn` and `checkOut`.
- Airbnb rate-limits datacenter IPs aggressively. Leave the default residential proxy on.
- Amenity IDs for `search_by_bbox` are the numeric values in Airbnb search URLs (`amenities%5B%5D=4`). Apply the amenity filter on airbnb.com and read the IDs from the URL.
- Use `maxResults` to cap large queries and avoid billing surprises.

***

### ⚖️ Legal and ethics

This actor collects only publicly visible information and is intended for market research, analytics and personal use. It does not bypass logins or access private data. You are responsible for complying with Airbnb's terms of service and with applicable data protection laws when storing or redistributing scraped data, especially reviewer names and host details.

***

### 📝 Changelog

Recent fixes: searches now page through every result page and split big areas to reach `maxResults` (search by URL used to stop at the first 40 listings), listings repeated across pages are saved and billed once, listing rows carry coordinates and true nightly prices (search cards show the stay total), host portfolio rows carry name, rating and photo, and room details carry name, description, host ID and a numeric price quote. Earlier: search by URL honors the location in the URL path, room details retry up to 5 times with a fresh IP and detect challenge pages, batch runs return partial results plus an `info` summary instead of failing, and unavailable dates return the listing with `price_unavailable_reason` instead of an error. Full version history ships with the actor as `CHANGELOG.md`.

# Changelog

This Actor's version history is a separate document: https://apify.com/openclawai/airbnb-scraper/changelog.md

# Actor input Schema

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

Which scrape to run. Each mode uses different inputs and bills its own per-record event ($0.0005 per record in every mode). See the readme for the inputs each mode needs.

## `searchUrl` (type: `string`):

Used by mode = search_by_url. Paste a full airbnb.com/s/… URL with your dates, price, amenity, and map filters already applied. The easiest way: filter on airbnb.com in your browser, then copy the URL. Without dates in the URL, Airbnb prices a 5-night stay.

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

Check-in date. Required for bbox search to receive prices, and for room_details to receive a quote. Format: YYYY-MM-DD.

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

Check-out date. Same rules as check-in.

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

Number of adult guests for the price quote.

## `neLat` (type: `number`):

Bounding box — north-east latitude. Used by mode = search_by_bbox.

## `neLng` (type: `number`):

Bounding box — north-east longitude.

## `swLat` (type: `number`):

Bounding box — south-west latitude.

## `swLng` (type: `number`):

Bounding box — south-west longitude.

## `zoom` (type: `integer`):

Map zoom level (1–20). Higher = tighter results.

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

Minimum nightly price filter (in `currency`). 0 = no minimum.

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

Maximum nightly price filter (in `currency`). 0 = no maximum.

## `placeType` (type: `string`):

Filter by listing type. Leave as Any to return all.

## `amenities` (type: `array`):

Airbnb amenity IDs to filter by. Example: \[4, 7] = WiFi + Pool. Find IDs by applying an amenity filter on airbnb.com and reading the amenities\[]= values from the URL.

## `freeCancellation` (type: `boolean`):

Only return listings with flexible/free cancellation.

## `roomUrls` (type: `array`):

List of airbnb.com/rooms/<id> URLs. Used by modes: room_details, room_reviews, room_calendar. Max 100 per run.

## `hostId` (type: `string`):

Numeric Airbnb host/user ID. Used by mode = host_listings. Find it in the host's profile URL: airbnb.com/users/show/<id>.

## `experiencePlaceId` (type: `string`):

Optional raw Google place ID for Experiences search. Prefer `experiencePlace` with a plain city name.

## `experiencePlace` (type: `string`):

Used by mode = experience_search. A city or place name, e.g. "Amsterdam" or "Gouda, Netherlands". This is what Airbnb's own Experiences search takes.

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

ISO currency code for price data. Examples: USD, EUR, GBP, JPY, MXN.

## `language` (type: `string`):

ISO 2-letter language code. Examples: en, es, fr, de, pt, ja, zh.

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

Cap on listings returned (search modes) or reviews fetched per room (review mode). Searches page through every result page and split big areas into smaller map areas with the same filters until this many unique listings are found. Prevents billing surprises.

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

Proxy settings. Residential proxies recommended — Airbnb fingerprints datacenter IPs aggressively.

## Actor input object example

```json
{
  "mode": "search_by_url",
  "searchUrl": "https://www.airbnb.com/s/Lisbon--Portugal/homes?checkin=2026-06-10&checkout=2026-06-15&adults=2",
  "checkIn": "2026-06-10",
  "checkOut": "2026-06-15",
  "adults": 2,
  "neLat": 38.78,
  "neLng": -9.1,
  "swLat": 38.69,
  "swLng": -9.23,
  "zoom": 12,
  "priceMin": 0,
  "priceMax": 0,
  "placeType": "",
  "freeCancellation": false,
  "hostId": "12345678",
  "experiencePlace": "Amsterdam",
  "currency": "USD",
  "language": "en",
  "maxResults": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `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 = {
    "searchUrl": "https://www.airbnb.com/s/Lisbon--Portugal/homes"
};

// Run the Actor and wait for it to finish
const run = await client.actor("openclawai/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 = { "searchUrl": "https://www.airbnb.com/s/Lisbon--Portugal/homes" }

# Run the Actor and wait for it to finish
run = client.actor("openclawai/airbnb-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 '{
  "searchUrl": "https://www.airbnb.com/s/Lisbon--Portugal/homes"
}' |
apify call openclawai/airbnb-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,openclawai/airbnb-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/JvX0T5jm5g4Y35xkT/builds/rqRCC0x3fOIC5dC4v/openapi.json
