# Airbnb Reviews Scraper (`w3crawler/airbnb-reviews-scraper`) Actor

Scrape public Airbnb listing reviews with pagination, category ratings, star distribution, host responses, and fail-closed access diagnostics.

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

## Pricing

from $2.99 / 1,000 reviews

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

### What does Airbnb Reviews Scraper do?

**Airbnb Reviews Scraper** extracts rich, public review records from one or more Airbnb listing pages. It is an **Airbnb reviews API alternative** for collecting listing context, ratings, reviewer details, review text, host responses, topic mentions, and pagination provenance in a normalized dataset.

The Actor opens Airbnb's public reviews surface in a real browser, activates the public sort/search controls when available, follows incremental review loading, and extracts hydrated review cards from the DOM. A bounded JSON-LD/HTML fallback keeps a run explainable when a browser cannot launch or a listing cannot be opened. The Actor does not log in, solve CAPTCHAs, cross paywalls, or bypass access controls.

### Why use Airbnb Reviews Scraper?

Use it for accommodation research, guest-sentiment analysis, host-response monitoring, listing quality comparisons, travel-market reports, and review datasets for downstream analytics.

Main capabilities:

- Rich review rows with listing, host, reviewer, review, response, image, rating, category-rating, and public topic-mention fields.
- Multiple listing URLs in one run, URL normalization, global `maxItems` enforcement, and optional global review deduplication.
- Incremental DOM pagination for Airbnb's scrollable review dialog, with a bounded `maxPages` control and stable `reviewIndex`, `pagesScraped`, and `reviewsLoaded` context.
- Airbnb sort and search controls plus local deterministic filtering and sorting by rating/date.
- Rating, reviewer-location, stay-text, language, date, keyword, and host-response filters.
- Fail-closed diagnostics for blocked, empty, malformed, timed-out, and unavailable public pages. Diagnostics use `pageType: "run_diagnostic"` and are never presented as fake review rows.
- A named `OUTPUT_SUMMARY` key-value record with counts, pagination, filter, fallback, and browser status information.
- Apify scheduling, API access, integrations, run history, and monitoring.

### What data can Airbnb Reviews Scraper extract?

Fields are omitted when Airbnb does not expose a public value. Arrays and nested objects are bounded so a single row remains practical to download.

| Group | Fields |
|---|---|
| Record and request provenance | `recordId`, `recordType`, `url`, `listingId`, `listingUrl`, `requestedUrl`, `finalUrl`, `sourceDomain`, `ok`, `dataAvailable`, `accessStatus`, `targetKind`, `source`, `pageType`, `found`, `runStatus`, `extractionMethod`, `fallbackMode`, `scrapedAt` |
| Listing context | `listingTitle`, `listingType`, `location`, `guestCapacity`, `bedroomCount`, `bedCount`, `bathroomCount`, `listingDescription`, `coverImageUrl`, `listingImages`, `amenities`, `amenitiesSnippet`, `amenityCount`, `isGuestFavourite` |
| Listing ratings and review topics | `overallRating`, `totalReviewCount`, `starDistribution`, `categoryRatings`, `reviewTopics` |
| Host context | `hostName`, `hostProfileUrl`, `hostIsSuperhost`, `hostReviewCount`, `hostRating`, `hostYearsHosting`, `hostResponseRate`, `hostResponseTime` |
| Review and pagination context | `reviewIndex`, `reviewPage`, `pagesScraped`, `scrollsPerformed`, `reviewsLoaded`, `reviewId`, `rating`, `date`, `dateIso`, `stayType`, `stayDate`, `stayDateIso`, `reviewText`, `reviewLanguage`, `isTranslated`, `helpfulCount`, `reviewImages` |
| Reviewer context | `authorName`, `authorInfo`, `reviewerLocation`, `reviewerYearsOnAirbnb`, `reviewerId`, `reviewerUrl`, `authorAvatar` |
| Host response context | `hasHostResponse`, `hostResponse`, `hostResponseAuthor`, `hostResponseAuthorId`, `hostResponseAuthorUrl`, `hostResponseDate`, `hostResponseDateIso` |
| Diagnostic-only fields | `status`, `error`, `errorCode` |

`reviewTopics` is an array such as `{ "name": "Location", "count": 40 }`. `starDistribution` contains percentage buckets such as `5_star`; `categoryRatings` contains public sub-ratings such as `cleanliness`, `accuracy`, `checkIn`, `communication`, `location`, and `value`.

### How to scrape Airbnb reviews

1. Open the Actor's **Input** tab.
2. Add one or more public Airbnb `/rooms/<id>` URLs to `productUrls`.
3. Choose review limits, pagination, filters, sort order, and output fields.
4. Start the Actor and open the **Dataset** tab when the run completes.
5. Download the dataset or use the Actor's **API** tab to integrate it into an application, workflow, or scheduled job.

### How much will it cost to scrape Airbnb reviews?

The Actor is compute-based. A one-listing, low-limit run normally uses less compute than a multi-listing run that loads many review pages. The main cost controls are `maxItems`, `maxReviewsPerListing`, `maxPages`, `requestDelayMs`, `maxConcurrency`, `maxRequestRetries`, and `requestTimeoutSecs`. The browser path is more complete but more expensive than the bounded HTTP fallback.

`maxPages: 0` can load all publicly exposed review batches, so a listing with hundreds of reviews can use more browser time. Airbnb may require several physical scroll windows to request one additional batch; `scrollsPerformed` exposes that actual browser work. Filters are applied after the visible review cards are hydrated; a restrictive filter may still require pagination to find matches. Current run cost and platform pricing are shown in the Apify Console for your account.

### Input

All input values are validated and normalized by the same runtime validator used by the test fixtures. URL rules are also checked in code because they are more specific than a generic JSON Schema pattern.

#### Input sources

| Field | Type | Default | Description |
|---|---|---:|---|
| `productUrls` | array of strings | required | HTTPS Airbnb listing URLs such as `https://www.airbnb.com/rooms/123456789`. Region domains are accepted and normalized to `www.airbnb.com`. Duplicate listing IDs are removed. |

#### Pagination and limits

| Field | Type | Default | Description |
|---|---|---:|---|
| `maxItems` | integer | `0` | Preferred global maximum number of review rows across all listings. `0` means no global cap. |
| `maxTotalReviews` | integer | `0` | Legacy alias for `maxItems`. If both are greater than zero, `maxTotalReviews` takes precedence. |
| `maxReviewsPerListing` | integer | `0` | Maximum rows emitted for each listing. `0` means no per-listing cap. |
| `maxPages` | integer | `0` | Maximum bounded review pagination scan windows per listing. Airbnb may require several physical scroll events per window; `0` continues until the source is exhausted or stable loading stops. |
| `deduplicate` | boolean | `true` | Remove repeated review IDs globally. If no ID exists, use normalized listing/author/date/text as a fallback key. |

The browser path prefers the real scrollable review container and stops when the requested review target is reached, Airbnb exposes no more cards, the configured `maxPages` is reached, or loading remains stable for a bounded number of rounds. The HTTP fallback can expose only the bounded review sample present in public JSON-LD; it does not pretend that static HTML pagination is complete.

#### Review filters and sorting

| Field | Type | Default | Description |
|---|---|---:|---|
| `reviewSearch` | string | `""` | Case-insensitive phrase matched against review text, reviewer details, stay text, and host response text. The Actor also attempts Airbnb's public Search all reviews control. |
| `minRating` | number `0`–`5` | not set | Keep reviews at or above this rating. |
| `maxRating` | number `0`–`5` | not set | Keep reviews at or below this rating. |
| `reviewerLocation` | string | `""` | Case-insensitive substring filter for the public reviewer location line. |
| `stayTypeFilter` | string | `""` | Case-insensitive substring filter for displayed stay text, such as `night` or `business`. |
| `reviewLanguage` | string | `""` | Optional language code such as `en` or `fr`. Reviews without an exposed language attribute do not pass when this filter is set. |
| `minReviewDate` | `YYYY-MM-DD` string | `""` | Inclusive minimum date. Month/year and relative Airbnb dates are normalized best-effort. |
| `maxReviewDate` | `YYYY-MM-DD` string | `""` | Inclusive maximum date. Must be on or after `minReviewDate`. |
| `hasHostResponseOnly` | boolean | `false` | Keep only reviews with a detected public host response. |
| `reviewSort` | enum | `BEST_QUALITY` | `BEST_QUALITY`, `MOST_RECENT`, `HIGHEST_RATED`, or `LOWEST_RATED`. Ties retain source order and missing values sort last. |

The selected Airbnb sort is requested before scrolling, then the normalized rows are sorted locally as a deterministic safety net. Filters do not fabricate missing values: a minimum/date/language filter requires the corresponding public value.

#### Output options

| Field | Type | Default | Description |
|---|---|---:|---|
| `includeListingMetadata` | boolean | `true` | Include public listing, rating, amenities, and gallery fields. |
| `includeReviewerDetails` | boolean | `true` | Include public reviewer profile, location/tenure, avatar, and profile URL fields. |
| `includeHostResponses` | boolean | `true` | Include public host response text and response-author fields. `hasHostResponse` remains available for filtering/context. |
| `includeReviewMedia` | boolean | `true` | Include public image URLs attached to review cards. |
| `includeReviewTopics` | boolean | `true` | Include the public review-topic chips and counts shown by Airbnb. |

#### Developer options

These controls are grouped under **Developer Options** in the input schema and are always bounded.

| Field | Type | Default | Valid range | Description |
|---|---|---:|---:|---|
| `requestDelayMs` | integer | `1500` | `0`–`15000` | Delay before listing/review requests and fallback fetches. |
| `maxConcurrency` | integer | `2` | `1`–`5` | Maximum concurrent browser listing pages. |
| `maxRequestRetries` | integer | `2` | `0`–`10` | Crawlee retries for failed browser requests. HTTP fallback retries are separately bounded. |
| `requestTimeoutSecs` | integer | `90` | `30`–`300` | Navigation and fallback HTTP timeout per listing request. |
| `saveDebugHtml` | boolean | `true` | — | Save bounded `debug-<listingId>.html` artifacts when browser extraction fails. |
| `saveDebugScreenshot` | boolean | `false` | — | Save bounded `debug-<listingId>.jpg` artifacts alongside debug HTML. |
| `proxyConfiguration` | object | not set | — | Compatibility field. It is intentionally ignored; this Actor uses direct transparent requests without IP rotation. |

Proxy credentials are never logged. Proxy settings are not a CAPTCHA, login, fingerprint, or access-control bypass, and the Actor does not claim that a proxy was used.

### Input examples

#### 1. Quick rich smoke test

This is a small browser test that should produce several rich records without loading every review.

```json
{
  "productUrls": [
    "https://www.airbnb.com/rooms/1104883308160967951"
  ],
  "maxItems": 3,
  "maxReviewsPerListing": 3,
  "maxPages": 2,
  "reviewSort": "MOST_RECENT",
  "requestDelayMs": 0,
  "maxConcurrency": 1,
  "requestTimeoutSecs": 60,
  "saveDebugHtml": false
}
```

#### 2. Multiple listings with a global cap

The global limit applies across all URLs, while the per-listing limit prevents one listing from consuming the complete result set.

```json
{
  "productUrls": [
    "https://www.airbnb.com/rooms/1104883308160967951",
    "https://www.airbnb.com/rooms/38637542"
  ],
  "maxItems": 4,
  "maxReviewsPerListing": 2,
  "maxPages": 2,
  "deduplicate": true,
  "includeHostResponses": true,
  "includeReviewerDetails": true,
  "requestDelayMs": 0,
  "maxConcurrency": 1,
  "maxRequestRetries": 0,
  "requestTimeoutSecs": 60,
  "saveDebugHtml": false
}
```

#### 3. Filtered sentiment sample

Filters are allow-listed and validated; no arbitrary code or sort expression is accepted.

```json
{
  "productUrls": [
    "https://www.airbnb.com/rooms/1104883308160967951"
  ],
  "reviewSearch": "comfortable",
  "minRating": 5,
  "reviewerLocation": "Virginia",
  "hasHostResponseOnly": true,
  "minReviewDate": "2026-01-01",
  "reviewSort": "HIGHEST_RATED",
  "maxItems": 5,
  "maxPages": 5,
  "requestDelayMs": 0,
  "maxConcurrency": 1,
  "maxRequestRetries": 0,
  "requestTimeoutSecs": 60,
  "saveDebugHtml": false
}
```

#### 4. Review-only output with media/topics disabled

This is useful when downstream storage should contain the core text and response fields only.

```json
{
  "productUrls": [
    "https://www.airbnb.com/rooms/1104883308160967951"
  ],
  "maxItems": 10,
  "includeListingMetadata": false,
  "includeReviewerDetails": false,
  "includeReviewMedia": false,
  "includeReviewTopics": false,
  "includeHostResponses": false,
  "requestDelayMs": 0,
  "maxConcurrency": 1,
  "maxRequestRetries": 0,
  "requestTimeoutSecs": 60,
  "saveDebugHtml": false
}
```

#### 5. Developer-controlled conservative run

```json
{
  "productUrls": [
    "https://www.airbnb.com/rooms/1104883308160967951"
  ],
  "maxItems": 5,
  "maxPages": 1,
  "requestDelayMs": 3000,
  "maxConcurrency": 1,
  "maxRequestRetries": 1,
  "requestTimeoutSecs": 60,
  "saveDebugHtml": false,
  "saveDebugScreenshot": false
}
```

### Output

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

The default dataset contains one normalized review record per emitted review. Rows with `pageType: "run_diagnostic"` are transparent diagnostics for blocked, empty, or failed listings and should be separated from normal review rows in downstream processing.

#### Representative rich review item

The following is a shortened, anonymized example. Array lengths vary with the public page and input limits.

```json
{
  "recordId": "123456789#review-987654321",
  "recordType": "review",
  "url": "https://www.airbnb.com/rooms/123456789",
  "listingId": "123456789",
  "listingUrl": "https://www.airbnb.com/rooms/123456789",
  "requestedUrl": "https://www.airbnb.com/rooms/123456789",
  "finalUrl": "https://www.airbnb.co.in/rooms/123456789?locale=en",
  "sourceDomain": "www.airbnb.co.in",
  "ok": true,
  "dataAvailable": true,
  "accessStatus": "ok",
  "targetKind": "listing",
  "source": "Airbnb listing reviews",
  "pageType": "review",
  "found": true,
  "extractionMethod": "playwright_dom",
  "fallbackMode": "browser",
  "listingTitle": "Example central apartment",
  "listingType": "Entire apartment",
  "location": "Example City, Example Region",
  "guestCapacity": 2,
  "bedroomCount": 1,
  "bedCount": 1,
  "bathroomCount": 1,
  "listingImages": ["https://a0.muscache.com/im/pictures/example-cover.jpg"],
  "amenities": ["Wifi", "Kitchen", "Air conditioning"],
  "amenityCount": 24,
  "isGuestFavourite": true,
  "overallRating": 4.9,
  "totalReviewCount": 128,
  "starDistribution": { "5_star": 96, "4_star": 4 },
  "categoryRatings": { "cleanliness": 4.9, "accuracy": 4.8, "communication": 5, "location": 4.9 },
  "reviewTopics": [{ "name": "Location", "count": 40 }, { "name": "Cleanliness", "count": 30 }],
  "hostName": "Example host",
  "hostIsSuperhost": true,
  "reviewIndex": 1,
  "pagesScraped": 2,
  "scrollsPerformed": 12,
  "reviewsLoaded": 18,
  "reviewId": "987654321",
  "authorName": "Example guest",
  "authorInfo": "Example region",
  "reviewerLocation": "Example region",
  "reviewerUrl": "https://www.airbnb.com/users/profile/111222333",
  "rating": 5,
  "date": "March 2026",
  "dateIso": "2026-03-01T00:00:00.000Z",
  "stayType": "Stayed a few nights",
  "reviewText": "A clean and comfortable stay near public transport.",
  "reviewLanguage": "en",
  "isTranslated": false,
  "hasHostResponse": true,
  "hostResponse": "Thank you for staying with us.",
  "hostResponseAuthor": "Example host",
  "hostResponseDate": "April 2026",
  "scrapedAt": "2026-09-05T12:00:00.000Z"
}
```

#### Diagnostic item

```json
{
  "recordId": "123456789#diagnostic-blocked",
  "recordType": "diagnostic",
  "url": "https://www.airbnb.com/rooms/123456789",
  "listingId": "123456789",
  "requestedUrl": "https://www.airbnb.com/rooms/123456789",
  "finalUrl": "https://www.airbnb.com/rooms/123456789",
  "sourceDomain": "www.airbnb.com",
  "status": 403,
  "ok": false,
  "dataAvailable": false,
  "accessStatus": "blocked",
  "targetKind": "listing",
  "source": "Airbnb listing reviews",
  "pageType": "run_diagnostic",
  "found": false,
  "runStatus": "BLOCKED_FAIL_CLOSED",
  "error": "Airbnb public page returned a CAPTCHA, access-denied, or rate-limit page.",
  "errorCode": "BLOCKED",
  "extractionMethod": "http_html",
  "fallbackMode": "http",
  "scrapedAt": "2026-09-05T12:00:00.000Z"
}
```

#### `OUTPUT_SUMMARY` key-value record

```json
{
  "status": "SUCCEEDED",
  "itemCount": 25,
  "successfulCount": 25,
  "diagnosticCount": 0,
  "blockedCount": 0,
  "startUrlCount": 2,
  "pagesProcessed": 8,
  "scrollsProcessed": 24,
  "filteredOutCount": 12,
  "dataAvailable": true,
  "fallbackUsed": false,
  "browserBlocked": false,
  "browserInfraFailure": false,
  "source": "airbnb_public_reviews",
  "completedAt": "2026-09-05T12:00:00.000Z"
}
```

### Pagination, multiple listings, and fallback behavior

Airbnb currently presents reviews in a scrollable dialog rather than a stable numbered URL sequence. The Actor tracks the initial/incremental scan windows in `pagesScraped` and the physical DOM scroll work in `scrollsPerformed`. `maxPages` bounds those scan windows per listing; `maxItems` is global across all normalized listing URLs; `maxReviewsPerListing` is applied per listing; and deduplication is global across the run.

When the browser path fails for one listing, the Actor tries a direct public JSON-LD/HTML fallback for that listing only. A fallback success is marked with `extractionMethod: "http_ssr_jsonld"` and `fallbackMode: "http"`; fallback output may contain fewer reviews because static JSON-LD is not the full modal feed. If both paths fail, one diagnostic row is emitted for that listing. No synthetic review is created.

### Troubleshooting

- **No review rows:** Check `OUTPUT_SUMMARY`, then inspect diagnostic rows and any `debug-<listingId>.html` or `.jpg` artifacts. A restrictive filter can intentionally produce `NO_MATCHING_REVIEWS`.
- **Blocked or CAPTCHA page:** The Actor stops that source with `BLOCKED_FAIL_CLOSED`. Increase pacing, lower concurrency, respect Airbnb's policies, and try again later. The Actor does not solve the challenge.
- **Only a few reviews:** Confirm `maxPages` and `maxReviewsPerListing`. Static HTTP fallback is intentionally bounded; the browser path is required for deeper public review loading.
- **Search did not appear:** Airbnb may change its public UI. The Actor still applies the same keyword locally to hydrated text and reports the extraction path in each row.
- **API/integration output:** Use the Dataset and API tabs in the Apify Console. The named `OUTPUT_SUMMARY` key is in the default key-value store.

### Privacy, legal, and affiliation

Use this Actor only for public information and in accordance with Airbnb's Terms of Service, robots guidance, applicable privacy/data-protection laws, and your own authorization. Do not use it to collect private data, evade access controls, harass reviewers or hosts, or make decisions about people. Airbnb is a trademark of its respective owner; this Actor is an independent tool and is not affiliated with or endorsed by Airbnb.

# Actor input Schema

## `productUrls` (type: `array`):

One or more HTTPS Airbnb listing URLs. Region domains and query strings are accepted and normalized to the listing ID.

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

Maximum review records emitted for each listing. Set 0 for no per-listing cap.

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

Global maximum number of review records across all listing URLs. Set 0 for no global cap. This is the preferred name for new integrations.

## `maxTotalReviews` (type: `integer`):

Backwards-compatible alias for maxItems. When both are greater than zero, maxTotalReviews takes precedence.

## `maxPages` (type: `integer`):

Maximum bounded review-pagination scan windows per listing. Airbnb may require several physical scroll events per window; set 0 to continue until the source is exhausted or the review limit is reached.

## `deduplicate` (type: `boolean`):

Remove repeated review IDs across the complete run; when Airbnb does not expose an ID, use normalized author/date/text as a bounded fallback key.

## `reviewSearch` (type: `string`):

Optional case-insensitive phrase matched against review text, reviewer details, stay text, and host response text.

## `minRating` (type: `number`):

Keep reviews with a rating at or above this value. Reviews without a rating do not pass when this filter is set.

## `maxRating` (type: `number`):

Keep reviews with a rating at or below this value. Must be greater than or equal to minRating when both are set.

## `reviewerLocation` (type: `string`):

Optional case-insensitive substring filter for the public reviewer location line.

## `stayTypeFilter` (type: `string`):

Optional case-insensitive substring filter for Airbnb's displayed stay text, such as nights, week, or business trip.

## `reviewLanguage` (type: `string`):

Optional two-letter language code filter, for example en or fr. It is applied only when Airbnb exposes a language attribute.

## `minReviewDate` (type: `string`):

Optional inclusive date in YYYY-MM-DD format. Month/year and relative Airbnb dates are normalized best-effort.

## `maxReviewDate` (type: `string`):

Optional inclusive date in YYYY-MM-DD format. Must be on or after minReviewDate when both are set.

## `hasHostResponseOnly` (type: `boolean`):

Keep only reviews where a public host response was detected.

## `reviewSort` (type: `string`):

Order requested from Airbnb and mirrored locally after extraction for deterministic output.

## `includeListingMetadata` (type: `boolean`):

Include public listing title, type, location, capacity, description, ratings, amenities, and gallery image fields.

## `includeReviewerDetails` (type: `boolean`):

Include public reviewer profile, location/tenure, avatar, language, and profile URL fields when exposed.

## `includeHostResponses` (type: `boolean`):

Include the public host response text and response-author fields when Airbnb exposes them.

## `includeReviewMedia` (type: `boolean`):

Include public image URLs attached to review cards when exposed. Avatar URLs remain part of reviewer details.

## `includeReviewTopics` (type: `boolean`):

Include Airbnb's public Guest reviews mention topic labels and counts when displayed in the review dialog.

## `requestDelayMs` (type: `integer`):

Delay before each listing/review-page request and fallback fetch. Use a respectful value for production runs.

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

Maximum number of listing browser pages processed concurrently. Higher values use more memory and can increase access pressure.

## `maxRequestRetries` (type: `integer`):

Maximum Crawlee retries for a failed browser request. HTTP fallback uses its own bounded retry loop.

## `requestTimeoutSecs` (type: `integer`):

Bounded navigation and fallback HTTP timeout for each listing request.

## `saveDebugHtml` (type: `boolean`):

Save a bounded debug HTML key-value record when a listing or reviews panel cannot be extracted.

## `saveDebugScreenshot` (type: `boolean`):

Save a JPEG screenshot alongside debug HTML when browser extraction fails.

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

Accepted for compatibility but intentionally ignored. This Actor makes direct transparent requests and does not rotate IPs or bypass access controls.

## Actor input object example

```json
{
  "productUrls": [
    "https://www.airbnb.com/rooms/1104883308160967951"
  ],
  "maxReviewsPerListing": 0,
  "maxItems": 0,
  "maxTotalReviews": 0,
  "maxPages": 0,
  "deduplicate": true,
  "reviewSearch": "",
  "reviewerLocation": "",
  "stayTypeFilter": "",
  "reviewLanguage": "",
  "minReviewDate": "",
  "maxReviewDate": "",
  "hasHostResponseOnly": false,
  "reviewSort": "BEST_QUALITY",
  "includeListingMetadata": true,
  "includeReviewerDetails": true,
  "includeHostResponses": true,
  "includeReviewMedia": true,
  "includeReviewTopics": true,
  "requestDelayMs": 1500,
  "maxConcurrency": 2,
  "maxRequestRetries": 2,
  "requestTimeoutSecs": 90,
  "saveDebugHtml": true,
  "saveDebugScreenshot": false
}
```

# Actor output Schema

## `dataset` (type: `string`):

Review rows with listing/host/reviewer context, review topics, pagination context, and transparent extraction provenance. Diagnostic rows use pageType=run\_diagnostic.

## `files` (type: `string`):

Key-value store containing debug HTML captured when a reviews panel cannot be opened.

## `summary` (type: `string`):

OUTPUT\_SUMMARY JSON with review, diagnostic, pagination, filtering, fallback, and completion counts.

# 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 = {
    "productUrls": [
        "https://www.airbnb.com/rooms/1104883308160967951"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("w3crawler/airbnb-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 = { "productUrls": ["https://www.airbnb.com/rooms/1104883308160967951"] }

# Run the Actor and wait for it to finish
run = client.actor("w3crawler/airbnb-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 '{
  "productUrls": [
    "https://www.airbnb.com/rooms/1104883308160967951"
  ]
}' |
apify call w3crawler/airbnb-reviews-scraper --silent --output-dataset

```

## MCP server setup

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