# Airbnb Listings Scraper (`rainminer/airbnb-listings-scraper`) Actor

Scrape public Airbnb search results and listing detail pages — titles, full descriptions, prices, ratings, amenities, hosts, and photo galleries. Honest completeness and pagination flags; incomplete rows are never billed.

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

## Pricing

from $0.99 / 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](https://a0.muscache.com/airbnb/static/logos/belo-200x200-4d851c5b0f605ffcbccad5fe514f76e4.png)

### What does Airbnb Listings Scraper do?

**Airbnb Listings Scraper** extracts public vacation-rental data from [Airbnb](https://www.airbnb.com/) **search** and **listing detail** pages. Paste a homes search URL, a city/location query, and/or direct `/rooms/` links, and get structured rows with **full descriptions**, prices, ratings, amenities, host signals, coordinates, and photo galleries.

Input and output field names align with the popular Store Actor `tri_angle/airbnb-scraper` so existing workflows can switch with minimal friction — while this Actor keeps complete descriptions and honest completeness flags.

Use it for short-term rental market research, competitive pricing, inventory monitoring, or feeding listing datasets into spreadsheets, BI tools, and internal apps. Export JSON, CSV, Excel, HTML, or pull results through the Apify API.

### Why this scraper?

Popular Airbnb Actors often return **search cards without descriptions**, break after layout/API churn, or bill for empty/partial rows. This Actor is built around a clear wedge:

- Opens each listing detail page to capture the **complete public description** (not just the search subtitle).
- Sets honest flags: `hasDescription`, `descriptionFetchFailed`, `isComplete`, `hasMoreSearchPages`, `paginationComplete`.
- **Never bills incomplete rows** — only listings with a non-empty description are charged when pay-per-event is enabled.
- Uses Airbnb’s public embedded page data (no login, no user cookies).
- Accepts the same core inputs as `tri_angle/airbnb-scraper` (`locationQueries`, `maxResults`, dates, guests, price filters, locale, currency).

### What Airbnb data can you extract?

| Field                                                          | Description                                           |
| -------------------------------------------------------------- | ----------------------------------------------------- |
| `id` / `listingId` / `url`                                     | Public listing id and canonical `/rooms/` URL         |
| `androidLink` / `iosLink`                                      | Deep links                                            |
| `title`, `seoTitle`, `sharingConfigTitle`, `metaDescription`   | Titles and SEO snippets when exposed                  |
| `description` / `htmlDescription` / `descriptionHtml`          | Full public description (plain + HTML)                |
| `roomType` / `propertyType` / `homeTier` / `personCapacity`    | Stay type and capacity                                |
| `location` / `city` / `coordinates` / `latitude` / `longitude` | Location strings and map coordinates                  |
| `subDescription`                                               | Overview chips (guests / beds / baths)                |
| `amenities`                                                    | Structured amenity groups (`title` + `values[]`)      |
| `amenityTitles`                                                | Flat list of available amenity titles                 |
| `host` / `hostName` / `hostIsSuperhost` / `hostIsVerified`     | Public host signals                                   |
| `rating` / `ratingAverage` / `reviewsCount`                    | Guest rating summary (+ category scores when present) |
| `price` / `priceLabel` / `checkIn` / `checkOut`                | Price/date context                                    |
| `thumbnail` / `imageUrl` / `imageUrls` / `images`              | Primary photo + gallery (absolute `https` URLs)       |
| `highlights`, `houseRules`, `cancellationPolicies`             | Extra listing context when publicly present           |
| `hasDescription`, `isComplete`, `descriptionFetchFailed`       | Completeness flags                                    |
| `searchPage`, `hasMoreSearchPages`, `paginationComplete`       | Honest pagination context                             |
| `timestamp` / `scrapedAt`                                      | Scrape time                                           |

### How to scrape Airbnb listings

1. Open the Actor input tab.
2. Add **location queries** (e.g. `Paris`) and/or Airbnb **homes search** / `/rooms/{id}` URLs.
3. Optionally set check-in/out, guests, price range, locale, and currency — same names as `tri_angle/airbnb-scraper`.
4. Set `maxItems` (or `maxResults`) to control dataset rows **per start URL / location query**. Incomplete rows count toward this limit but are never billed.
5. Run the Actor and download the dataset.

The Actor only extracts **public** listing data. It does not require Airbnb account credentials or session cookies.

### How much does scraping Airbnb cost?

When pay-per-event monetization is enabled, you pay once per **complete** listing saved with a real description. Incomplete rows (blocked/missing description) may appear with flags for debugging but are **not billed**.

Apify adds scheduling, API access, dataset storage, webhooks, and integrations so Airbnb monitoring can run automatically.

### Input example

```json
{
  "locationQueries": ["Paris"],
  "startUrls": [{ "url": "https://www.airbnb.com/s/Paris--France/homes" }],
  "maxItems": 5,
  "checkIn": "2026-09-01",
  "checkOut": "2026-09-05",
  "adults": 2,
  "currency": "USD",
  "locale": "en-US",
  "proxyConfiguration": { "useApifyProxy": false }
}
```

`maxResults` is accepted as an alias of `maxItems`. `enrichUserProfiles` is accepted for compatibility; host fields are taken from the public listing page (no separate profile crawl).

### Output example

```json
{
  "id": "1729686443151285482",
  "listingId": "1729686443151285482",
  "url": "https://www.airbnb.com/rooms/1729686443151285482",
  "androidLink": "airbnb://rooms/1729686443151285482",
  "iosLink": "airbnb://rooms/1729686443151285482",
  "title": "Secret terrace in the heart of historic Marais",
  "description": "Located in charming Le Marais, inside an authentic medieval building...",
  "htmlDescription": "Located in charming Le Marais...",
  "roomType": "Entire home/apt",
  "propertyType": "Entire rental unit in Paris, France",
  "location": "Paris, Île-de-France, France",
  "city": "Paris",
  "coordinates": { "latitude": 48.8559, "longitude": 2.3569 },
  "latitude": 48.8559,
  "longitude": 2.3569,
  "personCapacity": 2,
  "bedrooms": 1,
  "beds": 1,
  "baths": 1,
  "subDescription": {
    "title": "Entire rental unit in Paris, France",
    "items": ["2 guests", "1 bedroom", "1 bed", "1 bath"]
  },
  "amenities": [
    {
      "title": null,
      "values": [
        {
          "title": "Kitchen",
          "subtitle": null,
          "icon": null,
          "available": true
        }
      ]
    }
  ],
  "amenityTitles": ["Kitchen", "Wifi", "Washer"],
  "host": { "name": "Noa", "isSuperhost": false, "isVerified": true },
  "rating": { "guestSatisfaction": 5, "reviewsCount": 1 },
  "price": {
    "label": "$482 for 5 nights",
    "qualifier": "for 5 nights",
    "price": "$482"
  },
  "priceLabel": "$482 for 5 nights",
  "thumbnail": "https://a0.muscache.com/im/pictures/...",
  "imageUrl": "https://a0.muscache.com/im/pictures/...",
  "imageUrls": ["https://a0.muscache.com/im/pictures/..."],
  "images": [
    {
      "imageUrl": "https://a0.muscache.com/im/pictures/...",
      "caption": null,
      "orientation": null
    }
  ],
  "hasDescription": true,
  "descriptionFetchFailed": false,
  "isComplete": true,
  "searchPage": 1,
  "hasMoreSearchPages": true,
  "paginationComplete": false,
  "timestamp": "2026-08-08T10:00:00.000Z",
  "scrapedAt": "2026-08-08T10:00:00.000Z"
}
```

### FAQ

#### Is it legal to scrape Airbnb?

This Actor extracts publicly visible listing pages only. Make sure your use case has a lawful basis and respects Airbnb’s terms and applicable regulations.

#### Does this Actor need login cookies?

No. It scrapes public search and listing pages without account credentials.

#### Why are some rows marked incomplete?

If a detail page is blocked or missing embedded description data, the Actor may still export the search-card fields with `descriptionFetchFailed: true` and `isComplete: false`. Those rows are not billed.

#### Can I scrape cities outside the US site?

Yes. Use the Airbnb domain and search URL for your market (for example `airbnb.co.uk`, `airbnb.fr`). Filters and dates in the URL are kept. Location queries default to `airbnb.com` with your chosen `locale` / `currency`.

#### How does this compare to tri\_angle/airbnb-scraper?

Core inputs (`locationQueries`, `maxResults`, dates, guests, price filters, locale, currency) and the main output keys (`id`, `url`, `title`, `description`, `htmlDescription`, `coordinates`, `images`, `amenities`, `price`, `rating`, `host`, …) are aligned. This Actor additionally returns full descriptions more reliably, flat `amenityTitles`, `imageUrl`/`imageUrls`, and explicit completeness/pagination flags — and never bills hollow rows.

### Image Credit

Image credit: [Airbnb](https://www.airbnb.com/)

# Actor input Schema

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

Airbnb homes search URLs (for example https://www.airbnb.com/s/Paris--France/homes) and/or listing detail URLs (https://www.airbnb.com/rooms/…). Filters already in the URL are kept; optional filter fields below are merged when set.

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

List of location queries to scrape (tri\_angle/airbnb-scraper compatible). Example: London, Paris, Manchester.

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

Maximum number of listings to return per start URL or location query. Takes precedence over maxResults when both are set.

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

Alias of maxItems for tri\_angle/airbnb-scraper compatibility. Ignored when maxItems is set.

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

Date must be in YYYY-MM-DD format with zero-padded month and day, e.g. 2026-09-01.

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

Date must be in YYYY-MM-DD format with zero-padded month and day, e.g. 2026-09-05.

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

Localized results in this locale will be extracted (language and region).

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

Currency that will be extracted for prices.

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

Minimum price filter applied to search URLs / location queries.

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

Maximum price filter applied to search URLs / location queries.

## `minBeds` (type: `integer`):

Minimum beds filter.

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

Minimum bedrooms filter.

## `minBathrooms` (type: `integer`):

Minimum bathrooms filter.

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

Number of adults for search pricing/availability context.

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

Number of children for search pricing/availability context.

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

Number of infants for search pricing/availability context.

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

Number of pets for search pricing/availability context.

## `enrichUserProfiles` (type: `boolean`):

Accepted for tri\_angle/airbnb-scraper compatibility. This Actor already exports public host signals from the listing page and does not perform a separate host-profile crawl.

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

Proxy settings. Defaults to no proxy; enable Apify Proxy (datacenter or residential) if you see blocks in your region.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.airbnb.com/s/Paris--France/homes"
    }
  ],
  "locationQueries": [
    "Paris"
  ],
  "maxItems": 5,
  "locale": "en-US",
  "currency": "USD",
  "enrichUserProfiles": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `overview` (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 = {
    "startUrls": [
        {
            "url": "https://www.airbnb.com/s/Paris--France/homes"
        }
    ],
    "locationQueries": [
        "Paris"
    ],
    "locale": "en-US",
    "currency": "USD",
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("rainminer/airbnb-listings-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/s/Paris--France/homes" }],
    "locationQueries": ["Paris"],
    "locale": "en-US",
    "currency": "USD",
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("rainminer/airbnb-listings-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/s/Paris--France/homes"
    }
  ],
  "locationQueries": [
    "Paris"
  ],
  "locale": "en-US",
  "currency": "USD",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call rainminer/airbnb-listings-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,rainminer/airbnb-listings-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/31NafI6VGXRL2HIeM/builds/6Y5v5kbhZtZNvh04q/openapi.json
