# Airbnb Scraper - Stays, Reviews, Hosts & Prices (`abotapi/airbnb-stays-reviews-scraper`) Actor

Scrape Airbnb stays by destination or link: nightly and total price, rating breakdown, host stats, amenities, house rules, coordinates, photos, and the full review history with text and star ratings. Dual mode, filters, incremental monitoring, resume, MCP export.

- **URL**: https://apify.com/abotapi/airbnb-stays-reviews-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.90 / 1,000 listing records

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 Scraper: Stays, Reviews, Hosts & Prices

Scrape Airbnb stays by destination or by link, with the fields the listing page
actually shows: nightly and total price, the full rating breakdown, host stats,
amenities, house rules, coordinates, photos, and the **complete review history**
with review text, star rating, date, reviewer first name and the host reply.

Built for people who need the whole result set, not the first page: a run keeps
returning stays past the 270 the website's own result pager stops at, and stops
when the destination genuinely runs out.

### What you get

Every row is one stay. Search rows are free beyond the per-record price;
turning on detail or reviews adds one enrichment event per listing.

| Group | Fields |
|---|---|
| Identity | `listingId`, `url`, `title`, `categoryLabel`, `stayCategory`, `roomType`, `propertyType`, `subtitle` |
| Price | `pricePerNight`, `pricePerNightListed`, `priceTotal`, `priceOriginalTotal`, `priceCurrency`, `priceCurrencyRequested`, `priceLabel`, `priceQualifier`, `nights`, `checkIn`, `checkOut`, `adults` |
| Ratings | `rating`, `reviewsCount`, `ratingCleanliness`, `ratingAccuracy`, `ratingCheckin`, `ratingCommunication`, `ratingLocation`, `ratingValue`, `ratingDistribution`, `reviewTags`, `isGuestFavorite`, `isSuperhost`, `badges` |
| Capacity | `personCapacity`, `bedrooms`, `beds`, `bathrooms`, `sleepingArrangements` |
| Location | `latitude`, `longitude`, `city`, `region`, `country`, `locationSubtitle`, `locationLabel`, `locationIsVerified` |
| Content | `description`, `highlights`, `images`, `imagesCount`, `amenities`, `amenityGroups`, `amenitiesCount`, `houseRules`, `safetyAndProperty`, `cancellationPolicy`, `licenseInfo` |
| Host | `hostName`, `hostId`, `hostIsSuperhost`, `hostIsVerified`, `hostRating`, `hostReviewsCount`, `hostYearsHosting`, `hostResponseRate`, `hostResponseTime`, `hostProfileImageUrl`, `coHostNames` |
| Reviews | `reviews[]` (`reviewId`, `createdAt`, `relativeDate`, `rating`, `comment`, `language`, `reviewerName`, `reviewerId`, `reviewerLocation`, `reviewerPictureUrl`, `hostResponse`, `highlight`, `photoUrls`), `reviewsFetched`, `reviewsAverageOfFetched` |
| Monitoring | `changeType`, `changedFields`, `firstSeenAt`, `lastSeenAt`, `detailLoaded` |

Sample row (trimmed, values replaced with placeholders):

```json
{
  "kind": "listing",
  "listingId": "1000000000000000000",
  "url": "https://www.airbnb.com/rooms/1000000000000000000",
  "title": "Example listing name",
  "stayCategory": "Entire home/apt",
  "roomType": "Entire home/apt",
  "propertyType": "Entire rental unit",
  "pricePerNight": 180.0,
  "priceTotal": 540.0,
  "priceCurrency": "EUR",
  "nights": 3,
  "checkIn": "2026-11-10",
  "checkOut": "2026-11-13",
  "rating": 4.92,
  "reviewsCount": 57,
  "ratingCleanliness": 4.97,
  "ratingValue": 4.85,
  "personCapacity": 4,
  "bedrooms": 1,
  "beds": 1,
  "bathrooms": 1.0,
  "latitude": 48.8632,
  "longitude": 2.3521,
  "city": "Paris",
  "country": "France",
  "hostName": "Example host",
  "hostReviewsCount": 57,
  "hostResponseRate": "100%",
  "amenitiesCount": 38,
  "reviews": [
    {
      "reviewId": "1000000000000000001",
      "createdAt": "2026-08-01T00:00:00Z",
      "rating": 5,
      "comment": "Example review text.",
      "reviewerName": "Example guest"
    }
  ],
  "reviewsFetched": 30,
  "detailLoaded": true
}
```

#### Input parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| mode | string | `search` | `search` (destination search with the fields below) or `url` (paste listing and search links, used verbatim) |
| searchQueries | array | `["Paris, France"]` | Search mode: destinations written the way you would type them into the site, e.g. `Paris, France`, `Kyoto, Japan` |
| listingUrls | array | empty | URL mode: listing links (`https://www.airbnb.com/rooms/12345678`), bare listing ids, or search links, read in order |
| urls | array | empty | Alias for Listing and search links, accepted under the name other Apify actors use for URL mode |
| checkIn | string | empty | Stay start date as YYYY-MM-DD. Applies in both modes; pin it (with Check-out) when you monitor price |
| checkOut | string | empty | Stay end date as YYYY-MM-DD. Ignored unless Check-in is also set |
| adults | integer | `1` | Number of adults the stay is priced for (1 to 16) |
| children | integer | `0` | Number of children, ages 2 to 12 (0 to 15) |
| infants | integer | `0` | Number of infants under 2 (0 to 5) |
| pets | integer | `0` | Number of pets; narrows a search to stays that accept them |
| currency | string | `USD` | Three-letter currency code prices are quoted in, e.g. USD, EUR, GBP, AUD, JPY, BRL |
| priceMin | integer | empty | Search mode: lowest nightly price, in the currency above |
| priceMax | integer | empty | Search mode: highest nightly price, in the currency above |
| roomTypes | array | empty | Search mode: keep only these stay types (`Entire home/apt`, `Private room`, `Shared room`, `Hotel room`); empty for all |
| minBedrooms | integer | empty | Search mode: keep only stays with at least this many bedrooms (0 to 8) |
| minBeds | integer | empty | Search mode: keep only stays with at least this many beds (0 to 8) |
| minBathrooms | integer | empty | Search mode: keep only stays with at least this many bathrooms (0 to 8) |
| superhostOnly | boolean | `false` | Search mode: keep only stays whose host carries the Superhost badge |
| instantBookOnly | boolean | `false` | Search mode: keep only stays bookable without waiting for host approval |
| guestFavoriteOnly | boolean | `false` | Search mode: keep only stays carrying the Guest favourite badge |
| maxItems | integer | `20` | Stop after this many listing records (0 = no limit; the run stops when every search runs out) |
| fetchDetails | boolean | `false` | Add description, amenities, house rules, host stats and the full rating breakdown per listing; one Listing enrichment event each |
| includeReviews | boolean | `false` | Add the review history to every record; shares the single Listing enrichment event with the detail read |
| maxReviewsPerListing | integer | `20` | Cap on reviews collected per listing when Read the review history is on (read 24 per page); 0 skips reviews |
| resumeFromRunId | string | empty | Previous run ID or dataset ID to continue a large pull without returning listings already collected there |
| incrementalMode | boolean | `false` | Recurring monitoring: the first run marks every listing NEW; later runs return only NEW, UPDATED and REAPPEARED |
| stateKey | string | empty | Optional name for an incremental-mode monitoring campaign; auto-derived from the search setup when empty |
| emitUnchanged | boolean | `false` | Incremental mode only: also return (and bill for) listings unchanged since the last run |
| emitExpired | boolean | `false` | Incremental mode only: also return (and bill for) listings no longer found, once a run fully scans the tracked search |
| mcpConnectors | array | empty | Pipe results into apps you already use over Model Context Protocol; never changes the dataset output |
| notionParentPageUrl | string | empty | URL or id of the Notion page under which listing pages are created (Notion connector only) |
| maxNotifyListings | integer | `50` | Cap on listings written to each connector per run (1 to 1000); does not affect the dataset |
| proxyConfiguration | object | Apify Proxy on | Connection settings; the defaults are enough, on every Apify plan |

### Two ways to run it

#### Destination search

Name one or more places the way you would type them into the site
(`Paris, France`, `Kyoto, Japan`, `Austin, Texas`). Add your stay dates, guest
counts and filters and the actor builds the search for you and returns stays
until Max items.

Filters: minimum and maximum price per night, stay type (entire home or
apartment, private room, shared room, hotel room), minimum bedrooms, beds and
bathrooms, Superhost only, Instant Book only, Guest favourites only.

With several destinations, each gets an equal share of Max items.

#### Listing and search links

Paste either shape into URL mode:

- a listing link, `https://www.airbnb.com/rooms/12345678` (or just the id), read
  in full: description, amenities, house rules, host, rating breakdown, and the
  review history when you turn reviews on;
- a search link, `https://www.airbnb.com/s/Paris--France/homes?...`, used
  **verbatim**. Whatever your link asks for is what you get, and a link that
  already points at a later stretch of results continues from there. The search
  filter fields are deliberately not merged into a pasted link.

Both shapes can be mixed in one run.

### Reviews

Turn on **Read the review history** and every record gains its reviews, up to
**Max reviews per listing** (default 20, set 0 to skip). Every review carries
its text, star rating, exact date, language, the reviewer's first name and
profile link, and the host's public reply when there is one.

`reviewsCount` always reports the listing's own total, even when the cap
collected fewer, so a cap never rewrites the listing's real number.
`reviewsFetched` tells you how many you actually got.

Reviews share the single Listing enrichment event with the detail read, so a
listing that gets both is charged once, not twice, and a listing with 300
reviews costs the same as one with 3.

### Recurring monitoring and resume

- **Incremental changes for scheduled runs** returns only what moved. The first
  run marks every listing `NEW`; later runs return `NEW`, `UPDATED` and
  `REAPPEARED`, with `changedFields` naming exactly what changed. Turn on Emit
  unchanged or Emit expired to also get `UNCHANGED` and `EXPIRED` rows (those
  are extra rows, and they are billed).
- `EXPIRED` is only produced after a run that completely scanned the tracked
  search: a run stopped by the item limit, a resumed run, or a run whose pages
  did not all load never tombstones listings it did not reach.
- **Without pinned stay dates** the site quotes its own rolling window, so the
  stay dates, length and price move on their own. Those fields are then left out
  of the change comparison. Pin Check-in and Check-out when you want to monitor
  price.
- State is kept separately for every destination, filter and lookup setup. Use
  **State key** to name a campaign or to deliberately share state.
- **Resume from a previous run** takes a run ID or dataset ID and skips
  everything already collected there.

### What you are charged for

Three events, all shown on the Store page:

- **Actor Start**, once per run.
- **Listing record**, one per row in the dataset.
- **Listing enrichment**, once per listing whose full detail or review history
  was read. Never per review page, never per retry, and never charged when the
  read failed: a failed enrichment still returns the search record, uncharged.

A run that returns only search records never triggers the enrichment event.

### Send results into your apps (MCP connectors)

Optionally pipe results into the apps you already use over Model Context
Protocol. Authorize a connector under Apify, Settings, API & Integrations, then
name it in **mcpConnectors**. Notion gets a page per listing (set
**notionParentPageUrl**); other connectors get a best-effort record write or a
digest. **maxNotifyListings** caps how many rows go to each connector. The
dataset output never changes.

### Connection and reliability

- Apify Proxy with the default settings is enough, on every Apify plan.
- Requests retry at most five times with a short per-attempt timeout, rotating
  to a fresh exit on a transport failure, and then fail fast rather than grind.
- If enrichment reads start failing systematically, the run switches enrichment
  off for the rest of the run and returns search records instead of grinding
  every remaining listing. Nothing extra is billed for the listings it skipped.
- A run that reads nothing **because requests were rejected** fails loudly with
  a connection message. It never renders a total block as a quiet "no results".

### Notes and limits

- The website's own result pager stops at 270 stays per search. A run is not
  bound by that number and stops when a destination returns nothing new.
- `priceCurrency` reports the currency that was actually rendered. When the
  symbol is ambiguous (a bare `$`) and the run's requested currency cannot
  break the tie, it is left empty rather than guessed.
- Coordinates are the approximate location the site publishes before booking.
- `rating` and `reviewsCount` are empty on a listing that has no reviews yet.
  They are left empty rather than reported as zero, because the search result
  does not distinguish "no reviews" from "not shown".
- `stayCategory` is empty when the result does not carry a category line at
  all, rather than being guessed from the property name.
- `isGuestFavorite` is `true` or empty, never `false`: a result carries at most
  one badge, so another badge can displace the Guest favourite one on a listing
  that does carry it. Read full detail if you need it settled.
- `stayCategory` is the property category the search result itself carries
  ("Room in Paris", "Hotel in 9th Arrondissement"). It overlaps the stay-type
  filter rather than matching it one to one: in the site's own taxonomy a hotel
  room is also a private room, so a **Private room** search legitimately returns
  rows whose `stayCategory` is `Hotel room`. `roomType` is the value the listing
  page itself publishes and only appears when detail is read.
- `pricePerNight` is the nightly rate **after** any discount, which is the same
  quantity the price filter narrows on. `pricePerNightListed` is the pre-discount
  rate the price breakdown shows, so a listing with an early-booking discount
  reports both.
- Host and location fields can be empty on hotel-style listings, which do not
  publish an individual host section.
- The source re-ranks results continuously. The same first page fetched twice
  within a minute shares only part of its rows, so a walk's consecutive pages
  can repeat a few listings near the boundary. Every row is deduplicated and
  the dataset is unique by listing ID; a page that repeats rows the walk has
  already read never produces duplicate output.
- A destination the site does not recognise is answered with the site's own
  exploratory worldwide results rather than an error, so a typo'd destination
  returns unrelated stays instead of failing. Check the `locationLabel` column
  when a result set looks off-topic.

### Local development

```bash
python3.12 -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/python -m pytest tests -q
cd . && apify run --purge
```

# Actor input Schema

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

Search reads stays for the destinations you name, with your dates, guests and filters applied. URL mode reads the links you paste: a listing link is read in full, a search link is used exactly as pasted.

## `searchQueries` (type: `array`):

Search mode: one or more places, written the way you would type them into the site, for example 'Paris, France', 'Kyoto, Japan' or 'Austin, Texas'. Each destination is read separately and shares the item limit.

## `listingUrls` (type: `array`):

URL mode: listing links (https://www.airbnb.com/rooms/12345678), bare listing ids, or search links (https://www.airbnb.com/s/Paris--France/homes?...). A search link that already points at a later stretch of results continues from there.

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

Alias for Listing and search links, accepted under the name other Apify actors use for URL mode. Entries are read in order.

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

Stay start date as YYYY-MM-DD. Leave both dates empty to let the site quote its own rolling default window. Applies in both modes: it filters the search and prices the stay.

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

Stay end date as YYYY-MM-DD. Ignored unless Check-in is also set.

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

Number of adults the stay is priced for.

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

Number of children (ages 2 to 12).

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

Number of infants (under 2).

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

Number of pets. Narrows a destination search to stays that accept them.

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

Three letter currency code the prices are quoted in, for example USD, EUR, GBP, AUD, CAD, JPY, BRL, MXN. The record reports the currency that was actually rendered, and leaves it empty rather than guessing when the symbol is ambiguous.

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

Search mode: lowest nightly price, in the currency above. The site filters on the nightly rate before fees and taxes, which is the same quantity the record reports as Price per night.

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

Search mode: highest nightly price, in the currency above.

## `roomTypes` (type: `array`):

Search mode: keep only these kinds of stay. Leave empty for all of them.

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

Search mode: keep only stays with at least this many bedrooms.

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

Search mode: keep only stays with at least this many beds.

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

Search mode: keep only stays with at least this many bathrooms.

## `superhostOnly` (type: `boolean`):

Search mode: keep only stays whose host carries the Superhost badge.

## `instantBookOnly` (type: `boolean`):

Search mode: keep only stays that can be booked without waiting for host approval.

## `guestFavoriteOnly` (type: `boolean`):

Search mode: keep only stays carrying the Guest favourite badge.

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

Stop after this many listing records (0 = no limit; the run then stops when every search runs out of results).

## `fetchDetails` (type: `boolean`):

Off by default: search records already carry price, rating, review count, coordinates, photos and the stay type. Turn on to add description, amenities, house rules, host stats and the full rating breakdown to every record. Adds one Listing enrichment event per listing. Always included in URL mode for a listing link.

## `includeReviews` (type: `boolean`):

Off by default. Turn on to add the review history to every record, up to Max reviews per listing: text, star rating, date, reviewer first name and the host reply. Shares the same single Listing enrichment event as the detail read, so a listing is never charged twice.

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

Cap on reviews collected per listing when Read the review history is on. Reviews are read 24 per page, so this rounds up to the page — the default of 20 reads one page. Set 0 to skip reviews entirely.

## `resumeFromRunId` (type: `string`):

Paste a previous run ID or dataset ID to continue a large pull without returning listings already collected there.

## `incrementalMode` (type: `boolean`):

Turn this on for daily or recurring monitoring. The first run returns every matching listing as NEW. Later runs normally return only NEW, UPDATED and REAPPEARED listings. Turn on Emit unchanged or Emit expired only when you also want those rows returned (and billed). State is kept separately for each destination, filter and lookup setup; use State key to name or deliberately share a monitoring campaign. Without pinned stay dates the quoted window and its price are left out of the change comparison, because the site moves them on its own.

## `stateKey` (type: `string`):

Optional. Name this monitoring campaign to keep its state stable, or deliberately share state across differently configured runs. Leave empty to let the actor derive a key automatically from the search and filter settings.

## `emitUnchanged` (type: `boolean`):

Off by default. Turn on to also return listings that have not changed since the last run, marked UNCHANGED. This returns, and bills, extra rows you already have.

## `emitExpired` (type: `boolean`):

Off by default. Turn on to also return listings that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search.

## `mcpConnectors` (type: `array`):

Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify, Settings, API & Integrations, then select it here. Notion gets a rich page-per-item export; other connectors get a best-effort write or digest. Leave empty to skip; never changes the dataset output.

## `notionParentPageUrl` (type: `string`):

URL or id of the Notion page under which listing pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on listings written to each connector per run. Does not affect the dataset.

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

Apify Proxy settings. The defaults are enough, on every Apify plan.

## Actor input object example

```json
{
  "mode": "search",
  "searchQueries": [
    "Paris, France"
  ],
  "listingUrls": [
    "https://www.airbnb.com/rooms/1536119775792438782"
  ],
  "adults": 1,
  "children": 0,
  "infants": 0,
  "pets": 0,
  "currency": "USD",
  "superhostOnly": false,
  "instantBookOnly": false,
  "guestFavoriteOnly": false,
  "maxItems": 20,
  "fetchDetails": false,
  "includeReviews": false,
  "maxReviewsPerListing": 20,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "maxNotifyListings": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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 = {
    "mode": "search",
    "searchQueries": [
        "Paris, France"
    ],
    "listingUrls": [
        "https://www.airbnb.com/rooms/1536119775792438782"
    ],
    "adults": 1,
    "children": 0,
    "infants": 0,
    "pets": 0,
    "currency": "USD",
    "superhostOnly": false,
    "instantBookOnly": false,
    "guestFavoriteOnly": false,
    "maxItems": 20,
    "fetchDetails": false,
    "includeReviews": false,
    "maxReviewsPerListing": 20,
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false,
    "maxNotifyListings": 50,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/airbnb-stays-reviews-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 = {
    "mode": "search",
    "searchQueries": ["Paris, France"],
    "listingUrls": ["https://www.airbnb.com/rooms/1536119775792438782"],
    "adults": 1,
    "children": 0,
    "infants": 0,
    "pets": 0,
    "currency": "USD",
    "superhostOnly": False,
    "instantBookOnly": False,
    "guestFavoriteOnly": False,
    "maxItems": 20,
    "fetchDetails": False,
    "includeReviews": False,
    "maxReviewsPerListing": 20,
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "maxNotifyListings": 50,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/airbnb-stays-reviews-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 '{
  "mode": "search",
  "searchQueries": [
    "Paris, France"
  ],
  "listingUrls": [
    "https://www.airbnb.com/rooms/1536119775792438782"
  ],
  "adults": 1,
  "children": 0,
  "infants": 0,
  "pets": 0,
  "currency": "USD",
  "superhostOnly": false,
  "instantBookOnly": false,
  "guestFavoriteOnly": false,
  "maxItems": 20,
  "fetchDetails": false,
  "includeReviews": false,
  "maxReviewsPerListing": 20,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "maxNotifyListings": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call abotapi/airbnb-stays-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/airbnb-stays-reviews-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/DRrYfXKipx8j910wt/builds/etkOQ2Z8XDsWta2IT/openapi.json
