# Airbnb Scraper — Listings, Prices, Reviews & Calendars (`tortuga/airbnb-scraper`) Actor

Scrape Airbnb listings by location or search URL: prices for your dates, ratings, rooms, coordinates, hosts, amenities and house rules, plus guest reviews and availability calendars.

- **URL**: https://apify.com/tortuga/airbnb-scraper.md
- **Developed by:** [Trevor Ortega](https://apify.com/tortuga) (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 $3.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 — Listings, Prices, Reviews & Calendars

Scrape Airbnb the way a guest sees it: search any location (or paste any Airbnb search URL) and get every listing
with its **price for your dates**, rating, rooms, coordinates and badges. Turn on details for the full listing page
(description, amenities, house rules, check-in/out times, host profile, sub-ratings, license number), or switch the
mode to collect **guest reviews** or **availability calendars**. No login, no browser, no cookies needed.

**What you can do with it**

- Compare prices of a city or neighborhood for specific dates (short-term rental market research, pricing tools).
- Build lead lists of hosts and Superhosts, or track competitors' listings.
- Analyse guest reviews (sentiment, host responses, languages) for any listing.
- Track occupancy: day-by-day availability and minimum-night rules for up to 12 months.
- Run it on a schedule and get only **new or changed** listings, reviews or calendars.

### What data does it extract?

**Listings** (`mode: listings`) — one item per listing from your searches:

| Field | Example |
|---|---|
| `id`, `url` | `32422325`, `https://www.airbnb.com/rooms/32422325` |
| `name`, `title`, `subtitle` | `Brand new apartment right in the heart of Alfama.`, `Apartment in Santa Maria Maior` |
| `propertyType`, `neighborhood` | `Apartment`, `Santa Maria Maior` |
| `latitude`, `longitude` | `38.71167`, `-9.12559` (approximate, as Airbnb shows it) |
| `currency`, `checkIn`, `checkOut`, `nights` | `USD`, `2026-11-12`, `2026-11-15`, `3` |
| `pricePerNight`, `priceTotal`, `originalPriceTotal` | `124.36`, `374`, `443` (struck-through price) |
| `priceLabel`, `priceDetails` | `$374 for 3 nights, originally $443`, the price breakdown lines |
| `rating`, `reviewCount`, `isNew` | `4.82`, `481`, `false` |
| `bedrooms`, `beds`, `bathrooms`, `roomInfo` | `1`, `2`, `1`, `["1 bedroom", "2 beds", "1 bath"]` |
| `isSuperhost`, `isGuestFavorite`, `badges` | `false`, `true`, `["Guest favorite"]` |
| `freeCancellation`, `highlights` | `true`, `["Pay $0 today", "Free cancellation"]` |
| `thumbnail`, `photos` | photo URLs |
| `searchQuery`, `position` | the search the listing came from and its rank |

**With details** (`includeDetails: true`, and always for listing URLs / ids) each listing also has:
`description`, `summary` ("Entire rental unit in Lisbon, Portugal"), `roomType` ("Entire home/apt"), `guests`,
`amenities`, `amenityGroups`, `amenitiesNotIncluded`, `houseRules`, `checkInTime`, `checkOutTime`, `additionalRules`,
`safetyAndProperty`, `sleepingArrangements`, `ratingDetails` (cleanliness, accuracy, check-in, communication,
location, value), `listingHighlights`, `licenseNumber`, `hostId`, `hostName`, `host` (Superhost, verified, rating,
reviews, years hosting, response rate and time, about, profile URL), `coHosts`, all `photos`; with dates also
`available`, `instantBook` and `cancellationPolicy` ("Free cancellation before November 15").

**Reviews** (`mode: reviews`): `listingId`, `reviewId`, `rating`, `text`, `language`, `createdAt`, `localizedDate`,
`stayDetails` ("Stayed about a week"), `reviewerName` (first name as shown), `reviewerLocation` (or
`reviewerTenure` such as "4 years on Airbnb" when no location is shown), `reviewerProfileUrl`, `hostResponse`, `hostResponseDate`, `hostName`, `translatedText` (Airbnb's English
translation of reviews in other languages), `photos`.

**Calendars** (`mode: calendar`): `id`, `name`, `from`, `to`, `availableDays`, `unavailableDays`,
`firstAvailableDate`, `unavailableDates` and `days[]` with `date`, `available`, `availableForCheckin`,
`availableForCheckout`, `minNights`, `maxNights`.

### How to scrape Airbnb listings

1. Add one or more **Locations** ("Lisbon, Portugal", "Brooklyn, NY") or paste **Airbnb URLs** — search pages with
   any filters, map area or category, or listing pages.
2. Set **check-in / check-out** dates and guests to get the exact price of that stay. Without dates Airbnb quotes a
   sample stay (see `stayDates`).
3. Optional filters: price per night, type of place, bedrooms / beds / bathrooms, amenities, Superhost, Instant Book,
   Guest favorite, currency.
4. Run. Export to JSON, CSV, Excel or use the API.

```json
{
  "mode": "listings",
  "locations": ["Lisbon, Portugal"],
  "checkIn": "2026-11-12",
  "checkOut": "2026-11-15",
  "adults": 2,
  "roomType": "entire",
  "priceMax": 200,
  "maxItems": 500
}
```

Output (shortened):

```json
{
  "type": "listing",
  "id": "32422325",
  "url": "https://www.airbnb.com/rooms/32422325",
  "name": "Brand new apartment right in the heart of Alfama.",
  "title": "Apartment in Santa Maria Maior",
  "latitude": 38.71167,
  "longitude": -9.12559,
  "currency": "USD",
  "checkIn": "2026-11-12",
  "checkOut": "2026-11-15",
  "nights": 3,
  "pricePerNight": 124.36,
  "priceTotal": 374,
  "originalPriceTotal": 443,
  "priceLabel": "$374 for 3 nights, originally $443",
  "rating": 4.82,
  "reviewCount": 481,
  "bedrooms": 1,
  "beds": 2,
  "bathrooms": 1,
  "isSuperhost": false,
  "isGuestFavorite": true,
  "freeCancellation": true,
  "position": 4
}
```

With `"includeDetails": true` (shortened):

```json
{
  "name": "Casa Priorado/Pistachio Green Apartment",
  "available": true,
  "instantBook": false,
  "cancellationPolicy": "Free cancellation before November 15",
  "guests": 2,
  "roomType": "Entire home/apt",
  "propertyType": "Entire rental unit",
  "checkInTime": "3:00 PM - 12:00 AM",
  "checkOutTime": "11:00 AM",
  "licenseNumber": "159944/AL",
  "hostName": "Casa Priorado",
  "host": { "id": "595519769", "isSuperhost": true, "rating": 4.95, "reviewCount": 230, "yearsHosting": 1,
            "responseRate": "100%", "responseTime": "Responds within an hour" },
  "amenities": ["City skyline view", "Hair dryer", "Wifi", "Kitchen", "..."],
  "houseRules": ["Check-in: 3:00 PM - 12:00 AM", "Checkout before 11:00 AM", "2 guests maximum", "..."],
  "ratingDetails": { "cleanliness": 4.95, "accuracy": 4.94, "checkin": 4.97, "communication": 4.98,
                     "location": 4.79, "value": 4.89 }
}
```

### How many listings can I get per search?

Airbnb's result list for one search ends after roughly 300-360 listings, however many places the search has. When a
search has more, the scraper automatically splits it into nightly price bands (Airbnb's own price filter) and reads
each band, so one location returns thousands of listings: a test run collected 1,500 unique Lisbon listings for
fixed dates in 2.5 minutes. Set `maxItems` to what you need; you only pay for listings saved.

### How to scrape Airbnb reviews

Set `mode` to `reviews` and add listing URLs / ids (or locations: the top `maxListingsPerSearch` listings of each
search are used). Reviews come 50 per request, newest first by default (or most relevant / highest / lowest rated).
`reviewsNewerThan` ("7 days", "2026-09-01") stops paging once a whole page is older.

```json
{ "mode": "reviews", "startUrls": [{ "url": "https://www.airbnb.com/rooms/31820112" }], "maxReviewsPerListing": 200 }
```

```json
{
  "type": "review",
  "listingId": "3777540",
  "reviewId": "1778101155240201234",
  "rating": 1,
  "text": "Escadas muito sujas lugar muito sujo porta da entrada não trava qualquer um\nPode entrar",
  "translatedText": "Very dirty stairs, very dirty place, entrance door doesn't lock, anyone can get in.\nYou can come in.",
  "language": "pt",
  "createdAt": "2026-09-19T07:29:35Z",
  "stayDetails": "Stayed one night",
  "reviewerName": "Ryan",
  "reviewerTenure": "4 years on Airbnb",
  "hostName": "Tin",
  "hostResponse": "This is a residential building located in a safe residential area, ...",
  "hostResponseDate": "2 weeks ago"
}
```

### How to get Airbnb availability calendars

Set `mode` to `calendar`. Each listing gives one item with up to 12 months of days (from today): available or not,
whether check-in / check-out is allowed that day, and the minimum / maximum nights. Airbnb no longer shows nightly
prices in the calendar; for prices of specific dates use listings mode with check-in / check-out.

### Monitor changes on a schedule

Turn on **Only new or changed items** and save the input as a task with a Schedule (Apify Console → Schedules). Each
run remembers what earlier runs returned and outputs only listings that are new or whose total price for your dates,
struck-through price or availability changed (`changeType: "new"` or `"changed"`, with the old values in
`previousValues`); in reviews mode only reviews not seen before; in calendar mode only listings whose availability
changed on a day both runs cover (`newlyUnavailableDates`, `newlyAvailableDates`). Unchanged items are not saved and
not charged. Use fixed dates, and a search whose results fit in `maxItems` (narrow it with filters or a map area):
Airbnb reorders large result lists between visits, so on a broad search listings at the edge of the window can show
up as new. Use `monitoringKey` to keep several schedules on the same search apart.

### Does it work without login?

Yes. It reads the same public data a logged-out visitor sees, through Airbnb's own web API. No account, cookies or
browser are needed, and nothing behind a login is collected.

### Pricing

Pay per result, platform usage included in your Apify plan:

| Item | Price |
|---|---|
| Listing from search results | $0.003 |
| Listing with details (details on, or listing URL / id input) | $0.0045 |
| Review | $0.0035 |
| Availability calendar (one listing, up to 12 months) | $0.002 |

Platform usage is small: about $0.007 per 1,000 search listings (1,500 listings: $0.0097, 67 requests).

**Proxy note:** the default Apify datacenter proxy works for Airbnb; no residential or Unblocker proxy is needed.
Prices follow the `currency` you set (default USD); amounts converted from the host's currency can move by a few
cents from day to day.

### Is it legal to scrape Airbnb?

This actor collects publicly visible data only (listing pages, public reviews with the first name Airbnb shows,
public host profile summaries) and nothing behind a login. Respect Airbnb's terms, privacy law (GDPR, CCPA) and the
rights of hosts and guests when you store or use the data; do not use it to contact or profile private individuals.

# Actor input Schema

## `mode` (type: `string`):

listings: one item per listing from your searches (price for the dates, rating, rooms, coordinates, badges, photos; turn on 'Include listing details' for description, amenities, house rules and host). reviews: one item per guest review of the listings. calendar: one item per listing with day-by-day availability for up to 12 months.

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

Places to search, as you would type them on Airbnb: a city, region, neighborhood or address, e.g. "Lisbon, Portugal" or "Brooklyn, NY".

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

Any Airbnb search URL (https://www.airbnb.com/s/Lisbon--Portugal/homes?checkin=...\&adults=2, with the site's own filters, map area or categories) or listing URL (https://www.airbnb.com/rooms/31820112). Filters set below replace the same filters in a search URL.

## `listingIds` (type: `array`):

Airbnb listing ids (the number in /rooms/<id>), e.g. 31820112.

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

YYYY-MM-DD. With dates, listings carry the price for exactly that stay (per night and total). Without dates Airbnb shows a price for a sample stay of a few nights (see stayDates).

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

YYYY-MM-DD, after the check-in date.

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

Number of adult guests (prices and search results depend on it). Empty = 1.

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

Children aged 2-12.

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

Infants under 2.

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

Pets (only pet-friendly listings are returned).

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

Currency of all prices (ISO code such as USD, EUR, GBP).

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

Airbnb's price filter, per night in the chosen currency.

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

Airbnb's price filter, per night in the chosen currency.

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

Only this type of place. Empty = any type.

## `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.

## `amenities` (type: `array`):

Only listings that have all of these amenities.

## `superhost` (type: `boolean`):

Only listings whose host is a Superhost.

## `instantBook` (type: `boolean`):

Only listings that can be booked without host approval.

## `guestFavorite` (type: `boolean`):

Only listings with the Guest favorite badge.

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

Listings mode: also open each listing (one extra request; two with dates) for description, all amenities, house rules, check-in/out times, safety notes, sub-ratings, host profile, license number, all photos; with dates also availability, Instant Book and the cancellation policy. Charged as 'listing with details'. Listing URLs and ids always include details.

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

Stop after this many items in total (listings, reviews or calendars, depending on the mode).

## `maxListingsPerSearch` (type: `integer`):

Reviews and calendar modes: how many top listings of each location / search URL are processed.

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

Reviews mode: cap per listing.

## `reviewsSort` (type: `string`):

Reviews mode. 'Only reviews newer than' and monitoring always use newest first.

## `reviewsNewerThan` (type: `string`):

Only reviews newer than: a date (YYYY-MM-DD) or a period such as '7 days' or '24 hours'. Reviews are read newest first and paging stops at the first page that is entirely older.

## `calendarMonths` (type: `integer`):

Calendar mode: months to read, starting with the current month (1-12).

## `onlyNewOrChanged` (type: `boolean`):

Remember what earlier runs of this search returned and output only new items or items whose price/status changed. Use with a Schedule; unchanged items are not charged. Listings: compared on the total price for your dates, the struck-through price and availability (set check-in/out dates). Reviews: only reviews not seen before. Calendars: listings whose availability changed on a day both runs cover.

## `monitoringKey` (type: `string`):

Name for this watch, so several schedules on the same search stay separate; defaults to a key derived from the search input.

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

Apify datacenter proxy (default) works for Airbnb; no residential or Unblocker proxy is needed.

## Actor input object example

```json
{
  "mode": "listings",
  "locations": [
    "Lisbon, Portugal"
  ],
  "startUrls": [],
  "listingIds": [],
  "adults": 2,
  "currency": "USD",
  "amenities": [],
  "includeDetails": false,
  "maxItems": 100,
  "maxListingsPerSearch": 20,
  "maxReviewsPerListing": 100,
  "reviewsSort": "newest",
  "calendarMonths": 12,
  "onlyNewOrChanged": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (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"
    ],
    "startUrls": [],
    "listingIds": [],
    "adults": 2,
    "amenities": [],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("tortuga/airbnb-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": ["Lisbon, Portugal"],
    "startUrls": [],
    "listingIds": [],
    "adults": 2,
    "amenities": [],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("tortuga/airbnb-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": [
    "Lisbon, Portugal"
  ],
  "startUrls": [],
  "listingIds": [],
  "adults": 2,
  "amenities": [],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call tortuga/airbnb-scraper --silent --output-dataset

```

## MCP server setup

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