# Airbnb Scraper: listings, prices, details and reviews (`pikoulas/airbnb`) Actor

Scrape Airbnb by location, search URL or listing URL: price per night and total for your dates, rating, reviews count, beds, photos, coordinates, superhost and guest favourite, with description, amenities, host and house rules, and reviews. Whole cities, past the 280 a search shows. No login.

- **URL**: https://apify.com/pikoulas/airbnb.md
- **Developed by:** [Spyridon Pikoulas](https://apify.com/pikoulas) (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 $1.00 / 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

Scrape Airbnb's listings, without an account or a browser:

- **Locations:** `Lisbon, Portugal`, `Brooklyn, NY`, with your dates, guests, price range, type of
  place and minimum bedrooms, beds and bathrooms. The search covers the whole location, not just
  the 280 listings Airbnb shows for a search: where the map holds more, it is searched again in
  smaller parts. Lisbon for four nights gave 7,096 listings in 3.5 minutes.
- **Search URLs:** paste a search from airbnb.com/s/..., with its dates, filters and map area.
- **Listing URLs:** `airbnb.com/rooms/13010122`, or the ID alone.

Every listing comes with its name, type, neighbourhood, coordinates, **rating** and **review
count**, **price per night and total** for your dates with its breakdown (nights, discounts,
taxes), bedrooms, beds and bathrooms, **superhost** and **guest favourite**, and up to 29 photos.
With `includeDetails` it also comes with its description, **amenities**, **host** (name, ID,
superhost, years hosting, rating, response rate), **house rules**, check-in and check-out times,
capacity, sleeping arrangements, registration number and the rating's **sub-scores**. With
`maxReviewsPerListing`, its **reviews**, newest first.

It costs **$1 per 1,000 listings**, details included, and **$0.50 per 1,000 reviews**.

### What people use it for

- **Short-term rental research:** prices, occupancy on given dates and ratings of a whole city or
  neighbourhood, for investing or pricing your own listing.
- **Competitor tracking:** the prices, badges and reviews of the listings around yours.
- **Travel and data products:** listings with coordinates, photos and amenities for maps, apps
  and datasets.
- **Review analysis:** what guests say about a listing or a neighbourhood.

### How to scrape Airbnb

1. Click **Try for free**; Apify's free plan covers a first run.
2. Enter **Locations** (`Lisbon, Portugal`) or **Airbnb URLs**, and how many listings you want.
3. Click **Start**, then download the results as JSON, CSV, Excel or HTML, or read them through
   the API.

An input with more options:

```json
{
  "locations": ["Lisbon, Portugal"],
  "checkIn": "2026-11-10",
  "checkOut": "2026-11-14",
  "adults": 2,
  "maxPrice": 150,
  "roomType": "entire",
  "maxListings": 2000,
  "includeDetails": false,
  "maxReviewsPerListing": 0,
  "urls": ["https://www.airbnb.com/rooms/13010122"]
}
```

Each location is its own search with the dates and filters given; a search URL keeps its own. A
listing URL always comes with its details, and with its price where it is free on your dates.

### Output

```json
{
  "type": "listing",
  "id": "17649878",
  "url": "https://www.airbnb.com/rooms/17649878",
  "name": "Biquinha Houses | Peninha 3",
  "title": "Apartment in Sintra",
  "propertyType": "Entire rental unit",
  "roomType": "Entire home/apt",
  "location": "Sintra",
  "latitude": 38.7988,
  "longitude": -9.3903,
  "rating": 4.65,
  "reviewsCount": 91,
  "isNew": false,
  "pricePerNight": 71.79,
  "priceTotal": 287.16,
  "nightlyRate": 75.47,
  "nights": 4,
  "priceBeforeDiscount": 316.0,
  "priceLabel": "$288 total, originally $316",
  "priceDetails": [{"description": "4 nights x $75.47", "amount": 301.89},
                   {"description": "Long stay discount", "amount": -28.4},
                   {"description": "Taxes", "amount": 13.67}],
  "currency": "USD",
  "bedrooms": 2,
  "beds": 3,
  "bathrooms": 2,
  "hostType": "Business host",
  "isSuperhost": true,
  "isGuestFavorite": false,
  "badges": ["Superhost"],
  "labels": ["Extended stay discount"],
  "images": ["https://a0.muscache.com/im/pictures/hosting/Hosting-17649878/original/1100b582-00ab-4ff6-8769-e5c7e169dc16.jpeg", "..."],
  "searchQuery": "Sintra, Portugal"
}
```

With `includeDetails`, a listing also has `personCapacity`, `city`, `locationName`, `ratings`
(`{"accuracy": 4.8, "checkIn": 4.7, "cleanliness": 4.66, "communication": 4.9, "location": 4.82,
"value": 4.65}`), `description`, `neighborhoodOverview`, `amenities`, `amenitiesNotIncluded`,
`checkIn` (`"after 3:00 PM"`), `checkOut`, `houseRules`, `houseRulesAdditional`,
`safetyAndProperty`, `sleepingArrangements`, `registrationNumber` and its `host`:

```json
{"name": "Casas Da Biquinha", "id": "10379875", "isSuperhost": true, "isVerified": true,
 "yearsHosting": 12, "monthsHosting": 9, "reviewsCount": 1820, "rating": 4.67,
 "profilePicture": "https://a0.muscache.com/im/pictures/user/User-10379875/original/...",
 "about": "The Biquinha Houses are part of ...", "highlights": ["Speaks English, Portuguese, and Spanish"],
 "details": ["Response rate: 100%", "Responds within an hour"], "cohosts": []}
```

A review is its own item, in the dataset's reviews view:

```json
{
  "type": "review",
  "id": "1775211570453088914",
  "listingId": "13010122",
  "listingUrl": "https://www.airbnb.com/rooms/13010122",
  "rating": 5,
  "text": "We had a great time at Nuno’s place. Definitely recommend! ...",
  "language": "en",
  "translatedText": null,
  "createdAt": "2026-09-15T07:48:30Z",
  "date": "1 week ago",
  "stay": "Stayed a few nights",
  "reviewerName": "Charlotte",
  "reviewerId": "103346200",
  "reviewerPicture": "https://a0.muscache.com/im/pictures/user/User/original/1cc9bcb0-...jpeg",
  "reviewerProfile": "https://www.airbnb.com/users/profile/1494184466920757413",
  "reviewerDetails": "10 years on Airbnb",
  "hostResponse": null,
  "hostResponseDate": null,
  "hostName": "Nuno",
  "photos": []
}
```

### Use it as an API

One call runs it and returns the results as JSON (for runs under 5 minutes; longer ones start a
run and read its dataset). Apify's Python and JavaScript clients, and its Make, Zapier and n8n
integrations, work the same way.

```bash
curl -X POST "https://api.apify.com/v2/acts/pikoulas~airbnb/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"locations": ["Lisbon, Portugal"], "maxListings": 10}'
```

AI agents can call it as a tool through Apify's MCP server: `https://mcp.apify.com?tools=pikoulas/airbnb`.

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

You pay **$0.001 per listing**, which is $1 per 1,000 listings, with or without details, and
**$0.0005 per review**, $0.50 per 1,000. Runs that go through Apify's residential proxy also pay
its traffic, $0.0012 per 100 KB: a listing is about 3 KB from a search ($0.04 per 1,000), about
28 KB with details ($0.34 per 1,000), and a review under 1 KB. There are no monthly fees.

### Good to know

- Without dates, Airbnb prices each listing for dates of its own choosing (in `stayDates`) and
  often leaves out its beds and bedrooms. Give dates for comparable prices.
- With dates, a search gives only the listings free on them for your guests.
- `pricePerNight` is the total with fees, discounts and taxes divided by the nights;
  `nightlyRate` is the rate before them. The price filters work as Airbnb's do: a night, before
  taxes.
- `location` is the neighbourhood or town the search shows; `city` comes with the details.
- `roomType` in a search is read from the listing's type (a "Room" is a private room); it's exact
  with the type-of-place filter or with details.
- A listing found by several searches is given once per run.
- A location Airbnb doesn't know is skipped with a warning.

### FAQ

#### Is it legal to scrape Airbnb?

It collects only what Airbnb shows publicly, without logging in. Scraping public data is
generally legal, but personal data is protected by laws such as the GDPR and the CCPA, and
Airbnb's terms may limit how you use what you collect. If you're unsure, ask a lawyer;
Apify's [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/) is a good start.

#### Something missing or not working?

Open an issue on the **Issues** tab with the input you used, or ask there for a field you need.

# Actor input Schema

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

Cities, regions or neighbourhoods, as typed into Airbnb's search (Lisbon, Portugal; Brooklyn, NY). Each is its own search with the dates and filters below, over its whole area on the map.

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

The prices are for these dates, and only listings free on them are given. Without dates, Airbnb prices each listing for dates of its own choosing and leaves out beds and bedrooms.

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

The day of leaving.

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

Guests aged 13 or over. Only listings that take them all are given.

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

Guests aged 2 to 12.

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

Guests under 2.

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

Only listings that allow this many pets.

## `maxListings` (type: `integer`):

How many listings to take from each location or search URL. A whole city can hold thousands.

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

Each listing's description, amenities, host, house rules, check-in and check-out times and the rating's sub-scores. One more request per listing, so slower. Listing URLs always come with them.

## `maxReviewsPerListing` (type: `integer`):

The newest reviews of each listing, each its own item. 0 for none.

## `urls` (type: `array`):

Listing URLs (airbnb.com/rooms/...) or IDs, and search URLs copied from airbnb.com/s/..., with the dates, filters and map area set there.

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

In the currency below, as Airbnb's price filter has it: a night, with fees and discounts but before taxes.

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

In the currency below, as Airbnb's price filter has it: a night, with fees and discounts but before taxes.

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

Only entire homes, private rooms or hotel rooms.

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

Only listings with at least this many bedrooms.

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

Only listings with at least this many beds.

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

Only listings with at least this many bathrooms.

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

The currency of prices, as a code (USD, EUR, GBP).

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

Not needed for most runs. On the Apify platform, a run Airbnb refuses switches to residential proxy by itself.

## Actor input object example

```json
{
  "locations": [
    "Lisbon, Portugal"
  ],
  "maxListings": 20,
  "includeDetails": false,
  "maxReviewsPerListing": 0,
  "roomType": "any",
  "currency": "USD",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

## `reviews` (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, Portugal"
    ],
    "maxListings": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("pikoulas/airbnb").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, Portugal"],
    "maxListings": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("pikoulas/airbnb").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, Portugal"
  ],
  "maxListings": 20
}' |
apify call pikoulas/airbnb --silent --output-dataset

```

## MCP server setup

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

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/knul1FTdpI9rvTyVy/builds/hPcHoW1dlk6BOyGjA/openapi.json
