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

Airbnb search results with the real total price for your dates, guests and currency (full price breakdown), rating, reviews, coordinates and photos. Goes past the ~270-result limit by splitting the map. Optional details: capacity, rooms, amenities.

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

## Pricing

Pay per event

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 Listings Scraper

Scrape Airbnb search results for any city, region or neighbourhood and get the **real total price for your exact dates, guests and currency**, with Airbnb's own price breakdown (nightly rate, discounts, fees, taxes), plus rating, review count, coordinates, photos and badges. For big cities it goes **past Airbnb's ~270-results-per-search limit** by splitting the map into smaller areas. With details turned on, you also get guest capacity, bedrooms, beds, bathrooms, the full amenity list, the description, the house rules and the cancellation policy for your dates.

No Airbnb account is needed, and only public listing data is returned.

### What you can use it for

- **Price research for specific dates**: compare what a weekend in Lisbon really costs against a weekday stay, in EUR, USD or BRL.
- **Market analysis**: supply, room types, ratings and price levels across cities or neighbourhoods.
- **Revenue management**: track competitor pricing for the same dates and guest count.
- **Travel apps and dashboards**: coordinates, photos and prices ready to plot on a map.

### Input

| Field | Default | Notes |
|---|---|---|
| `locations` | required | e.g. `"Lisbon"`, `"Rio de Janeiro"`, `"Porto, Portugal"`. Accents are fine. |
| `checkIn` / `checkOut` | today+14 / check-in+2 | `YYYY-MM-DD` |
| `adults`, `children`, `pets` | 2, 0, 0 | With pets, only pet-friendly listings are returned. |
| `currency` | `USD` | Any currency Airbnb supports |
| `locale` | `en` | `pt`, `pt-PT`, `es`, `fr`, `de`, `it`, `ja`, `ko`... Changes the language of labels, amenities and translated names. |
| `minPrice`, `maxPrice` | – | Per night, in `currency` (Airbnb's price filter) |
| `roomType` | `any` | `entire_home`, `private_room` |
| `maxResultsPerLocation` | 100 | Up to 2,000 (see limits) |
| `includeDetails` | false | Opens each listing page (extra event) |
| `proxyConfiguration` | Apify Proxy | See "About the prices" below |

Example:

```json
{
    "locations": ["Lisbon", "Rio de Janeiro"],
    "checkIn": "2026-10-16",
    "checkOut": "2026-10-18",
    "adults": 2,
    "currency": "EUR",
    "maxResultsPerLocation": 200,
    "includeDetails": false
}
```

### Output

One item per listing:

```json
{
    "location": "Lisbon",
    "searchLocation": "Lisbon, Portugal",
    "listingId": "22606233",
    "url": "https://www.airbnb.com/rooms/22606233",
    "name": "Apartments Castelo Flat B (ground floor)",
    "cardTitle": "Apartment in Lisbon",
    "roomType": "entire_home",
    "latitude": 38.7127,
    "longitude": -9.1353,
    "rating": 4.67,
    "reviewCount": 419,
    "isSuperhost": false,
    "isGuestFavorite": false,
    "isNew": false,
    "freeCancellation": null,
    "pricePerNight": 108,
    "totalPrice": 216,
    "totalPricePerNight": 108,
    "originalTotalPrice": null,
    "priceQualifier": "for 2 nights",
    "priceIncludesTaxes": false,
    "priceText": "€216 for 2 nights",
    "priceBreakdown": [{ "label": "2 nights x €108.00", "amount": 216, "text": "€216.00" }],
    "currency": "EUR",
    "checkIn": "2026-10-13",
    "checkOut": "2026-10-15",
    "nights": 2,
    "adults": 2,
    "children": 0,
    "pets": 0,
    "bedInfo": ["1 bedroom", "2 beds"],
    "images": ["https://a0.muscache.com/im/pictures/miso/Hosting-22606233/original/8a5d4ac1-....jpeg"],
    "scrapedAt": "2026-09-29T21:37:34.229Z"
}
```

With `includeDetails: true`, each item also has:

```json
{
    "propertyType": "Entire rental unit",
    "personCapacity": 3,
    "bedrooms": 1,
    "beds": 2,
    "bathrooms": 1,
    "amenities": ["Hair dryer", "Shampoo", "Hot water", "Free washer – In unit", "Wifi", "..."],
    "description": "Nice apartment located in the historic center, halfway between ...",
    "houseRules": ["3 guests maximum", "No pets", "No parties or events", "No smoking"],
    "checkInTime": "Check-in after 3:00 PM",
    "checkOutTime": "Checkout before 11:00 AM",
    "cancellationPolicy": "Free cancellation before October 15. Cancel before check-in on October 20 for a partial refund.",
    "cancellationMilestones": [
        { "refundType": "Full refund", "when": "Before Oct 15 3:00 PM", "refundTerm": "Get back 100% of what you paid." },
        { "refundType": "Partial refund", "when": "Before Oct 20 3:00 PM", "refundTerm": "Get back 50% of every night. No refund of the service fee." }
    ],
    "detailsError": null
}
```

Locations that cannot be processed come back as `{ "location": ..., "error": "location_not_found" | "blocked" | "not_processed", "errorMessage": ... }` and are **not charged**.

#### About the prices

- `totalPrice` is the price Airbnb shows for the whole stay, for your dates, guests and currency. It is taken from Airbnb's own "Price details" (to the cent), not from the rounded number on the card.
- `priceQualifier` and `priceIncludesTaxes` tell you what that total covers. `priceBreakdown` lists every line: nights × rate, discounts, cleaning or resort fees, and taxes.
- **Taxes**: whether Airbnb shows totals with or without taxes depends on the Airbnb site for your `locale` and on the visitor's country. In our tests with the default proxy, Lisbon (`pt-PT`), São Paulo and Rio (`pt`), Paris (`fr`), Barcelona and Mexico City (`es`) came with taxes, while New York, Bali and London (`en`) and Tokyo (`ja`) came **before taxes**. `priceIncludesTaxes` tells you which one you got for each listing. For totals as locals see them, use the destination's language as `locale`, or a residential proxy in the destination's country.

### Pricing

Pay per event:

| Event | Price |
|---|---|
| `listing`: one listing returned | US$0.003 |
| `listing-details`: extra per listing when `includeDetails` is on and the details were retrieved | US$0.003 |

No start fee. Error items are free. Set **Maximum cost per run** in the run options to cap spending. When the cap is reached, the run stops cleanly, marks the remaining work as `not_processed` (free) and ends as SUCCEEDED.

Examples: 1,000 listings cost US$3; 1,000 listings with details cost US$6.

### Limits

- **~270 results per search**: Airbnb shows at most 15 pages of 18 listings. Above that, the Actor splits the map into quadrants (recursively for dense areas) and dedupes by listing ID. How many listings exist for your dates and filters is up to Airbnb. For a small town, or dates that are almost sold out, you get fewer than `maxResultsPerLocation`.
- **Cancellation policy** comes only with `includeDetails`. Without it, use `freeCancellation`, which is in every item: `true` when the search card shows "Free cancellation", and `null` when the card says nothing (that does not mean non-refundable).
- **Hotels and multi-room properties**: the cancellation policy depends on the room chosen, so Airbnb shows none on the listing page and `cancellationPolicy` is `null`. Their price is for the cheapest available room.
- **Superhost**: search cards show only one badge, so a Guest Favorite listing may hide its Superhost badge. `includeDetails` gives the exact value.
- **Coordinates are approximate**: Airbnb never publishes exact addresses, and this Actor doesn't try to derive them.
- **No personal data**: host names, host photos, host profiles, reviewer names and review texts are not returned. Phone numbers, e-mails and links are removed from descriptions.
- A location Airbnb does not recognise returns a free `location_not_found` error item. Ambiguous names can match a different place. Check `searchLocation`, and add the country if needed ("Porto, Portugal").

# Actor input Schema

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

Cities, regions or neighbourhoods as you would type them in Airbnb's search box. Add the country when a name is ambiguous ("Porto, Portugal"). Accents are fine.

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

YYYY-MM-DD. Empty = 14 days from today. Prices are the real prices for these dates.

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

YYYY-MM-DD. Empty = 2 nights after check-in.

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

Number of adult guests (13+).

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

Number of children aged 2-12.

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

With pets, only pet-friendly listings are returned.

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

3-letter currency code for all prices (USD, EUR, BRL, GBP, JPY, MXN...).

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

Language of names, descriptions, amenities and price labels (en, pt, pt-PT, es, fr, de, it, ja, ko...). Listing names are shown as the host wrote them or as Airbnb translates them.

## `minPrice` (type: `integer`):

Optional. In the chosen currency, per night (Airbnb's price filter).

## `maxPrice` (type: `integer`):

Optional. In the chosen currency, per night (Airbnb's price filter).

## `roomType` (type: `string`):

Entire home or private room only; "Any type" also returns shared and hotel rooms.

## `maxResultsPerLocation` (type: `integer`):

Airbnb shows at most ~270 listings per search. Above that, the Actor splits the map into smaller areas and searches each one (duplicates removed), so large cities can return up to 2,000.

## `includeDetails` (type: `boolean`):

Also open each listing page for guest capacity, bedrooms, beds, bathrooms, full amenity list, description and house rules. Slower, and charged as an extra event per listing.

## `maxConcurrency` (type: `integer`):

How many pages are fetched in parallel.

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

Apify Proxy is used by default (datacenter, with an automatic US residential fallback for requests that keep failing). Whether totals include taxes depends on Airbnb's rules for the locale and the visitor's country; a residential proxy in the destination's country shows prices as locals see them.

## Actor input object example

```json
{
  "locations": [
    "Lisbon",
    "Rio de Janeiro",
    "New York"
  ],
  "adults": 2,
  "children": 0,
  "pets": 0,
  "currency": "USD",
  "locale": "en",
  "roomType": "any",
  "maxResultsPerLocation": 100,
  "includeDetails": false,
  "maxConcurrency": 8,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `listings` (type: `string`):

No description

## `details` (type: `string`):

No description

## `errors` (type: `string`):

No description

## `runStats` (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": [
        "Lisbon"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("atalaia/airbnb-listings").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": ["Lisbon"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("atalaia/airbnb-listings").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": [
    "Lisbon"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call atalaia/airbnb-listings --silent --output-dataset

```

## MCP server setup

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

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/Fnh1E8QPJvuigeJxw/builds/NFd0VeeDzRyqvZDTR/openapi.json
