# HRS Hotel Scraper (`datascrapers/hrs-scraper`) Actor

HRS (hrs.com) hotel listings by location and travel dates: prices, ratings, amenities, and optional pictures, hotel details, and guest reviews. Structured JSON per hotel.

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

## Pricing

from $1.50 / 1,000 hotels

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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?

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

**HRS Hotel Scraper** creates a structured dataset of hotel records collected from hrs.com. Each dataset item represents one hotel and includes its name, location, star rating, guest rating, price (total and per night), currency, amenities, and availability; when enabled, it also attaches additional pictures, full hotel details, and guest reviews. Query the source by city or region (`locations`), optionally by HRS location IDs (`locationIds`), specify check-in/check-out dates and occupancy, cap the result with `maxItems`, and retrieve records through the Apify Dataset API or export them as JSON, CSV, Excel, XML, or another supported format.

### Dataset at a glance

| Property | Value |
|---|---|
| Source | HRS — hrs.com |
| Record unit | One hotel |
| Input methods | `locations`, `locationIds` (+ dates, room type, occupancy) |
| Main identifiers | `hotelId`, `url` |
| Delivery | Apify Dataset and API |
| Export formats | JSON, CSV, Excel, HTML, XML |
| Update model | Fresh records per Actor run |
| Pricing | Pay-per-event: $3 / 1,000 hotels; optional pictures, details, and reviews billed separately |

### Coverage and available records

The Actor searches HRS by city or region name (`locations`), resolved through the HRS location autocomplete, or directly by HRS location ID (`locationIds`). Location names and IDs can be combined in one run. Search parameters include:

- **Dates** — `checkInDate` and `checkOutDate` in `YYYY-MM-DD` format. If a past check-in is provided, it is automatically moved to today and check-out is set to six nights later. Check-out defaults to six nights after check-in.
- **Occupancy** — `roomType` (`SINGLEROOM`, `DOUBLEROOM`, `THREEBEDROOM`, `FOURBEDROOM`), plus `rooms` (1–8), `adults` (1–6), and `children` (0–6) per room.
- **Language and currency** — `language` (English, German, French, Spanish, Italian, Dutch, Polish) and an informational `currency` field (prices come from the API).

Conditional enrichment is controlled by three toggles:

- **`includePictures`** (default `true`) — fetches additional hotel pictures beyond the search thumbnail.
- **`includeHotelDetails`** (default `false`) — fetches the full detail page (description, amenities, room offers, contact information, all pictures).
- **`includeReviews`** (default `false`) — fetches guest reviews and extended rating breakdowns, capped per hotel by `maxReviewsPerHotel` (`0` = all available).

`maxItems` caps the total hotels collected (`0` = unlimited).

### Data dictionary

| Field | Type | Nullable | Description | Example |
|---|---:|---|---|---|
| `hotelId` | integer | No | HRS hotel identifier | `875998` |
| `hotelName` | string | No | Hotel name | `"Capri by Fraser Berlin"` |
| `url` | string | No | HRS hotel page URL | `"https://www.hrs.com/en/hotel/..."` |
| `searchLocation` | string | Yes | Location used for the search | `"Berlin"` |
| `locationId` | integer | Yes | HRS location ID | `55133` |
| `checkInDate` | string | Yes | Check-in date | `"2026-08-03"` |
| `checkOutDate` | string | Yes | Check-out date | `"2026-08-09"` |
| `street` | string | Yes | Street address | `"Scharrenstraße 22"` |
| `zipCode` | string | Yes | Postal code | `"10178"` |
| `cityName` | string | Yes | City | `"Berlin"` |
| `districtName` | string | Yes | District | `"Berlin"` |
| `country` | string | Yes | Country code | `"DEU"` |
| `address` | string | Yes | Formatted address | `"Scharrenstraße 22, 10178, Berlin, DEU"` |
| `latitude` | number | Yes | Latitude | `52.513894` |
| `longitude` | number | Yes | Longitude | `13.405057` |
| `stars` | integer | Yes | Star rating | `4` |
| `rating` | number | Yes | Guest rating | `9.1` |
| `ratingCount` | integer | Yes | Number of ratings | `15` |
| `recommendationRate` | number | Yes | Recommendation percentage | `80` |
| `totalPrice` | number | Yes | Total price for the stay | `850` |
| `pricePerNight` | number | Yes | Price per night | `141.67` |
| `currency` | string | Yes | Price currency | `"EUR"` |
| `totalAvailCount` | integer | Yes | Availability count | `47` |
| `chainName` | string | Yes | Hotel chain | `"Frasers Hospitality"` |
| `brandName` | string | Yes | Brand | `"Frasers Hospitality"` |
| `roomCategories` | array | Yes | Room categories | `["SUPERIOR"]` |
| `featureTypes` | array | Yes | Amenity/feature codes | `["PARKING", "RESTAURANT"]` |
| `hotelTypes` | array | Yes | Hotel type codes | `["CITY_HOTEL"]` |
| `crsType` | string | Yes | Reservation system type | `"HRS"` |
| `thumbnailUrl` | string | Yes | Thumbnail image URL | `"https://foto.hrsstatic.com/..."` |
| `pictureUrls` | array | Yes | Gallery image URLs; extended when `includePictures` is on | `["https://foto.hrsstatic.com/..."]` |
| `detailUrl` | string | Yes | Detail page URL | `"https://www.hrs.com/en/detail?hn=875998"` |
| `hotelDetails` | object | Yes | Full detail-page data when `includeHotelDetails` is on | see below |
| `reviewSummary` | object | Yes | Aggregated review scores when `includeReviews` is on | see below |
| `reviews` | array | Yes | Guest reviews when `includeReviews` is on | see below |

The optional `hotelDetails` object carries phone, email, homepage, description comments, room offers, and all pictures. `reviewSummary` carries aggregate category scores, and each `reviews` item carries the review text, rating, traveler group, and dates. The best stable field for deduplication is `hotelId`, with `url` as a fallback.

### Example dataset record

The following record was produced for a Berlin search with `includePictures` and `includeHotelDetails` enabled. Long arrays are truncated for readability.

```json
{
  "hotelId": 875998,
  "hotelName": "Capri by Fraser Berlin",
  "url": "https://www.hrs.com/en/hotel/capri-by-fraser-berlin-875998",
  "searchLocation": "Berlin",
  "locationId": 55133,
  "checkInDate": "2026-08-03",
  "checkOutDate": "2026-08-09",
  "street": "Scharrenstraße 22",
  "zipCode": "10178",
  "cityName": "Berlin",
  "districtName": "Berlin",
  "country": "DEU",
  "address": "Scharrenstraße 22, 10178, Berlin, DEU",
  "latitude": 52.513894,
  "longitude": 13.405057,
  "stars": 4,
  "rating": 9.1,
  "ratingCount": 15,
  "recommendationRate": 80,
  "chainName": "Frasers Hospitality",
  "brandName": "Frasers Hospitality",
  "hotelTypes": ["CITY_HOTEL", "BUSINESS_HOTEL"],
  "featureTypes": ["PARKING", "RESTAURANT", "AIRCONDITION"],
  "totalPrice": 850,
  "currency": "EUR",
  "pricePerNight": 141.67,
  "totalAvailCount": 47,
  "roomCategories": ["SUPERIOR"],
  "crsType": "HRS",
  "thumbnailUrl": "https://foto.hrsstatic.com/fotos/...",
  "pictureUrls": ["https://foto.hrsstatic.com/fotos/..."],
  "hotelDetails": {
    "detailUrl": "https://www.hrs.com/en/detail?hn=875998",
    "displayName": "Capri by Fraser Berlin",
    "status": "OPEN",
    "stars": 4,
    "phone": "+49 302007701800",
    "email": "reservations.berlin@capribyfraser.com",
    "homepage": "berlin.capribyfraser.com",
    "latitude": 52.513894,
    "longitude": 13.405057
  }
}
```

### Query and input reference

| Input | Type | Required | Default | Accepted values | Description |
|---|---:|---|---|---|---|
| `locations` | array | No | `["Berlin"]` | city/region names | Locations to search. |
| `locationIds` | array | No | `[]` | HRS location IDs | Skip autocomplete by using IDs. |
| `checkInDate` | string | No | today | `YYYY-MM-DD` | Check-in date; past dates are moved to today. |
| `checkOutDate` | string | No | check-in + 6 nights | `YYYY-MM-DD` | Check-out date. |
| `language` | string | No | `en` | `en`, `de`, `fr`, `es`, `it`, `nl`, `pl` | Language for search and URLs. |
| `roomType` | string | No | `SINGLEROOM` | `SINGLEROOM`, `DOUBLEROOM`, `THREEBEDROOM`, `FOURBEDROOM` | Room type. |
| `rooms` | integer | No | `1` | `1`–`8` | Number of rooms. |
| `adults` | integer | No | `1` | `1`–`6` | Adults per room. |
| `children` | integer | No | `0` | `0`–`6` | Children per room. |
| `currency` | string | No | `EUR` | `EUR`, `USD`, `GBP`, `CHF` | Informational currency field. |
| `includePictures` | boolean | No | `true` | `true` / `false` | Fetch additional pictures. |
| `includeHotelDetails` | boolean | No | `false` | `true` / `false` | Fetch full detail page data. |
| `includeReviews` | boolean | No | `false` | `true` / `false` | Fetch guest reviews. |
| `maxReviewsPerHotel` | integer | No | `0` | `0` = all available | Max reviews per hotel. |
| `maxItems` | integer | No | `0` | `0` = unlimited | Maximum hotels to collect. |
| `proxyConfiguration` | object | No | Apify `RESIDENTIAL` | proxy config | Proxy settings; residential recommended. |

A minimal request and an advanced request:

```json
{ "locations": ["Berlin"], "maxItems": 10 }
```

```json
{
  "locations": ["Berlin"],
  "checkInDate": "2026-08-03",
  "checkOutDate": "2026-08-09",
  "language": "en",
  "roomType": "SINGLEROOM",
  "rooms": 1,
  "adults": 1,
  "currency": "EUR",
  "includePictures": true,
  "includeHotelDetails": true,
  "includeReviews": true,
  "maxReviewsPerHotel": 5,
  "maxItems": 20,
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
```

### Retrieve the data through the API

1. Start the Actor with a JSON input.
2. Wait for the run to finish, or use the synchronous `?waitForFinish=` endpoint when appropriate.
3. Read items from the run's default dataset.
4. Paginate or export the dataset.

A Python example using the Apify client:

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("datascrapers/hrs-scraper").call(
    run_input={"locations": ["Berlin"], "maxItems": 10}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["hotelName"], item["pricePerNight"], item["currency"])
```

For other languages, use the generated API tab on the Actor page. Never place a real token in a URL or example.

### Data quality and record handling

- **Conditional fields** — `hotelDetails`, `reviewSummary`, and `reviews` are present only when their toggles are enabled; `pictureUrls` contains more images when `includePictures` is on.
- **Completeness** — some hotels omit optional fields (chain, brand, ratings) when the source does not provide them.
- **Deduplication** — deduplicate on `hotelId` (or `url`). Re-runs can repeat the same hotel for different date ranges.
- **Retries** — requests are retried with backoff; a residential proxy is recommended for reliable access.
- **Normalization** — dates are `YYYY-MM-DD`; prices are numeric with a `currency` field; coordinates are numeric.
- **Raw versus derived** — all fields are source values; the Actor does not derive pricing across dates.

### Export and pipeline examples

| Destination | Recommended method | Typical use |
|---|---|---|
| PostgreSQL / Supabase | Dataset API or webhook consumer | Hotel price history storage |
| Google Sheets | Apify integration | Rate comparison sheets |
| S3 / cloud storage | Scheduled export or integration | Daily rate snapshots |
| BI / dashboard | Scheduled run + export | Occupancy and pricing dashboards |

### Pricing and cost examples

Billing is pay-per-event, with optional add-on events:

| Event | What counts | Rate (per 1,000) |
|---|---|---|
| Hotel (`dataset-item`) | Each hotel written to the dataset | $3.00 |
| Pictures (`pictures`) | Additional hotel pictures (when `includePictures` is on) | $1.00 |
| Hotel Details (`hotel-details`) | Full detail page (when `includeHotelDetails` is on) | $4.00 |
| Reviews (`hotel-reviews`) | Guest reviews (when `includeReviews` is on) | $2.00 |

A one-time Actor Start event ($0.00005) is also applied per run.

| Records | Estimated base cost |
|---:|---:|
| 1,000 hotels (base only) | $3.00 |
| 10,000 hotels (base only) | $30.00 |
| 1,000 hotels + details + reviews | $9.00 |

Estimates assume the standard tier. Pictures, details, and reviews are only charged when their toggle is enabled.

### Limitations and responsible data use

- The Actor collects publicly accessible HRS hotel data only.
- Prices and availability are valid for the requested dates and can change.
- Some fields are conditional or empty (see Data quality).
- No historical snapshots are guaranteed unless you store the exported datasets yourself.
- You are responsible for complying with applicable privacy, contractual, and legal requirements when using the data.

### Dataset questions

#### What does one dataset item represent?

One hotel, optionally enriched with additional pictures, full detail-page data, and guest reviews when those toggles are enabled.

#### Which field should I use as a unique identifier?

Use `hotelId`; fall back to `url`.

#### Are fields nullable or conditional?

Yes. `hotelDetails`, `reviewSummary`, `reviews`, and extended `pictureUrls` are conditional on the toggles; several optional fields depend on what the source lists for a hotel.

#### Can I retrieve the records as CSV or JSON?

Yes. Export from the run's dataset in JSON, CSV, Excel, HTML, or XML, or read the dataset through the API.

#### What counts as a billable result?

Each hotel is a Hotel charge; pictures, details, and reviews are separate add-on events when their toggles are enabled.

#### Does the Actor return historical data?

No. Each run returns the records available for the requested dates. Schedule recurring runs to build your own history.

### Related datasets from Data Scrapers

- **Booking.com Scraper** — hotel listings with optional details and pricing calendars, for cross-platform rate comparison.
- **TripAdvisor Reviews Scraper** — hotel review records for reputation and sentiment analysis.
- **OpenTable Scraper** — restaurant listings and availability, adjacent to hospitality research.
- **Skyscanner Scraper** — flight and travel search data for broader travel intelligence.

### Data Scrapers support

Need an additional field, record type, or export workflow? Contact Data Scrapers at stardustspotlight@gmail.com. Include a sample source URL, the required fields, the expected record volume, and your preferred delivery format.

# Actor input Schema

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

City or region names to search on HRS (e.g. Berlin, Munich, Paris). Resolved via the HRS location autocomplete API.

## `locationIds` (type: `array`):

Optional HRS location IDs to skip autocomplete (e.g. 55133 for Berlin). Use instead of or together with location names.

## `checkInDate` (type: `string`):

Check-in date in YYYY-MM-DD format. Defaults to today. If a past date is provided (including stale prefill values), it is automatically moved to today and check-out is set to six nights later.

## `checkOutDate` (type: `string`):

Check-out date in YYYY-MM-DD format. Defaults to six nights after check-in. Adjusted automatically when check-in is moved forward from a past date.

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

Language code for location search and hotel URLs.

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

HRS room type for the search request.

## `rooms` (type: `integer`):

Number of rooms to request.

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

Number of adults per room.

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

Number of children per room.

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

Expected price currency (informational; prices come from the API).

## `includePictures` (type: `boolean`):

Fetch additional hotel pictures beyond the search thumbnail.

## `includeHotelDetails` (type: `boolean`):

Fetch full hotel detail page data (description, amenities, room offers, contact info, all pictures). Adds extra API calls per hotel.

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

Fetch guest reviews and extended rating breakdowns from the hotel detail page. Adds extra API calls per hotel.

## `maxReviewsPerHotel` (type: `integer`):

Maximum number of guest reviews to include per hotel when Include reviews is enabled (0 = all available).

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

Maximum number of hotels to scrape (0 = unlimited)

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

Proxy settings for anti-bot protection

## Actor input object example

```json
{
  "locations": [
    "Berlin"
  ],
  "locationIds": [],
  "language": "en",
  "roomType": "SINGLEROOM",
  "rooms": 1,
  "adults": 1,
  "children": 0,
  "currency": "EUR",
  "includePictures": true,
  "includeHotelDetails": false,
  "includeReviews": false,
  "maxReviewsPerHotel": 10,
  "maxItems": 10,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset containing scraped HRS hotel records

## `runStats` (type: `string`):

Run statistics including record count and timestamps

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "locations": [
        "Berlin"
    ],
    "locationIds": [],
    "includeHotelDetails": false,
    "includeReviews": false,
    "maxReviewsPerHotel": 10,
    "maxItems": 10,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("datascrapers/hrs-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "locations": ["Berlin"],
    "locationIds": [],
    "includeHotelDetails": False,
    "includeReviews": False,
    "maxReviewsPerHotel": 10,
    "maxItems": 10,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

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

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

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

```

## CLI example

```bash
echo '{
  "locations": [
    "Berlin"
  ],
  "locationIds": [],
  "includeHotelDetails": false,
  "includeReviews": false,
  "maxReviewsPerHotel": 10,
  "maxItems": 10,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call datascrapers/hrs-scraper --silent --output-dataset

```

## MCP server setup

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