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

Scrapes every guest review of Airbnb listings: rating, text with translation, date, reviewer, host response, plus the listing's overall and category ratings. Paste listing links or ids.

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

## Pricing

$2.00 / 1,000 reviews

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

### What does Airbnb Reviews Scraper do?

**Airbnb Reviews Scraper** collects **every guest review** of the
[Airbnb](https://www.airbnb.com) listings you give it: the **star rating, full
text, Airbnb's own translation, date, reviewer name, photo and home town, and
the host's response**. Each review also carries the listing's **overall rating,
review count and category ratings** (cleanliness, accuracy, check-in,
communication, location, value).

Paste a listing link from any Airbnb country site, or just the listing id,
and click **Start**. The prefilled example returns 20 reviews in about 5
seconds. Because it runs on the Apify platform, you also get API access,
scheduled runs, integrations (Google Sheets, Make, Zapier, webhooks), run
monitoring and automatic retries through Apify Proxy if Airbnb ever refuses a
request.

### Why scrape Airbnb reviews?

- **Hosts and property managers**: track what guests say about your own
  listings and your competitors', and spot recurring complaints early.
- **Market and investment research**: compare neighbourhoods and property
  types by guest satisfaction before buying or renting out.
- **Sentiment analysis and AI datasets**: get clean review text with the
  language code and an English (or any other) translation side by side.
- **Reputation monitoring**: schedule a run with "Most recent" sorting to
  pick up new reviews and host responses as they appear.

### How to scrape Airbnb reviews

1. Open a listing on Airbnb and copy the address from your browser, such as
   `https://www.airbnb.com/rooms/1541240866926218500`.
2. Paste it into **Airbnb listing links**, one link per line. Links from
   airbnb.co.uk, airbnb.de and other country sites, Airbnb Plus links and
   links with dates or guest counts in them all work.
3. Set **Max reviews per listing** (0 gets them all), the **sort order**, and
   the **language** you want translations in.
4. Click **Start**, then download the reviews when the run finishes.

### Input

All fields except the links are optional. See the **Input** tab for the full form.

| Field | Type | Default | What it does |
|---|---|---|---|
| `listingUrls` | array of strings | — | Listing links or ids. Objects such as `{"url": "..."}` from other Actors are accepted too. |
| `maxReviewsPerListing` | integer | 100 | Stops after this many reviews per listing. `0` = every review. |
| `sortBy` | string | `most_recent` | `most_recent`, `most_relevant`, `highest_rated` or `lowest_rated`. |
| `language` | string | `en` | Language code (`en`, `de`, `fr`, `es`, `pt-PT`, …) for translations, listing titles and relative dates. |
| `proxyConfiguration` | object | none | Leave empty; the Actor falls back to Apify Proxy on its own. |

```json
{
    "listingUrls": [
        "https://www.airbnb.com/rooms/1541240866926218500",
        "https://www.airbnb.co.uk/rooms/604915670831100428?adults=2",
        "1268882296424305560"
    ],
    "maxReviewsPerListing": 200,
    "sortBy": "most_recent",
    "language": "en"
}
```

### Output

One row per review. A real row from the prefilled run:

```json
{
    "reviewId": "1786795774766171985",
    "listingId": "1541240866926218500",
    "listingUrl": "https://www.airbnb.com/rooms/1541240866926218500",
    "rating": 5,
    "text": "Excelente alojamiento, muy limpio y agradable, es igual a las fotos y cumple con lo que dice. ...",
    "textLanguage": "es",
    "translatedText": "Excellent accommodation. Very clean and nice. It's just like the photos and lives up to what it says. ...",
    "translatedLanguage": "en",
    "createdAt": "2026-10-01T07:24:14Z",
    "stayDetails": "Group trip",
    "reviewerId": "123685534",
    "reviewerName": "Tania",
    "reviewerPhotoUrl": "https://a0.muscache.com/im/pictures/user/User/original/03b5de5b-9210-4cc4-8d79-2b5e2186970f.jpeg",
    "reviewerProfileUrl": "https://www.airbnb.com/users/profile/1485935310036670072",
    "reviewerLocation": "Mexico City, Mexico",
    "reviewerTenure": null,
    "hostResponse": "Grazie mille per le tue belle parole!\nÈ stato un piacere ospitarvi. ...",
    "hostResponseTranslated": "Thank you so much for your kind words!\nIt was a pleasure to host you. ...",
    "hostResponseDateText": "2 weeks ago",
    "hostName": "Alma",
    "listingTitle": "Luxury stay near Vatican and Piazza del Popolo!",
    "listingLocation": "Rome, Lazio, Italy",
    "listingRating": 4.99,
    "listingReviewCount": 92,
    "ratingAccuracy": 5.0,
    "ratingCheckin": 4.9,
    "ratingCleanliness": 5.0,
    "ratingCommunication": 5.0,
    "ratingLocation": 5.0,
    "ratingValue": 5.0,
    "scrapedAt": "2026-10-20T13:54:40.058139+00:00"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or
Excel. The Output tab also has a **Listing ratings** view with the category
ratings side by side.

### Data fields

| Field | Description |
|---|---|
| `reviewId` | Airbnb's review id (text). Each review is saved once per run. |
| `listingId`, `listingUrl` | The listing the review belongs to. |
| `rating` | The guest's star rating, 1–5. |
| `text`, `textLanguage` | The review as the guest wrote it, and its language code. |
| `translatedText`, `translatedLanguage` | Airbnb's translation into your `language`; `null` when the review is already in it. |
| `createdAt` | When the review was posted, ISO 8601 in UTC. |
| `stayDetails` | What Airbnb shows about the stay, such as "Group trip" or "Stayed a few nights", when it shows anything. |
| `reviewerId`, `reviewerName`, `reviewerPhotoUrl`, `reviewerProfileUrl` | The guest as Airbnb shows them (first name only). |
| `reviewerLocation` | The guest's home town, when they give one. |
| `reviewerTenure` | Shown instead of a town when there is none, such as "7 years on Airbnb". |
| `hostResponse`, `hostResponseTranslated` | The host's public reply and its translation, when there is one. |
| `hostResponseDateText` | When the host replied, as Airbnb words it ("2 weeks ago"); Airbnb does not publish an exact date. |
| `hostName` | First name of the host who replied. |
| `listingTitle`, `listingLocation` | The listing's title and town, in your `language`. |
| `listingRating`, `listingReviewCount` | The listing's overall rating and number of reviews. |
| `ratingAccuracy`, `ratingCheckin`, `ratingCleanliness`, `ratingCommunication`, `ratingLocation`, `ratingValue` | The listing's category ratings, 1–5, with one decimal as the listing page shows them. For hotels they cover the whole property. |
| `scrapedAt` | When the row was saved. |

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

You pay per review saved; see the **Pricing** tab for the exact price.
Listings that give nothing (removed, no reviews yet, unusable link) are never
billed. The Actor reads Airbnb's own review API over plain HTTP without a
browser and without a proxy unless Airbnb refuses, so a run is fast: about
1,900 reviews from 35 listings took 25 seconds in testing, and its platform
usage cost less than a cent.

### Tips

- **Getting only new reviews**: sort by `most_recent` and set a small
  `maxReviewsPerListing`, then schedule the run daily or weekly.
- **Finding problems fast**: sort by `lowest_rated` to read the critical
  reviews first.
- **Large batches**: hundreds of listings in one run are fine; listings are
  read three at a time and reviews 50 per request.
- **Spending cap**: set a maximum cost per run in the run options and the
  Actor stops cleanly when it is reached, keeping everything saved so far.
- **Translations**: Airbnb translates reviews itself. Set `language` to `de`
  to get German translations, German listing titles and German relative dates.

### FAQ, disclaimers, and support

**Which links work?** `airbnb.<any country>/rooms/<id>` links, including
`/rooms/plus/<id>` and links with query parameters, and bare listing ids.
Short share links (`abnb.me/…`, `airbnb.com/h/…`) and Experiences are not
supported: open a short link in a browser and paste the `/rooms/` address.

**Where do failed listings go?** Links that gave no reviews are listed with a
plain reason in the `FAILED_INPUTS` record of the run's key-value store, and
the run's status message summarises them. A run fails only when every listing
could not be loaded because of a block or network error.

**Does it need an Airbnb account?** No. It reads only what Airbnb shows to
any visitor of a listing page.

**Is it legal to scrape Airbnb?** This Actor collects publicly visible review
data. Airbnb's Terms of Service restrict automated access, and reviews contain
personal data (guests' first names, photos and home towns), which laws such as
the GDPR protect. Make sure you have a legitimate reason to process it, store
only what you need, and consult a lawyer if you are unsure.

**Something is missing or broken?** Please open an issue on the **Issues**
tab with the listing link, and we'll look at it. Need a custom Airbnb
dataset or integration? Ask there too.

# Actor input Schema

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

Listing links, one per line, such as https://www.airbnb.com/rooms/1541240866926218500. Links from any Airbnb country site (airbnb.co.uk, airbnb.de, …), Airbnb Plus links (/rooms/plus/…) and links with dates or other parameters all work, and so does a bare listing id. Short share links (abnb.me, /h/…) must be opened first and the /rooms/ address pasted instead.

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

Stops after this many reviews for each listing. Set 0 to get every review the listing has.

## `sortBy` (type: `string`):

The order Airbnb returns reviews in, which decides which ones you get when a limit is set.

## `language` (type: `string`):

A language code such as en, de, fr, es, it, pt or ja. Reviews written in another language come with Airbnb's own translation into it in translatedText (the original text is always kept), and listing titles, locations and relative dates are shown in it.

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

Leave this empty: the Actor connects directly and, if Airbnb refuses, retries through Apify's datacenter and then residential proxies on its own. A proxy chosen here is used for every request instead.

## Actor input object example

```json
{
  "listingUrls": [
    "https://www.airbnb.com/rooms/1541240866926218500"
  ],
  "maxReviewsPerListing": 20,
  "sortBy": "most_recent",
  "language": "en",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (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 = {
    "listingUrls": [
        "https://www.airbnb.com/rooms/1541240866926218500"
    ],
    "maxReviewsPerListing": 20
};

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

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

```

## MCP server setup

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