# Airbnb Scraper (`mlg14/airbnb-rooms-scraper`) Actor

Scrape public Airbnb room URLs for property details, ratings, amenities, house rules, photos, host details, and dated booking prices.

- **URL**: https://apify.com/mlg14/airbnb-rooms-scraper.md
- **Developed by:** [MLG Data](https://apify.com/mlg14) (community)
- **Categories:** Travel, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 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.

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

Scrape public Airbnb room pages from direct listing URLs and export Airbnb property data to CSV, JSON, or a spreadsheet. This Airbnb data extraction service is a practical API alternative for collecting accommodation details, ratings, amenities, photos, house rules, and dated booking prices from rooms you already know.

Each room produces one record. Provide a list of URLs, optionally add travel dates and guest counts, and set a maximum number of results. The output keeps stable top-level field names so you can compare repeated runs or join records by `roomId`.

### What data can you extract from Airbnb?

The dataset contains one row per successfully read public room page. Arrays such as amenities and house rules retain their natural groups; the main identifiers, ratings, location, host summary, and booking fields remain at the top level.

| Field | Description | Example |
| --- | --- | --- |
| `roomId` | Numeric listing identifier, stored as text to preserve long IDs | `53997462` |
| `url` | Canonical public room link | `https://www.airbnb.com/rooms/53997462` |
| `title` | Listing headline | `Cozy apartment at historical center` |
| `description` | Public listing description with markup removed | `Experience the urban city life...` |
| `propertyType` | Displayed accommodation type | `Entire condo` |
| `roomType` | Underlying room category | `ENTIRE_HOME` |
| `personCapacity` | Maximum guest count reported for the room | `3` |
| `overview` | Short property summary | `Entire condo in Thessaloniki, Greece` |
| `overviewItems` | Guest, bedroom, bed, and bath summary labels | `["3 guests", "1 bedroom"]` |
| `location` | Public city or area label | `Thessaloniki, Greece` |
| `latitude` | Public listing latitude, when shown | `40.6298` |
| `longitude` | Public listing longitude, when shown | `22.9497` |
| `isExactLocation` | Whether the listing marks its map position exact | `true` |
| `rating` | Overall guest rating | `4.95` |
| `reviewsCount` | Number of guest reviews | `75` |
| `ratingAccuracy` | Accuracy rating | `4.89` |
| `ratingCheckIn` | Check-in rating | `4.97` |
| `ratingCleanliness` | Cleanliness rating | `4.92` |
| `ratingCommunication` | Communication rating | `5.0` |
| `ratingLocation` | Location rating | `4.99` |
| `ratingValue` | Value rating | `4.93` |
| `isGuestFavorite` | Whether a guest favorite designation is shown | `true` |
| `hostId` | Public host profile identifier | `437479978` |
| `hostName` | Public host display name | A name shown on the room page |
| `hostProfileUrl` | Public host profile link | A profile URL |
| `hostPhotoUrl` | Public host profile image link | An image URL |
| `hostIsSuperhost` | Whether the host is marked as a Superhost | `true` |
| `hostIsVerified` | Whether a verified marker is shown | `true` |
| `hostYearsHosting` | Completed years hosting, when available | `4` |
| `hostResponseRate` | Displayed response-rate text | `Response rate: 100%` |
| `hostResponseTime` | Displayed response-time text | `Responds within an hour` |
| `amenities` | Groups of amenities; each value has title, subtitle, icon, and availability | Bathroom → Hair dryer |
| `highlights` | Listing highlights with title, subtitle, icon, and type | `Self check-in` |
| `houseRules` | Groups of check-in, stay, and checkout rules | `No smoking` |
| `safetyAndProperty` | Groups of public safety and property details | `Smoke alarm installed` |
| `sleepingArrangements` | Rooms and their bed descriptions | Bedroom → 1 double bed |
| `images` | Listing image URLs with any available captions | Image URL and caption |
| `imageUrl` | Primary listing image link | An image URL |
| `checkIn` | Requested arrival date | `2026-11-10` |
| `checkOut` | Requested departure date | `2026-11-13` |
| `locale` | Requested output language | `en` |
| `currency` | Requested booking currency | `USD` |
| `available` | Availability for supplied dates, when returned | `true` |
| `priceDisplay` | Booking total with its qualifier | `$216 for 3 nights` |
| `priceTotal` | Displayed booking total as text | `$216` |
| `priceDetails` | Displayed booking price line items | `3 nights x $71.76` |

`priceTotal` is a display string. It preserves the currency symbol and formatting visible for the requested currency rather than guessing a numeric value. `priceDetails` can contain nightly charges or other lines that the booking section exposes. A missing value means that the room page or booking response did not show that field; it does not mean zero.

### How to scrape Airbnb

1. Copy direct public room URLs. A room link has the form `https://www.airbnb.com/rooms/53997462`. You can paste several links into `startUrls` or supply numeric room IDs.
2. Add both `checkIn` and `checkOut` if you need a price or availability for a specific stay. Set guest counts and currency to match your comparison.
3. Set `maxItems` to cap the dataset. Leaving it at zero processes every distinct valid room in the input list.
4. Run the actor, then open the dataset to preview records or download them in JSON, CSV, or spreadsheet form.

The actor deduplicates room IDs before making requests. A repeated URL, a URL containing tracking parameters, and the same numeric ID all refer to one room record. Invalid links are skipped. A room removed from public view is logged as a failed room while the remaining URLs continue.

### Input

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `startUrls` | List of URLs or IDs | Required | Public room links or numeric room IDs. |
| `checkIn` | Date | Empty | Arrival date in `YYYY-MM-DD` format. Requires `checkOut`. |
| `checkOut` | Date | Empty | Departure date after `checkIn`. Requires `checkIn`. |
| `adults` | Integer | `2` | Adult guests for dated booking details. |
| `children` | Integer | `0` | Child guests for dated booking details. |
| `infants` | Integer | `0` | Infant guests for dated booking details. |
| `pets` | Integer | `0` | Pets for dated booking details. |
| `locale` | Text | `en` | Language for listing text; examples include `en`, `fr`, `de`, `es`, and `tr`. |
| `currency` | Text | `USD` | Three-letter booking currency code such as `USD`, `EUR`, `GBP`, or `TRY`. |
| `maxItems` | Integer | `0` | Maximum records to save; zero means no total cap. |
| `proxyConfiguration` | Object | Configured proxy | Connection settings for public room requests. |

Example input for a three-night stay:

```json
{
  "startUrls": [
    { "url": "https://www.airbnb.com/rooms/53997462" },
    { "url": "https://www.airbnb.com/rooms/668146487515150072" }
  ],
  "checkIn": "2026-11-10",
  "checkOut": "2026-11-13",
  "adults": 2,
  "locale": "en",
  "currency": "USD",
  "maxItems": 2
}
```

Use dates in the future for live booking comparisons. The same room may show a different total with a different stay length, guest mix, or currency. A price can change between runs as availability and booking terms change.

### Output example

This is a shortened record from a successful dated run. Longer arrays and the full public description are omitted for readability; the shown values come from the collected item.

```json
{
  "roomId": "53997462",
  "url": "https://www.airbnb.com/rooms/53997462",
  "title": "Cozy apartment at historical center",
  "propertyType": "Entire condo",
  "roomType": "ENTIRE_HOME",
  "personCapacity": 3,
  "location": "Thessaloniki, Greece",
  "latitude": 40.6298,
  "longitude": 22.9497,
  "rating": 4.95,
  "reviewsCount": 75,
  "hostIsSuperhost": true,
  "checkIn": "2026-11-10",
  "checkOut": "2026-11-13",
  "currency": "USD",
  "available": true,
  "priceDisplay": "$216 for 3 nights",
  "priceTotal": "$216",
  "priceDetails": [
    { "description": "3 nights x $71.76", "price": "$215.28" }
  ]
}
```

The total displayed in the booking section may be rounded while individual line items keep cents. Treat the displayed total as the amount presented for that stay, and retain line items when auditing a quote. Price fields can be empty even when the listing details are complete.

### Use cases

- **Accommodation comparison:** Compare known rooms by capacity, property type, rating, amenity coverage, and a dated displayed total. The stable room ID makes repeated comparisons straightforward.
- **Hospitality research:** Measure which amenities and house rules appear across a selected portfolio of public listings in a city or neighborhood. Supply the URLs from your own list.
- **Travel planning:** Review sleeping arrangements, guest capacity, check-in rules, and safety details before building a shortlist for a group trip.
- **Listing monitoring:** Run the same URL list on a schedule and compare titles, descriptions, ratings, review counts, and photos over time.
- **Pricing research:** Hold dates, guest count, and currency constant across a group of rooms, then inspect displayed totals and missing quotes separately.
- **Quality checks:** Confirm that a curated directory still points to public rooms and that core fields such as title, property type, and image are present.

This actor starts from direct room URLs. It does not discover rooms from a city name. If your workflow begins with a destination, gather the room URLs first, then pass that list as `startUrls`.

### How much does it cost to scrape Airbnb?

The configured result price is **$0.001 per saved room**, or **$1 per 1,000 saved rooms**. A 35-room dataset corresponds to $0.035 in result charges. A 500-room dataset corresponds to $0.50, and a 5,000-room dataset corresponds to $5.00. Platform usage is included in the result price for a priced run; actual private test usage can appear separately in run details.

You are charged for saved results, not for invalid input URLs that produce no row. A room that fails to load is logged and skipped. Setting `maxItems` keeps large input lists within a chosen output count. Dated runs make an extra booking request for each room and can take longer, but the per-result price remains the same.

The price above is the current configuration. Check the run screen before a large production job because published pricing can be updated. The output count is the simplest way to estimate result charges: multiply saved rooms by $0.001.

### Tips for best results

Provide direct room links, preferably from a recent list. Rooms can be removed, paused, or made private after a URL was collected. A current list reduces failed requests and makes any missing row easier to investigate.

Use a consistent date pair for comparisons. Without dates, the actor focuses on stable listing details and leaves price and availability fields empty. With dates, it asks the booking section for that stay. A three-night stay and a seven-night stay may use different rates or discounts. Guest counts can also change eligibility or price.

Choose one currency across a run. A visible amount such as `$216` is a formatted string, and the same symbol can be used by several currencies. Keep the `currency` field alongside `priceTotal` when combining datasets. Do not compare price strings until you have separated currency and stay length.

Review `available` together with `priceTotal`. In a 35-room dated validation run, 9 rooms returned displayed totals. The other rooms still produced complete listing records, but did not yield a booking total for those dates. A blank total must not be interpreted as a free stay.

Use `maxItems` when testing a large URL list. Start with a few known rooms to confirm dates and currency, then expand the list. If you run the same IDs repeatedly, join snapshots on `roomId` and retain your collection timestamp outside the row or in your downstream store.

### Limits

Only publicly accessible room pages are supported. The actor does not sign in, bypass a private listing, or collect private account information. It does not return individual review text, a full availability calendar, or host profile enrichment. Host fields are the public summary shown on the room page.

A room page can omit an amenity, category rating, exact map position, host response statistic, photo caption, or booking total. The output uses an empty value where the public page does not provide one. Ratings and review counts are snapshots, so they may differ on a later run.

Price and availability depend on a separate booking section. A requested room may be unavailable for the dates, may not offer a quote to an anonymous visitor, or may be awaiting a site-side update. The price query is made only when both dates are set. No historical rate is inferred from a current quote.

The site can redirect a visitor to a regional domain and can change the shape of its embedded listing data or booking query. The actor follows a regional handoff when it can read the same public room there. If the page layout changes, extraction may need an update. The actor logs per-room failures and continues with other URLs rather than substituting incomplete placeholder rows.

The dataset is capped by your `maxItems` setting and the URLs you supply. There is no search pagination or destination slicing because the input is a known set of rooms. A single URL yields at most one row. Long numeric IDs are kept as text to prevent loss of digits in spreadsheet software.

### Use with automated workflows

The input and output fields are descriptive enough to be used from a scheduler, script, or connected workflow. Two example requests are:

1. “Collect these 40 room URLs, use November 10–13 with two adults in USD, and give me a table of title, capacity, rating, amenities, and displayed total.”
2. “Run my saved room list every week and flag rooms whose review count, title, house rules, or main image changed.”

For a comparison, keep both the room ID and the requested dates with each result. For monitoring, save each run separately before comparing snapshots. Missing prices should be tracked as missing values; they may reflect availability or a booking response that omitted a quote.

### FAQ

#### Is scraping these room pages legal?

The actor reads public room information. Whether your use is permitted depends on applicable law, the site's terms, and how you handle the resulting data. Respect privacy and data-protection rules, especially when working with public host profile details. Do not use this actor to collect private or login-only information.

#### Do I need to configure a proxy?

The default input uses the configured proxy settings. Most users can leave them as provided. If a room fails because the site redirects or blocks a connection, inspect the run log and retry with an appropriate proxy configuration.

#### How fast is a run?

Speed varies with room count, page response time, regional redirects, and whether you requested booking prices. A validation run of 35 rooms with dates completed in about two minutes. Smaller lists are usually quicker, while blocked or slow pages can take longer.

#### Can I schedule or monitor repeated runs?

Yes. Save a stable input list and schedule it at your preferred interval. Compare successive datasets by `roomId`. Watch the run status and the number of saved rooms; a sudden drop can indicate removed listings, connection issues, or a site change.

#### Can I export to a spreadsheet?

Yes. Download the dataset in CSV or spreadsheet format, or send records to a connected spreadsheet workflow. Arrays such as amenities and images may be serialized in a single cell, so JSON is preferable when you need every nested value.

#### Why is a field empty?

The public page or booking response did not provide it for that room and request. Category ratings are absent on some listings. Prices can be unavailable without dates or for a stay that cannot be quoted. Inspect the room directly if a particular value is critical.

#### Can I search a city with this actor?

No. Supply direct room URLs or room IDs. This keeps one input room mapped to at most one output row and avoids unexpected search ranking, pagination, or geographic filtering.

### Integrations

Use the dataset through its API, a webhook, a scheduler, or a connected automation service. You can send room records to a database, dashboard, spreadsheet, or monitoring process. Keep dates and currency alongside booking totals, and use `roomId` as the stable key for joins and updates.

### Support

Open an issue on the Issues tab; we reply within 24h and add fields on request. Include a public room URL, the relevant input options, and the field you expected so the issue can be reproduced.

# Actor input Schema

## `startUrls` (type: `array`):

Direct public room URLs or numeric room IDs. Paste one or more rooms to extract.

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

Arrival date in YYYY-MM-DD. Set both dates to request availability and a price.

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

Departure date in YYYY-MM-DD; must be after check-in.

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

Number of adult guests for dated booking details.

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

Number of children for dated booking details.

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

Number of infants for dated booking details.

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

Number of pets for dated booking details.

## `locale` (type: `string`):

Language used for listing text, such as en, fr, de, es, or tr.

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

Three-letter currency code for booking prices, such as USD, EUR, GBP, or TRY.

## `maxItems` (type: `integer`):

Maximum number of room records to save. Set 0 for no limit.

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

Proxy settings for room requests. The default uses the configured proxy.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.airbnb.com/rooms/53997462"
    },
    {
      "url": "https://www.airbnb.com/rooms/668146487515150072"
    }
  ],
  "adults": 2,
  "children": 0,
  "infants": 0,
  "pets": 0,
  "locale": "en",
  "currency": "USD",
  "maxItems": 0,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `rooms` (type: `string`):

All room records in the default dataset.

# 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 = {
    "startUrls": [
        {
            "url": "https://www.airbnb.com/rooms/53997462"
        },
        {
            "url": "https://www.airbnb.com/rooms/668146487515150072"
        }
    ],
    "locale": "en",
    "currency": "USD"
};

// Run the Actor and wait for it to finish
const run = await client.actor("mlg14/airbnb-rooms-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 = {
    "startUrls": [
        { "url": "https://www.airbnb.com/rooms/53997462" },
        { "url": "https://www.airbnb.com/rooms/668146487515150072" },
    ],
    "locale": "en",
    "currency": "USD",
}

# Run the Actor and wait for it to finish
run = client.actor("mlg14/airbnb-rooms-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 '{
  "startUrls": [
    {
      "url": "https://www.airbnb.com/rooms/53997462"
    },
    {
      "url": "https://www.airbnb.com/rooms/668146487515150072"
    }
  ],
  "locale": "en",
  "currency": "USD"
}' |
apify call mlg14/airbnb-rooms-scraper --silent --output-dataset

```

## MCP server setup

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