# Airbnb Listings Scraper - Prices, Ratings & Hosts (`dami_studio/airbnb-listings-scraper`) Actor

Scrape Airbnb search results for any location with your own dates and guest count. Get listing ID, name, room type, price, rating, review count, host and direct URL in clean JSON. No Airbnb account, no API key. Built for short-let market research, revenue benchmarking and competitor tracking.

- **URL**: https://apify.com/dami\_studio/airbnb-listings-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** Travel, Real estate, E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.40 / 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.
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 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 Listings Scraper

Collect a bounded set of publicly displayed Airbnb search listings without login. The actor requests the public search page directly, follows Airbnb's ordinary country-domain handoff when present, and extracts the structured listing data returned in that page.

### Pricing

**$0.40 per 1,000 listings** ($0.0004 each), with no run-start fee. Flat rate — no volume tiers, no plan gates — and you are charged only for listings actually returned.

The `listing` event is charged once per genuine row, and only after that row has been written to the dataset. Samples, diagnostics, duplicates, empty results, and blocked responses are never charged, so a run that finds nothing costs nothing at all.

### Behavior

- Direct HTTP is always tried first. It does not silently use a proxy.
- Direct HTTP is the only transport. A blocked page returns an uncharged diagnostic and never starts a residential proxy.
- Each location is capped at 20 output rows; at most five locations may be supplied per run.
- The overall wall-clock deadline is capped at 180 seconds.
- A genuine listing is written before its `listing` result event is charged. Samples, diagnostics, duplicates, empty results, and blocked responses are not charged.
- Empty input returns one explicit sample row and makes no network request or charge.

### Input

| Field | Type | Default | Notes |
|---|---|---|---|
| `locations` | string array | none | City, region, or destination strings, such as `Toronto, Ontario, Canada`. Up to five per run. Leave empty for an uncharged sample row. |
| `checkIn` | string | none | Optional `YYYY-MM-DD` check-in date. |
| `checkOut` | string | none | Optional `YYYY-MM-DD` check-out date; must be after check-in when both are supplied. |
| `adults` | integer | `2` | Adult guest count sent to the public search page, from 1 to 16. |
| `maxItemsPerLocation` | integer | `20` | Hard cap on genuine listing rows saved for each location, from 1 to 20. |
| `deadlineSecs` | integer | `90` | Hard wall-clock budget for all locations, from 15 to 180 seconds. |

`checkIn` and `checkOut` must be supplied together — one without the other is rejected as `BAD_INPUT` rather than silently ignored. Supplying dates lets Airbnb return date-specific displayed prices instead of generic nightly rates.

### Output

Each genuine row is `ok: true`, `recordType: "listing"`, and carries:

`listingId`, `listingUrl`, `name`, `propertyType`, `rating`, `reviewCount`, `price`, `priceAmount` (the numeric value parsed out of the displayed string), `currency`, `priceQualifier` (for example `total` or `night`), `priceAccessibilityLabel`, `badges[]` (such as Guest favourite), `spaceDetails[]` (the short bed/guest/bath lines Airbnb prints under the title), `latitude`, `longitude`, `photoUrls[]` (up to five public image URLs), plus the search inputs that produced the row — `searchLocation`, `checkIn`, `checkOut`, `adults` — and `source`.

Prices are displayed search-page values, not a booking quote or availability guarantee. Fields Airbnb does not publish for a given listing come back as `null` or an empty array rather than being dropped.

### Diagnostics

Problems exit successfully as an uncharged row with `ok: false`, `recordType: "diagnostic"`, and a `code`:

| Code | Meaning |
|---|---|
| `BAD_INPUT` | Dates supplied incorrectly — only one of check-in/check-out, or checkout on or before check-in. |
| `NOT_FOUND` | The public search page returned 404 for that location. |
| `BLOCKED` | Airbnb returned 403/429, a captcha, or an access wall. |
| `NETWORK` | The request timed out or the connection failed. |
| `TARGET_ERROR` | The page loaded but the embedded listing payload was missing or in an unrecognised shape. |
| `NO_RESULTS` | The search resolved but contained no new genuine listings within the configured bounds. |
| `DEADLINE` | The wall-clock budget ran out before this location was reached. |

One failing location does not stop the others; each is reported on its own row.

### Limitations

Airbnb can vary, block, or remove public search data by locale and request context. This actor does not log in, bypass CAPTCHA, collect private data, or promise availability. It returns an uncharged diagnostic when public data is unavailable instead of inventing listings or billing empty output.

### Example

```json
{
  "locations": ["Toronto, Ontario, Canada"],
  "checkIn": "2026-08-10",
  "checkOut": "2026-08-12",
  "adults": 2,
  "maxItemsPerLocation": 20,
  "deadlineSecs": 90
}
```

# Actor input Schema

## `locations` (type: `array`):

City, region, or destination strings for public Airbnb stays search. Leave empty for an uncharged sample row.

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

Optional YYYY-MM-DD check-in date. Use both dates to receive date-specific displayed prices.

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

Optional YYYY-MM-DD check-out date. Must be after check-in when both are supplied.

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

Number of adult guests sent to the public search page.

## `maxItemsPerLocation` (type: `integer`):

Hard cap on genuine listing rows saved for each location.

## `deadlineSecs` (type: `integer`):

Hard wall-clock budget for all locations.

## Actor input object example

```json
{
  "locations": [
    "Toronto, Ontario, Canada"
  ],
  "checkIn": "2026-08-10",
  "checkOut": "2026-08-12",
  "adults": 2,
  "maxItemsPerLocation": 20,
  "deadlineSecs": 90
}
```

# Actor output Schema

## `dataset` (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 = {
    "locations": [
        "Toronto, Ontario, Canada"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/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 = { "locations": ["Toronto, Ontario, Canada"] }

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/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 '{
  "locations": [
    "Toronto, Ontario, Canada"
  ]
}' |
apify call dami_studio/airbnb-listings-scraper --silent --output-dataset

```

## MCP server setup

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