> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zenrows.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> The Zenrows API (Fetch, Extract via extract=auto, and Batch) is described in OpenAPI 3.1 at https://www.zenrows.com/openapi.json and listed in the RFC 9727 API catalog at https://www.zenrows.com/.well-known/api-catalog. Use the spec for exact parameter names and types.

# Travel: hotels, rates and reviews

> Get hotel details and room prices from Booking.com, compare them by traveler location, and collect Trustpilot reviews with Zenrows.

Travel and review data feeds rate shopping, hotel benchmarking and reputation monitoring. This page covers hotel details, room prices as travelers in different countries see them, and public reviews, using Booking.com and Trustpilot as the worked examples.

**Uses:** [Fetch](/fetch/api-reference) with [`js_render`](/fetch/features/js-rendering), [`premium_proxy`](/fetch/features/premium-proxy), [`proxy_country`](/fetch/features/proxy-country) and [`wait_for`](/fetch/features/wait-for); [Extract](/extract/introduction) (`extract=auto`); [`css_extractor`](/fetch/features/css-extractor); [Adaptive Stealth Mode](/fetch/features/adaptive-stealth-mode) (`mode=auto`)

## Ask your AI agent

With the [Zenrows MCP server](/mcp/overview) connected to Claude, Cursor or any MCP client, paste this prompt. Your agent picks the right Zenrows tools and settings on its own.

```text theme={"dark"}
Use Zenrows to read
https://www.booking.com/hotel/gb/the-savoy.html?checkin=2026-11-12&checkout=2026-11-13&group_adults=2&no_rooms=1
as a visitor from the US, after the room table loads.
Tell me the review score, the number of reviews, the room types and the check-in time.
```

## Get hotel details from Booking.com

Booking.com is prepared for Extract, so `extract=auto` returns the property, location, review scores, room types and house rules as JSON. Include check-in and check-out dates in the URL so the page shows availability, and wait for the room table (`.hprt-table`) so the whole page is in place before Extract reads it.

<CodeGroup>
  ```python Python (Requests) theme={"dark"}
  import json
  import requests

  params = {
      "apikey": "YOUR_ZENROWS_API_KEY",
      "url": "https://www.booking.com/hotel/gb/the-savoy.html?checkin=2026-11-12&checkout=2026-11-13&group_adults=2&no_rooms=1",
      "js_render": "true",
      "premium_proxy": "true",
      "proxy_country": "us",
      "wait_for": ".hprt-table",
      "extract": "auto",
      "extract_fields": "property.name,property.property_type,location.city,location.street_address,review_summary.overall_score,review_summary.review_count,room_types.name,house_rules.checkin_from",
  }

  response = requests.get("https://api.zenrows.com/v1/", params=params, timeout=180)
  response.raise_for_status()
  print(json.dumps(response.json()["parsed"], indent=2))
  ```

  ```bash cURL theme={"dark"}
  curl "https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fwww.booking.com%2Fhotel%2Fgb%2Fthe-savoy.html%3Fcheckin%3D2026-11-12%26checkout%3D2026-11-13%26group_adults%3D2%26no_rooms%3D1&js_render=true&premium_proxy=true&proxy_country=us&wait_for=.hprt-table&extract=auto&extract_fields=property.name%2Cproperty.property_type%2Clocation.city%2Clocation.street_address%2Creview_summary.overall_score%2Creview_summary.review_count%2Croom_types.name%2Chouse_rules.checkin_from"
  ```
</CodeGroup>

## Example output

```json theme={"dark"}
{
  "house_rules": {
    "checkin_from": "3:00 PM"
  },
  "location": {
    "city": "London",
    "street_address": "Strand"
  },
  "property": {
    "name": "The Savoy",
    "property_type": "Hotel"
  },
  "review_summary": {
    "overall_score": 9.4,
    "review_count": 1433
  },
  "room_types": [
    { "name": "Superior Queen Room" },
    { "name": "Deluxe King Room" },
    { "name": "Luxury King Room" },
    { "name": "Luxury Twin Room with Two Single Beds" }
  ]
}
```

Omit `extract_fields` to get every group, including `facilities`, `photos`, `fine_print`, the coordinates in `location` and the per-category scores in `review_summary` (cleanliness, comfort, location, staff, value for money).

## Compare room prices by traveler location

Hotel sites show prices in the traveler's currency and can quote different rates by market. Request the same dates from different countries with `proxy_country`, and read the room names and prices with `css_extractor`:

```python Python (Requests) theme={"dark"}
import json
import requests

hotel_url = (
    "https://www.booking.com/hotel/gb/the-savoy.html"
    "?checkin=2026-11-12&checkout=2026-11-13&group_adults=2&no_rooms=1"
)
selectors = {"rooms": ".hprt-roomtype-icon-link", "prices": ".hprt-table .bui-price-display__value"}

for country in ["us", "gb"]:
    params = {
        "apikey": "YOUR_ZENROWS_API_KEY",
        "url": hotel_url,
        "js_render": "true",
        "premium_proxy": "true",
        "proxy_country": country,
        "wait_for": ".hprt-table",
        "css_extractor": json.dumps(selectors),
    }
    response = requests.get("https://api.zenrows.com/v1/", params=params, timeout=180)
    response.raise_for_status()
    data = response.json()
    print(country, data["rooms"][0], "from", data["prices"][0])
```

```text theme={"dark"}
us Superior Queen Room from $1,031
gb Superior Queen Room from £941
```

`prices` lists every rate row in the room table, in page order, so a room with several rate plans has several prices. Add the selector for the rate conditions, or loop over `prices` to pick the lowest.

## Collect reviews from Trustpilot

Review pages render each review in a card. `css_extractor` returns one list per field, so the star ratings, titles and texts line up review by review. The selectors below use Trustpilot's `data-*` attributes, which are more stable than its class names:

```python Python (Requests) theme={"dark"}
import json
import requests

selectors = {
    "trust_score": "[data-rating-typography]",
    "stars": "[data-service-review-rating] @data-service-review-rating",
    "titles": "[data-service-review-title-typography]",
    "texts": "[data-service-review-text-typography]",
}

params = {
    "apikey": "YOUR_ZENROWS_API_KEY",
    "url": "https://www.trustpilot.com/review/www.getyourguide.com",
    "mode": "auto",
    "css_extractor": json.dumps(selectors),
}

response = requests.get("https://api.zenrows.com/v1/", params=params, timeout=180)
response.raise_for_status()
data = response.json()

print("TrustScore:", data["trust_score"])
reviews = [
    {"stars": int(s), "title": t, "text": x}
    for s, t, x in zip(data["stars"], data["titles"], data["texts"])
]
print(len(reviews), "reviews")
print("First review:", {**reviews[0], "text": reviews[0]["text"][:30] + "..."})
print("Average of this page:", round(sum(r["stars"] for r in reviews) / len(reviews), 1))
```

```text theme={"dark"}
TrustScore: 3.9
20 reviews
First review: {'stars': 2, 'title': 'death valley star tour', 'text': 'we went yo death valley star t...'}
Average of this page: 3.4
```

The selectors leave out reviewer names and profiles, so you keep only the review content. For sentiment analysis or summaries with an LLM, request the page with `response_type=markdown` instead and send the text to your model, see [Markdown for LLMs](/academy/fetch/markdown-for-llms).

## Customize it

| Change | How |
| - | - |
| Another hotel or dates | Change the hotel path and `checkin`, `checkout`, `group_adults` in the Booking.com URL |
| Another market's prices | Change `proxy_country` to any ISO country code, see [Proxy country](/fetch/features/proxy-country) |
| More Trustpilot reviews | Add `?page=2`, `?page=3` to the review URL |
| Hundreds of hotels or review pages | Send the URLs to one [Batch](/academy/scrape-from-a-list-of-urls) job with the same parameters in `zenrows_params` |
| A daily rate check | Run the job on a [schedule](/academy/batch/scheduled-jobs) |
| Hotel data across many cities | See [Build a price monitor](/academy/build-price-monitoring) |

## Troubleshooting

* **`no_data_extracted` (422) on a hotel page**: Extract read the page before the room table was in place. Use `js_render=true` and `premium_proxy=true` with `wait_for=.hprt-table`, as in the examples. See [no\_data\_extracted](/api-error-codes#no_data_extracted).
* **`prices` is empty**: the page has no availability for those dates, or the table hadn't loaded. Check the dates in the URL and keep `wait_for=.hprt-table`.
* **Prices are in an unexpected currency**: the currency follows the request's location. Set `proxy_country` to the market you want.
* **Review lists have different lengths**: some reviews have no title or text. Read the cards in the order they appear and compare the list lengths before you pair them.

## Related recipes

<CardGroup cols={2}>
  <Card title="Get content as seen from any country" icon="world" href="/academy/fetch/geotargeting">
    Geotarget any request with proxy\_country.
  </Card>

  <Card title="Scrape JavaScript-rendered pages" icon="clock" href="/academy/fetch/javascript-pages">
    Render JavaScript and wait for the elements you need.
  </Card>

  <Card title="Get structured JSON from any page" icon="wand" href="/academy/extract/auto-extraction">
    How extract=auto and prepared domains work.
  </Card>

  <Card title="Build a price monitor" icon="chart-line" href="/academy/build-price-monitoring">
    Track rates on a schedule and store the history.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.