# Hotels.com Reviews $2.15💰 Scraper-Guest Feedback & Sentiment (`memo23/hotels-scraper`) Actor

Only $2.15💰 Extract reviews from Hotels.com with ratings, sentiment analysis, travel companion data, reviewer info, photos & responses. Includes reviewText, reviewRating (1-10), sentiments (liked/disliked), traveledWith field, reviewDate, authorName, tripType, and managementResponse. Date filtering

- **URL**: https://apify.com/memo23/hotels-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Travel, Automation, Lead generation
- **Stats:** 57 total users, 20 monthly users, 98.3% runs succeeded, 2 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $2.15 / 1,000 results

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

Hotels.com Reviews Scraper - Extract Guest Feedback & Sentiment Data


**Unlock the Full Power of Hotels.com Review Data** - The only scraper you need to track, analyze, and understand hotel reviews on Hotels.com with enterprise-grade reliability and precision. Whether you're monitoring customer sentiment, tracking hotel performance, conducting hospitality research, or building review datasets, our scraper delivers comprehensive, real-time insights while saving you time and resources.

_"From guest feedback to sentiment analysis, we turn Hotels.com review data into actionable business intelligence."_

### Overview

The Hotels.com Reviews Scraper is your go-to tool for extracting hotel review data from Hotels.com using their official GraphQL API. Ideal for hotel managers, hospitality analysts, reputation management teams, market researchers, and data scientists, it extracts detailed review information including ratings, guest feedback, sentiment analysis, travel companion data, and reviewer demographics. With easy setup and multiple export formats (JSON, CSV), it's perfect for anyone looking to gather comprehensive hotel review data from Hotels.com.

### What does Hotels.com Reviews Scraper do?

The Hotels.com Reviews Scraper is a powerful tool that enables you to:

#### Comprehensive Review Data Collection

-   **Guest Reviews**
    -   Extract complete review text, titles, and ratings (1-10 scale)
    -   Scrape reviewer names and demographics
    -   Gather travel companion information (business, family, partner, group, solo)
    -   Capture trip details (stay duration, travel dates)
    -   Download review photos submitted by guests
    -   Extract management responses to reviews
-   **Sentiment Analysis Data**
    -   Automatic sentiment categorization (liked/disliked aspects)
    -   Extract specific feedback on cleanliness, staff & service, amenities, property conditions, room comfort
    -   Identify positive and negative sentiment patterns
    -   Analyze guest satisfaction metrics
    -   Track sentiment trends over time

#### Advanced Scraping Capabilities

-   **Pagination Handling**: Automatically navigates through all review pages (25 reviews per page)
-   **Date Filtering**: Filter reviews by date range using the `reviewsFrom` parameter to scrape only recent reviews
-   **Duplicate Detection**: Smart duplicate detection prevents re-scraping the same reviews
-   **Efficient Processing**: Stops pagination early when date filters indicate no more relevant data
-   **Multi-locale Support**: Handles different locales and site IDs (US, UK, Greece, etc.)
-   **GraphQL API Integration**: Uses Hotels.com's official GraphQL API for reliable data extraction

#### Flexible Scraping Options

-   **Hotel Detail Pages**: Extract reviews from any Hotels.com hotel page
    -   US Site: `https://www.hotels.com/ho434012/hotel-anastassiou-kastoria-ellada/?locale=en_US&siteid=300000001`
    -   UK Site: `https://www.hotels.com/ho123456/hotel-name/?locale=en_GB&siteid=300000008`
    -   Greek Site: `https://el.hotels.com/ho434012/hotel-name/?locale=el_GR&siteid=300000021`
-   **Date-Filtered Scraping**: Scrape only reviews from specific dates forward
    -   Recent Reviews: Add `reviewsFrom: "2025-01-01"` to get only 2025 reviews
    -   Time-based Analysis: Track review trends month-by-month or quarter-by-quarter

This tool is ideal for:

-   Hotel reputation management and monitoring
-   Competitive intelligence and benchmarking against competitors
-   Guest sentiment analysis and service improvement insights
-   Market research for hospitality industry trends
-   Review aggregation for data analytics and machine learning
-   Monitoring competitor performance and customer satisfaction
-   Building comprehensive review databases for business intelligence

### Features

-   **Comprehensive Review Extraction**: Detailed guest reviews, ratings, sentiments, photos, and management responses
-   **Multiple Data Points**:
    -   **Review Content**: Full review text, titles, and numeric ratings (1-10 scale)
    -   **Reviewer Information**: Guest names, travel types, trip duration, and travel companion details
    -   **Sentiment Data**: Liked/disliked aspects with automatic categorization
    -   **Media**: Guest-uploaded photos and images from reviews
-   **Advanced Filtering**:
    -   **Date Range Filtering**: Use `reviewsFrom` parameter to scrape only recent reviews
    -   **Smart Pagination**: Automatically stops when reaching date cutoff or no more reviews
    -   **Duplicate Prevention**: Built-in duplicate detection across pagination
-   **Flexible Input**: Supports Hotels.com URLs with various locales:
    -   US, UK, Greek, and other regional Hotels.com sites
    -   Automatic locale and site ID detection from URLs
-   **Automatic Pagination**: Handles multi-page review results automatically (25 reviews per page)
-   **Efficient Processing**: Concurrent scraping with configurable concurrency settings
-   **Reliable Performance**: GraphQL API integration with built-in retry mechanisms and proxy support
-   **Structured Data Export**: Download review data in JSON or CSV format for analysis

### Supported Data Types

The Hotels.com Reviews Scraper extracts comprehensive review data from Hotels.com hotel pages:

1. **Guest Reviews** - Complete review information with all available data

    - Example: `https://www.hotels.com/ho434012/hotel-anastassiou-kastoria-ellada/?locale=en_US&siteid=300000001`
    - Fields: `reviewText`, `reviewTitle`, `reviewRating`, `reviewDate`, `authorName`, `sentiments`, etc.

2. **Sentiment Analysis** - Automatic categorization of guest feedback

    - Liked Aspects: `"Liked: cleanliness, staff & service, room comfort"`
    - Disliked Aspects: `"Disliked: amenities, property conditions & facilities"`
    - Sentiment Labels: Extracted from the GraphQL API's sentiment analysis

3. **Travel Companion Data** - Information about who the guest traveled with

    - Examples: `"Traveled with family"`, `"Business traveler, traveled with partner"`, `"Traveled with group"`
    - Fields: `traveledWith`, `tripType`

4. **Review Media** - Guest-uploaded photos and images
    - Photo URLs: High-resolution images from guest reviews
    - Management Responses: Hotel responses to guest feedback
    - Fields: `photos[]`, `managementResponse`

Each review includes comprehensive metadata including hotel information, scraping timestamps, pagination data, and provider details, all fully documented in the Output Fields section below.

### Quick Start

1. **Sign up for Apify**: Create your free account at [apify.com](https://apify.com).
2. **Find the Scraper**: Search for "Hotels.com Reviews Scraper" in the Apify Store.
3. **Configure Input**: Add Hotels.com hotel URLs to the `startUrls` array.
4. **Run the Scraper**: Execute the scraper on the Apify platform.
5. **Data Collection**: The scraper will output all hotel review data in JSON or CSV format.

### Input Configuration

Here's an example of how to set up the input for the Hotels.com Reviews Scraper:

```json
{
    "startUrls": [
        "https://www.hotels.com/ho434012/hotel-anastassiou-kastoria-ellada/?locale=en_US&siteid=300000001",
        "https://www.hotels.com/ho123456/another-hotel-name/?locale=en_US&siteid=300000001",
        "https://el.hotels.com/ho789012/greek-hotel/?locale=el_GR&siteid=300000021"
    ],
    "reviewsFrom": "2024-01-01",
    "maxItems": 1000,
    "maxConcurrency": 10,
    "minConcurrency": 1,
    "maxRequestRetries": 100,
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": ["RESIDENTIAL"]
    }
}
````

#### Input Fields Explanation

- `startUrls`: Array of Hotels.com hotel URLs to scrape reviews from:
  - US Hotel: `"https://www.hotels.com/ho434012/hotel-name/?locale=en_US&siteid=300000001"`
  - UK Hotel: `"https://www.hotels.com/ho123456/hotel-name/?locale=en_GB&siteid=300000008"`
  - Greek Hotel: `"https://el.hotels.com/ho789012/hotel-name/?locale=el_GR&siteid=300000021"`
  - **Note**: The scraper automatically extracts hotel ID, locale, and site ID from URLs
- `reviewsFrom` (Optional): Filter reviews by date (format: "YYYY-MM-DD"):
  - Example: `"2024-01-01"` - Only scrape reviews from January 1, 2024 onwards
  - **Smart pagination**: Automatically stops when reaching older reviews (since reviews are in chronological order)
  - Leave empty to scrape all reviews regardless of date
- `maxItems`: Maximum number of reviews to scrape (default: 1000).
- `maxConcurrency`: Maximum number of pages processed simultaneously (default: 10).
- `minConcurrency`: Minimum number of pages processed simultaneously (default: 1).
- `maxRequestRetries`: Number of retries for failed requests (default: 100).
- `proxy`: Proxy configuration object for enhanced scraping reliability:
  - `useApifyProxy`: Set to `true` to use Apify's proxy service
  - `apifyProxyGroups`: Array of proxy groups (e.g., `["RESIDENTIAL"]` for residential IPs)

### Date Filtering

The `reviewsFrom` parameter allows you to filter reviews by date, scraping only reviews from a specific date forward. This is particularly useful for:

- Monitoring recent guest feedback and sentiment changes
- Tracking review trends over specific time periods
- Reducing API calls and scraping time by focusing on recent reviews
- Building time-series datasets for trend analysis

#### How Date Filtering Works

1. **Set the Date**: Add `reviewsFrom: "2024-01-01"` to your input configuration
2. **Automatic Filtering**: The scraper filters reviews based on their `reviewDate` field
3. **Smart Pagination**: Hotels.com returns reviews in reverse chronological order (newest first)
4. **Early Stopping**: When the scraper encounters a full page of reviews older than `reviewsFrom`, it stops pagination automatically
5. **Efficiency**: This saves API calls and processing time since there's no need to check older pages

#### Example Use Cases

- **Recent Reviews Only**: `"reviewsFrom": "2025-01-01"` - Get only 2025 reviews
- **Quarterly Analysis**: `"reviewsFrom": "2024-10-01"` - Q4 2024 reviews
- **Monthly Monitoring**: Run monthly with `reviewsFrom` set to first day of current month
- **Year-over-Year Comparison**: Run separate scrapes for different year ranges

### Output Structure

The scraper provides comprehensive hotel review data from Hotels.com. The output includes complete review text, ratings, reviewer information, sentiment analysis, travel companion data, photos, and management responses. Here's a breakdown of the main components:

#### Sample JSON Output

```json
{
    "placeName": "Hotel Anastassiou Kastoria Ellada",
    "placeAddress": "",
    "provider": "hotels",
    "hotelId": "434012",
    "hotelUrl": "https://www.hotels.com/ho434012/hotel-anastassiou-kastoria-ellada/?locale=en_US&siteid=300000001",
    "reviewId": "67bf52814570c67eb5d18a8b",
    "reviewText": "Nice simple stay.",
    "reviewTitle": "",
    "reviewDate": "2025-03-12T23:00:00.000Z",
    "reviewRating": 8,
    "rating": "8/10 Very good",
    "authorName": "Jeffrey",
    "reviewerName": "Jeffrey",
    "tripType": "Stayed 1 night in Feb 2025",
    "traveledWith": "Business traveler, traveled with family",
    "sentiments": [
        "Liked: cleanliness, staff & service"
    ],
    "photos": [],
    "page": 0,
    "scrapedAt": "2026-02-06T07:04:46.691Z"
}
```

### Output Fields Explanation

The scraper returns a comprehensive dataset for each hotel review. Below is a detailed explanation of all fields in the JSON output.

#### Hotel Identification

- `placeName` (String): The hotel name extracted and formatted from the URL (e.g., "Hotel Anastassiou Kastoria Ellada").
- `placeAddress` (String): Hotel address. Currently empty as it's not available in the reviews API response.
- `provider` (String): Data source identifier, always "hotels" for Hotels.com.
- `hotelId` (String): Unique hotel identifier extracted from the URL (e.g., "434012" from `/ho434012/`).
- `hotelUrl` (String): Complete Hotels.com URL for the hotel property page.

#### Review Identification

- `reviewId` (String): Unique identifier for the review assigned by Hotels.com (e.g., "67bf52814570c67eb5d18a8b").
- `page` (Number): Pagination page number where this review was found (0-indexed, e.g., 0 for first page, 1 for second page).

#### Review Content

- `reviewText` (String): The main body text of the guest review. This is the detailed feedback written by the guest.
- `reviewTitle` (String): Optional title or headline for the review. May be empty if the guest didn't provide a title.

#### Rating Information

- `reviewRating` (Number): Numeric rating value extracted from the rating string (1-10 scale). Example: `8` from "8/10 Very good".
- `rating` (String): Full rating string as displayed on Hotels.com, including the descriptive text (e.g., "8/10 Very good", "10/10 Exceptional", "4/10 Fair").

#### Reviewer Information

- `authorName` (String): The name of the guest who wrote the review. May be a real name or "Verified traveler" for anonymous reviews.
- `reviewerName` (String): Duplicate of `authorName` field maintained for compatibility.

#### Travel Details

- `reviewDate` (String): ISO 8601 timestamp of when the review was posted (e.g., "2025-03-12T23:00:00.000Z").
- `tripType` (String): Description of the stay duration and timing (e.g., "Stayed 1 night in Feb 2025", "Stayed 3 nights in Jul 2025").
- `traveledWith` (String|null): Information about the guest's travel companion(s):
  - Examples: "Business traveler, traveled with family", "Traveled with partner", "Traveled with group"
  - `null` if the information is not available
  - Extracted from `supportingMessages` using regex pattern matching for "traveled with" or "travelled with"

#### Sentiment Analysis

- `sentiments` (Array of Strings): Hotels.com's automatic sentiment categorization of the review:
  - Positive feedback: `"Liked: cleanliness, staff & service, property conditions & facilities, room comfort"`
  - Negative feedback: `"Disliked: amenities, property conditions & facilities"`
  - May be an empty array if no sentiment data is available
  - Multiple sentiment strings can be present in the array

#### Review Media

- `photos` (Array of Strings): URLs of photos uploaded by the guest with their review:
  - High-resolution image URLs hosted on Hotels.com CDN
  - Example: `["https://a.travel-assets.com/ugc/hotel-reviews/s1155-pd9012fd0-original.jpg"]`
  - Empty array if the review has no photos

#### Hotel Response

- `managementResponse` (String|undefined): The hotel management's official response to the review:
  - Contains the full text of the hotel's reply to guest feedback
  - `undefined` if the hotel hasn't responded to the review

#### Metadata

- `scrapedAt` (String): ISO 8601 timestamp of when the data was scraped (e.g., "2026-02-06T07:04:46.691Z").

### Field Details and Examples

#### placeName

Automatically extracted from the hotel URL path and formatted for readability:

- URL: `/ho434012/hotel-anastassiou-kastoria-ellada/`
- Result: `"Hotel Anastassiou Kastoria Ellada"`

#### reviewRating vs rating

- `reviewRating`: Numeric value only (1-10) → `8`
- `rating`: Full descriptive string → `"8/10 Very good"`

#### traveledWith Field

Captures who the guest traveled with, providing valuable demographic insights:

- **Business + Family**: `"Business traveler, traveled with family"`
- **Couples**: `"Traveled with partner"`
- **Families**: `"Traveled with family"`
- **Groups**: `"Traveled with group"`
- **Solo**: `"Business traveler"` (without additional travel companions)
- **Not specified**: `null`

This field is particularly useful for:

- Analyzing review sentiment by traveler type
- Understanding target demographics
- Tailoring hotel services to guest types
- Identifying patterns in feedback by travel companion

#### sentiments Array

Provides pre-categorized feedback in these aspects:

- **cleanliness**: Room and property cleanliness
- **staff & service**: Employee interactions and service quality
- **amenities**: Hotel facilities and features
- **property conditions & facilities**: Building maintenance and infrastructure
- **room comfort**: Bed quality, temperature control, noise levels

Example with multiple sentiments:

```json
"sentiments": [
    "Liked: cleanliness, staff & service, room comfort",
    "Disliked: amenities"
]
```

#### photos Array

Guest-uploaded images provide visual feedback:

- **Empty array**: No photos uploaded with review
- **With photos**: Array of CDN URLs to high-resolution images
- Useful for: Visual sentiment analysis, property condition verification, identifying recurring issues

### Use Cases by Field

#### Reputation Management

Monitor these fields: `reviewRating`, `sentiments`, `reviewText`, `reviewDate`

#### Competitor Analysis

Compare: `reviewRating`, `sentiments`, `traveledWith` across properties

#### Service Improvement

Analyze: `sentiments`, `reviewText`, `managementResponse` patterns

#### Demographic Insights

Study: `traveledWith`, `tripType`, `authorName` distributions

#### Time-Series Analysis

Track: `reviewDate`, `reviewRating`, `sentiments` over time periods

#### Response Rate Monitoring

Calculate: Percentage of reviews with `managementResponse` present

### Technical Notes

- **Pagination**: Reviews are returned 25 per page (`page` field tracks this)
- **Chronological Order**: Reviews are in reverse chronological order (newest first)
- **Duplicate Prevention**: Built-in deduplication using `reviewId`
- **Date Filtering**: `reviewsFrom` parameter filters on `reviewDate` field
- **Locale Support**: Works with any Hotels.com locale (en\_US, en\_GB, el\_GR, etc.)
- **GraphQL API**: Data comes from Hotels.com's official ProductReviewsList operation
- **Null Handling**: Fields like `traveledWith` and `managementResponse` may be `null`/`undefined`

### Troubleshooting

#### Common Issues

**No reviews returned**

- Check if the hotel URL is correct and hotel ID is valid
- Verify the hotel has reviews on Hotels.com
- Check if locale and site ID match the URL

**Pagination stops early**

- This is expected behavior when using `reviewsFrom` date filtering
- Check logs to see if date cutoff was reached
- Verify review dates in output match expectations

**Rate limiting errors**

- Reduce `maxConcurrency` to 1-3
- Ensure you're using residential proxies
- Add delays between requests if needed

**Missing fields in output**

- Some fields like `traveledWith` or `photos` may be null/empty
- This is normal - not all reviews have all data
- Check the actual Hotels.com page to verify data availability

### Roadmap

Future enhancements being considered:

- Hotel details extraction (not just reviews)
- Price tracking features
- Availability checking
- Multi-hotel comparison reports
- Sentiment scoring algorithms
- Review photo downloading
- Translation services integration

***

### Explore More Scrapers

If you found this Apify Smartbuyglasses Scraper useful, be sure to check out our other powerful scrapers and actors at [memo23's Apify profile](https://apify.com/memo23). We offer a wide range of tools to enhance your web scraping and automation needs across various platforms and use cases.

### Support

- For issues or feature requests, please use the [Issues](https://console.apify.com/actors/WraPCOxYfqozsrP1W/issues) section of this actor.
- If you need customization or have questions, feel free to contact the author:
  - Author's website: <https://muhamed-didovic.github.io/>
  - Email: <muhamed.didovic@gmail.com>

### Additional Services

- Request customization or whole dataset: <muhamed.didovic@gmail.com>
- If you need anything else scraped, or this actor customized, email: <muhamed.didovic@gmail.com>
- For API services of this scraper (no Apify fee, just usage fee for the API), contact: <muhamed.didovic@gmail.com>
- Email: muhamed.didovic@gmail.com

# Actor input Schema

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

URLs to start with. The actor supports search URLs like `https://www.hotels.com/ho434012/hotel-anastassiou-kastoria-ellada/?locale=en_US&siteid=300000001`.

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

Maximum number of review rows per start URL (each hotel link gets its own limit). Not a global cap across all URLs.

## `reviewsFrom` (type: `string`):

Format should be YYYY-MM-DD, e.g., 2025-02-20

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

Maximum number of pages that can be processed at the same time.

## `minConcurrency` (type: `integer`):

Minimum number of pages that will be processed at the same time.

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

Number of times the crawler will retry a failed request before giving up.

## `proxy` (type: `object`):

Specifies proxy servers that will be used by the scraper in order to hide its origin.<br><br>For details, see <a href='https://apify.com/apify/web-scraper#proxy-configuration' target='_blank' rel='noopener'>Proxy configuration</a> in README.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.hotels.com/ho434012/hotel-anastassiou-kastoria-ellada/?locale=en_US&siteid=300000001"
  ],
  "maxItems": 1000,
  "maxConcurrency": 10,
  "minConcurrency": 1,
  "maxRequestRetries": 100,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# 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 = {
    "startUrls": [
        "https://www.hotels.com/ho434012/hotel-anastassiou-kastoria-ellada/?locale=en_US&siteid=300000001"
    ],
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/hotels-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 = {
    "startUrls": ["https://www.hotels.com/ho434012/hotel-anastassiou-kastoria-ellada/?locale=en_US&siteid=300000001"],
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/hotels-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrls": [
    "https://www.hotels.com/ho434012/hotel-anastassiou-kastoria-ellada/?locale=en_US&siteid=300000001"
  ],
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call memo23/hotels-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=memo23/hotels-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Hotels.com Reviews $2.15💰 Scraper-Guest Feedback & Sentiment",
        "description": "Only $2.15💰 Extract reviews from Hotels.com with ratings, sentiment analysis, travel companion data, reviewer info, photos & responses. Includes reviewText, reviewRating (1-10), sentiments (liked/disliked), traveledWith field, reviewDate, authorName, tripType, and managementResponse. Date filtering",
        "version": "0.0",
        "x-build-id": "9DNQVZ3Q6vJSrysWO"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/memo23~hotels-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-memo23-hotels-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/memo23~hotels-scraper/runs": {
            "post": {
                "operationId": "runs-sync-memo23-hotels-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/memo23~hotels-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-memo23-hotels-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "startUrls"
                ],
                "properties": {
                    "startUrls": {
                        "title": "Start URLs",
                        "type": "array",
                        "description": "URLs to start with. The actor supports search URLs like `https://www.hotels.com/ho434012/hotel-anastassiou-kastoria-ellada/?locale=en_US&siteid=300000001`.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxItems": {
                        "title": "Maximum number of items OR limit the results per crawl",
                        "type": "integer",
                        "description": "Maximum number of review rows per start URL (each hotel link gets its own limit). Not a global cap across all URLs.",
                        "default": 1000
                    },
                    "reviewsFrom": {
                        "title": "Only scrape reviews newer than [date]",
                        "type": "string",
                        "description": "Format should be YYYY-MM-DD, e.g., 2025-02-20"
                    },
                    "maxConcurrency": {
                        "title": "Max Concurrency",
                        "type": "integer",
                        "description": "Maximum number of pages that can be processed at the same time.",
                        "default": 10
                    },
                    "minConcurrency": {
                        "title": "Min Concurrency",
                        "type": "integer",
                        "description": "Minimum number of pages that will be processed at the same time.",
                        "default": 1
                    },
                    "maxRequestRetries": {
                        "title": "Max Request Retries",
                        "type": "integer",
                        "description": "Number of times the crawler will retry a failed request before giving up.",
                        "default": 100
                    },
                    "proxy": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Specifies proxy servers that will be used by the scraper in order to hide its origin.<br><br>For details, see <a href='https://apify.com/apify/web-scraper#proxy-configuration' target='_blank' rel='noopener'>Proxy configuration</a> in README.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ]
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
