# Agoda Scraper — Hotel Reviews, Ratings & Prices (`tortuga/agoda-scraper`) Actor

Scrape Agoda hotel reviews (Agoda and Booking.com), hotel details with scores and amenities, and search results with prices per night. Monitor new reviews on a schedule.

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

## Pricing

from $4.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

## Agoda Scraper — Hotel Reviews, Ratings & Prices

Scrape **Agoda hotel reviews** (from Agoda guests and the Booking.com reviews Agoda shows on the same page), **hotel details** (score, sub-scores, amenities, check-in/out times, coordinates, cheapest price per room type) and **search results with the price per night** for any destination and dates. Export to JSON, CSV or Excel, or call it from your app through the Apify API.

- Reviews for any hotel URL or hotel id: overall score, title, review text or liked / disliked parts, review date, stay dates, traveller type, room type, nights, reviewer name and country as shown, the hotel's response, source (Agoda or Booking.com) and language.
- Deep: all reviews Agoda serves for a hotel, typically 1,000-4,000 per popular hotel, in every language.
- Monitoring: schedule it and get only new reviews (or only changed prices) each run; repeats are not charged.
- Fast and cheap to run: plain HTTP through Apify datacenter proxies, about 1,000 reviews per 15-30 seconds.

### What data does it extract?

#### Reviews (`mode: reviews`, default)

| Field | Example |
|---|---|
| `reviewId` | `1189163426` |
| `hotelId`, `hotelName`, `hotelUrl` | `10715`, `The Peninsula Bangkok`, `https://www.agoda.com/the-peninsula-bangkok/hotel/bangkok-th.html` |
| `provider` | `Agoda` or `Booking.com` |
| `rating`, `ratingText` | `9.2`, `Exceptional` (10-point scale) |
| `title`, `text` | `Always a great option`, full review text |
| `positives`, `negatives` | Liked / disliked parts (Booking.com style reviews) |
| `reviewDate` | `2026-10-01T01:16:00+07:00` |
| `checkInDate`, `checkOutDate`, `stayMonth`, `lengthOfStay` | `2026-09-26`, `2026-09-29`, `September 2026`, `3` |
| `travellerType`, `roomType` | `Couple`, `Grand Deluxe Room` |
| `reviewerName`, `reviewerCountry`, `reviewerCountryCode` | `Lynette`, `Australia`, `AU` (as Agoda shows them) |
| `language`, `originalTitle`, `originalText` | `en`; original text when Agoda shows a translation |
| `helpfulVotes`, `photos` | Votes and guest photo URLs |
| `hotelResponse`, `hotelResponseDate`, `hotelResponderName` | The property's reply |
| `changeType` | `new` (only with monitoring) |

#### Hotel details (`mode: hotels`)

`hotelId`, `name`, `url`, `accommodationType`, `starRating`, `address`, `street`, `area`, `city`, `country`, `postalCode`, `latitude`, `longitude`, `reviewScore`, `reviewScoreText`, `reviewCount`, `reviewsWithTextCount`, `scoreBreakdown` (Cleanliness, Service, Facilities, Location, Room comfort, Value for money, Food), `scoreDistribution`, `reviewProviders`, `checkInFrom`, `checkOutUntil`, `amenities`, `amenityGroups`, `languagesSpoken`, `highlights`, `locationHighlight`, `description`, `images`, and with a check-in date: `checkIn`, `nights`, `available`, `priceFrom` (cheapest per night, before taxes), `currency`, `cheapestRoom`, `rooms` (cheapest price per room type).

#### Search results (`mode: search`)

`hotelId`, `name`, `url`, `accommodationType`, `starRating`, `area`, `city`, `country`, `latitude`, `longitude`, `reviewScore`, `reviewCount`, `available`, `soldOut`, `pricePerNight` (before taxes), `pricePerNightWithTaxes`, `originalPricePerNight` (struck-through price), `currency`, `checkIn`, `nights`.

### How to scrape Agoda reviews

1. Paste one or more Agoda hotel URLs into **Agoda URLs** (any hotel page, review page or link with tracking parameters), or hotel ids into **Hotel ids**.
2. Set **Max reviews per hotel** (and **Max items** for the whole run).
3. Optional: pick **Review sources** (Agoda / Booking.com), **Review languages**, **Sort reviews by**, or **Only reviews newer than**.
4. Run it and download the dataset.

Input example:

```json
{
  "mode": "reviews",
  "startUrls": [{ "url": "https://www.agoda.com/the-peninsula-bangkok/hotel/bangkok-th.html" }],
  "maxReviewsPerHotel": 500,
  "maxItems": 500
}
```

Output example:

```json
{
  "type": "review",
  "reviewId": "1189163426",
  "hotelId": 10715,
  "hotelName": "The Peninsula Bangkok",
  "hotelUrl": "https://www.agoda.com/the-peninsula-bangkok/hotel/bangkok-th.html",
  "provider": "Agoda",
  "rating": 9.2,
  "ratingText": "Exceptional",
  "title": "Always a great option",
  "text": "We have visited the Peninsula Bangkok multiple times as it never fails in quality...",
  "reviewDate": "2026-10-01T01:16:00+07:00",
  "checkInDate": "2026-09-26",
  "checkOutDate": "2026-09-29",
  "lengthOfStay": 3,
  "travellerType": "Group",
  "roomType": "Grand Deluxe Room",
  "reviewerName": "Lynette",
  "reviewerCountry": "Australia",
  "language": "en",
  "hotelResponse": null
}
```

You can also review whole destinations: put a search URL (`https://www.agoda.com/search?city=9395`), a city page (`https://www.agoda.com/city/bangkok-th.html`) or a destination name (`Bangkok`) in the input and the actor reads the reviews of the top hotels (**Max hotels per search**, Agoda's own ranking).

### How to get Agoda hotel prices for my dates

Use **Search results with prices** mode with a destination and dates:

```json
{
  "mode": "search",
  "destinations": ["Lisbon"],
  "checkIn": "2026-12-01",
  "nights": 2,
  "adults": 2,
  "currency": "EUR",
  "maxItems": 200
}
```

Each result has the price per night before taxes, the price with taxes and fees, the struck-through price when Agoda shows a discount, and whether the hotel is available. Search page URLs copied from Agoda keep their dates. For a single hotel's room prices use **Hotel details** mode with a check-in date: you get the cheapest price per room type (in USD).

### Monitor changes on a schedule

Turn on **Only new or changed items** and save the input as a task, then add a Schedule in Apify (for example daily). In reviews mode each run checks the newest **Max reviews per hotel** reviews of every hotel and saves only reviews it has not saved before; **Only reviews newer than** (`1 day`, `7 days` or a date) narrows it further. In hotels and search mode an item is saved again only when its price, struck-through price, availability or review score changed. Unchanged items are not output and not charged. New items carry `changeType: "new"`, changed ones `changeType: "changed"` plus `previousValues` with the old values of the fields that changed. Use **Monitoring key** to keep several schedules on the same input apart.

### Does it work without login or an Agoda account?

Yes. It reads the same public JSON the Agoda website loads for any visitor, with no login and no cookies from you. The default Apify datacenter proxy is enough; no residential or Unblocker proxy is needed.

### How many reviews can I get per hotel?

All that Agoda serves for the hotel: typically 1,000-4,000 for popular hotels (Agoda guests plus Booking.com guests, every language). Agoda counts reviews without text in its headline review number, so the number of written reviews is lower than "Based on N reviews" (`reviewsWithTextCount` in hotel details). Reviews come in Agoda's order: English first, newest first within each language. With a date filter, a language filter or monitoring, every language is read newest first and merged by date.

### How much does it cost?

Pay per result: $0.004 per review, $0.004 per hotel details item, $0.003 per search result. Platform usage is tiny (a 1,000-review run uses well under $0.01 of compute), and you can cap spend with **Max items**.

### Proxy note

The default `{"useApifyProxy": true}` (datacenter) works. Agoda's review service answers part of all requests with an empty page; the actor detects that and retries on a new proxy IP, so you do not have to.

### Is it legal to scrape Agoda?

The actor collects publicly visible data: hotel information, prices and guest reviews with the reviewer name and country as Agoda displays them. It does not log in or access anything private. Reviews contain personal data (names, countries); make sure your use complies with GDPR and similar laws and with Agoda's terms, and do not use the data to contact or profile individuals.

# Actor input Schema

## `mode` (type: `string`):

reviews: one item per guest review (Agoda and Booking.com reviews shown on Agoda). hotels: one details item per hotel (scores, sub-scores, amenities, check-in/out, coordinates; with a check-in date also prices per room type). search: one item per hotel in a destination's search results with the price per night.

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

Hotel pages (https://www.agoda.com/the-peninsula-bangkok/hotel/bangkok-th.html; review pages and URLs with tracking parameters work too), search pages (https://www.agoda.com/search?city=9395\&checkIn=2026-12-01\&los=2) or city pages (https://www.agoda.com/city/bangkok-th.html). In reviews and hotels mode a search or city page stands for its top hotels (see Max hotels per search).

## `hotelIds` (type: `array`):

Agoda numeric hotel ids (the hotel_id / hid in Agoda links), e.g. 10715.

## `destinations` (type: `array`):

City or area names to search, e.g. "Bangkok" or "Lisbon". Looked up with Agoda's own destination search (an area maps to its city).

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

Stop after this many items in total (reviews, hotels or search results across all inputs).

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

Reviews mode: cap per hotel. Agoda serves up to a few thousand reviews per hotel (Agoda and Booking.com reviews counted together).

## `maxHotelsPerSearch` (type: `integer`):

Reviews and hotels mode: how many top hotels (Agoda's ranking) of each search page, city page or destination are processed.

## `reviewSources` (type: `array`):

Agoda shows its own verified-guest reviews and Booking.com reviews of the same hotel. Empty = both.

## `reviewLanguages` (type: `array`):

Only reviews written in these languages. Empty = all languages (Agoda lists English first, then the other languages).

## `sortReviewsBy` (type: `string`):

Order Agoda uses inside each review language. 'Only reviews newer than' always uses newest first.

## `reviewsNewerThan` (type: `string`):

Only reviews newer than: a date (YYYY-MM-DD) or a period such as '7 days' or '24 hours'. Each review language is read newest first and paging stops once a whole page is older.

## `onlyNewOrChanged` (type: `boolean`):

Remember what earlier runs of this search returned and output only new items or items whose price/status changed. Use with a Schedule; unchanged items are not charged. Reviews: each run checks the newest 'Max reviews per hotel' reviews of every hotel and saves only reviews not seen before. Hotels: compared on cheapest price, review score and stars. Search: price per night, struck-through price, availability and review score.

## `monitoringKey` (type: `string`):

Name for this watch, so several schedules on the same search stay separate; defaults to a key derived from the search input.

## `checkIn` (type: `string`):

Search mode and hotels mode: check-in date (YYYY-MM-DD) for prices. Search without a date uses the date in the search URL, else 7 days from today. Hotel details without a date have no prices.

## `nights` (type: `integer`):

Length of stay for prices (prices are per night).

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

Guests for prices.

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

Rooms for prices.

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

Search mode: currency of the prices (ISO code such as USD, EUR, THB). Hotel details prices are in USD.

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

Apify datacenter proxy (default) works for Agoda; no residential or Unblocker proxy is needed.

## Actor input object example

```json
{
  "mode": "reviews",
  "startUrls": [
    {
      "url": "https://www.agoda.com/the-peninsula-bangkok/hotel/bangkok-th.html"
    }
  ],
  "hotelIds": [],
  "destinations": [],
  "maxItems": 100,
  "maxReviewsPerHotel": 100,
  "maxHotelsPerSearch": 20,
  "reviewSources": [],
  "reviewLanguages": [],
  "sortReviewsBy": "newest",
  "onlyNewOrChanged": false,
  "nights": 1,
  "adults": 2,
  "rooms": 1,
  "currency": "USD",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (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 = {
    "startUrls": [
        {
            "url": "https://www.agoda.com/the-peninsula-bangkok/hotel/bangkok-th.html"
        }
    ],
    "hotelIds": [],
    "destinations": [],
    "reviewSources": [],
    "reviewLanguages": [],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("tortuga/agoda-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": [{ "url": "https://www.agoda.com/the-peninsula-bangkok/hotel/bangkok-th.html" }],
    "hotelIds": [],
    "destinations": [],
    "reviewSources": [],
    "reviewLanguages": [],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("tortuga/agoda-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 '{
  "startUrls": [
    {
      "url": "https://www.agoda.com/the-peninsula-bangkok/hotel/bangkok-th.html"
    }
  ],
  "hotelIds": [],
  "destinations": [],
  "reviewSources": [],
  "reviewLanguages": [],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call tortuga/agoda-scraper --silent --output-dataset

```

## MCP server setup

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