# Agoda Reviews Extractor (`kawsar/agoda-reviews-extractor`) Actor

Agoda reviews scraper that pulls hotel guest reviews, ratings, hotel replies, room types, and reviewer countries from any Agoda hotel URL, so SEO teams and hotels can track reputation and check competitors without copying reviews by hand.

- **URL**: https://apify.com/kawsar/agoda-reviews-extractor.md
- **Developed by:** [Kawsar](https://apify.com/kawsar) (community)
- **Categories:** Travel, SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.99 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## Agoda Reviews Extractor: Scrape Hotel Guest Reviews from Agoda

Agoda Reviews Extractor is an Agoda reviews scraper that pulls guest reviews from any Agoda hotel page and returns them as structured data. Paste one or more hotel URLs and the actor collects ratings, review titles, full comments, hotel replies, room types, reviewer countries, and guest photos. It reads the hotel ID from each page for you, so you never have to dig through the source to find it.

Use it to track hotel reputation, watch competitors, or feed review text into sentiment analysis and dashboards, without copying and pasting reviews by hand.

### Use cases

- **Reputation tracking**: pull every recent Agoda review for your property and watch how ratings move over time
- **Competitor research**: scrape reviews for nearby hotels to see what guests praise and complain about
- **Sentiment analysis**: feed review comments into your own NLP pipeline to find recurring themes
- **SEO and content**: collect real guest quotes and ratings to enrich hotel listings and landing pages
- **Market research**: compare traveler types, room types, and country breakdowns across a set of hotels
- **Reporting**: export review data to Google Sheets or Excel for weekly stakeholder reports

### Input

Give the actor at least one hotel URL, or a numeric hotel ID. Everything else has sensible defaults.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `startUrls` | array | (empty) | One or more Agoda hotel page URLs to scrape. The actor reads the hotel ID from each page. |
| `hotelId` | integer | (none) | Agoda numeric hotel ID. Use instead of URLs if you already know it. Ignored when URLs are given. |
| `maxReviews` | integer | 100 | Maximum reviews to collect per hotel. |
| `sortBy` | string | `7` (Most helpful) | Review order: `7` Most helpful, `1` Most recent, `2` Rating high to low, `3` Rating low to high. |
| `language` | string | `en-gb` | Language for review text and labels. Options: English (UK/US), Thai, Chinese, Japanese, Korean. |
| `hotelProviderId` | integer | 332 | Advanced. Primary review provider. Leave as Agoda (332) for standard hotel pages. |
| `reviewProviderIds` | array | Agoda + partners | Advanced. Review sources to include. The default set returns the widest pool of reviews. |
| `requestTimeoutSecs` | integer | 30 | Advanced. Per-request timeout in seconds. |
| `proxyConfiguration` | object | Datacenter (Anywhere) | Proxy type and location for requests. Supports Datacenter, Residential, Special, and custom proxies. Optional. |

#### Example input

```json
{
    "startUrls": [
        "https://www.agoda.com/the-travellers-hotel_4/hotel/bangkok-th.html"
    ],
    "maxReviews": 100,
    "sortBy": "7",
    "language": "en-gb",
    "proxyConfiguration": { "useApifyProxy": true }
}
```

### What data does this actor extract?

The actor stores one record per review in the dataset. Each entry looks like this:

```json
{
    "hotelId": 39820584,
    "hotelName": "Palette The Travellers Hotel Bangkok",
    "reviewId": 1110462741,
    "providerName": "Agoda",
    "rating": 10.0,
    "ratingText": "Exceptional",
    "reviewTitle": "Worth the price paid very much.",
    "reviewText": "Good hotel, spacious room, very cheap price, excellent location...",
    "fullComment": "Good hotel, spacious room, very cheap price, excellent location...",
    "reviewPositives": "",
    "reviewNegatives": "",
    "originalComment": "โรงแรมดี ห้องกว้าง ราคาถูกมาก...",
    "originalLanguage": "th",
    "reviewDate": "2026-04-24T05:49:00+07:00",
    "checkInDate": "2026-04-23T00:00:00+07:00",
    "stayMonth": "April 2026",
    "reviewerName": "Achiravich",
    "reviewerCountry": "Thailand",
    "travelerType": "Solo traveler",
    "roomType": "Deluxe Twin",
    "lengthOfStay": 1,
    "hasHotelResponse": true,
    "responderName": "Palette The Travellers Hotel Bangkok",
    "responseText": "Thank you for your kind words...",
    "reviewImages": [
        "https://pix6.agoda.net/generic/ace9131245c52a37d65d9a8bc4c7158e.jpeg?ce=3"
    ],
    "reviewPageUrl": "https://www.agoda.com/en-gb/the-travellers-hotel-h39820584/reviews/bangkok-th.html",
    "scrapedAt": "2026-08-12T04:36:20.831574+00:00"
}
```

| Field | Type | Description |
|-------|------|-------------|
| `hotelId` | integer | Agoda hotel ID the review belongs to. |
| `hotelName` | string | Name of the hotel. |
| `reviewId` | integer | Unique Agoda review ID. |
| `providerName` | string | Source of the review, such as Agoda. |
| `rating` | number | Score on Agoda's 0 to 10 scale. |
| `ratingText` | string | Word label for the score, such as Exceptional. |
| `reviewTitle` | string | Review title in the selected language. |
| `reviewText` | string | Review body exactly as the source sent it. Empty for sources that split text into liked/disliked. |
| `fullComment` | string | Complete guest comment, always populated when the guest wrote anything. Use this if you just want the text. |
| `reviewPositives` | string | What the guest liked, when listed separately (common for Booking.com reviews). |
| `reviewNegatives` | string | What the guest disliked, when listed separately (common for Booking.com reviews). |
| `originalTitle` | string | Title in the language it was written in. |
| `originalComment` | string | Body in the language it was written in. |
| `originalLanguage` | string | Language code the review was written in. |
| `reviewDate` | string | Date the review was posted. |
| `checkInDate` | string | Guest check-in date. |
| `checkOutDate` | string | Guest check-out date. |
| `stayMonth` | string | Month and year of the stay. |
| `reviewerName` | string | Display name of the guest. |
| `reviewerCountry` | string | Country the guest is from. |
| `reviewerCountryCode` | string | Two-letter country code. |
| `travelerType` | string | Travel group, such as Business traveler or Couple. |
| `roomType` | string | Room type the guest stayed in. |
| `lengthOfStay` | integer | Number of nights stayed. |
| `helpfulVotes` | integer | Helpful votes the review received. |
| `hasHotelResponse` | boolean | True only when the hotel actually replied. Response fields are blank when false. |
| `responderName` | string | Hotel representative who replied. Blank when there was no reply. |
| `responseText` | string | Hotel's reply to the review. |
| `reviewImages` | array | URLs of guest photos attached to the review. |
| `reviewPageUrl` | string | URL of the hotel's Agoda reviews page. |
| `scrapedAt` | string | When the review was scraped (UTC). |

### How it works

1. For each hotel URL, the actor loads the page and reads the numeric hotel ID from it. If you pass a hotel ID directly, this step is skipped.
2. It calls Agoda's review endpoint and pages through results until it hits your `maxReviews` limit or runs out of reviews.
3. Each review is flattened into a clean record with the guest text, the hotel reply, and stay details.
4. Records are saved to the dataset, ready to export or push to another app.

### FAQ

**How do I find a hotel's URL?**
Search for the hotel on Agoda, open its page, and copy the URL from your browser. Paste it into `startUrls`. You do not need the numeric ID, the actor finds it for you.

**Can I scrape reviews for several hotels at once?**
Yes. Add as many hotel URLs as you want to `startUrls` and the actor processes them one after another.

**Some fields are empty on certain reviews. Is data missing?**
No. Agoda pulls reviews from several sources, and each source sends different fields. Agoda's own reviews fill `reviewText`, check-in dates, room type, and country. Booking.com reviews instead split the comment into `reviewPositives` and `reviewNegatives` and often omit stay details. Nothing is dropped, the empty fields simply were not provided by that source. Read `fullComment` to always get the complete review text regardless of source.

**Why is `responderName` sometimes blank when there is a reply on the site?**
The actor only fills the hotel response fields when there is real reply text. Agoda's raw data lists the hotel name as the responder on every review even when no reply exists, so blanking those out keeps the data honest. Check `hasHotelResponse` to know for sure.

**Does it keep reviews written in other languages?**
Yes. Every review comes with its original text and language code, plus the machine translation into the language you selected.

**How many reviews can it collect per hotel?**
Set `maxReviews` to whatever you need. Agoda exposes a capped pool of public reviews per hotel on its crawlable pages, and the actor collects up to that pool or your limit, whichever comes first.

**Do I need a proxy?**
Not for small runs. For larger jobs or if Agoda starts blocking requests, turn on Apify Proxy and switch to Residential if needed.

### Integrations

Connect Agoda Reviews Extractor with other apps and services using [Apify integrations](https://apify.com/integrations). You can integrate with Make, Zapier, Slack, Airbyte, GitHub, Google Sheets, Google Drive, and many more. You can also use [webhooks](https://docs.apify.com/integrations/webhooks) to trigger actions whenever results are available.

Start pulling Agoda hotel reviews now: drop in a hotel URL, run the actor, and get structured review data you can analyze, report on, or feed into your own tools.

# Actor input Schema

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

One or more Agoda hotel page URLs to scrape reviews from. Paste the full hotel page URL (for example the page you land on after searching a hotel). The actor reads the hotel ID from each page automatically. Leave empty only if you supply a Hotel ID below.

## `hotelId` (type: `integer`):

Agoda numeric hotel ID. Use this only if you already know the ID and want to skip URLs. If both URLs and a Hotel ID are given, the URLs are used and this is ignored.

## `maxReviews` (type: `integer`):

Maximum number of reviews to collect per hotel. Keeps runs fast and predictable. Set higher to pull more, or lower for a quick sample.

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

Order in which reviews are pulled from Agoda.

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

Language for review content and Agoda's own text fields (rating labels, dates). Reviews written in other languages still come through, along with their machine translation into the selected language.

## `hotelProviderId` (type: `integer`):

Advanced. Primary review provider ID. Leave at 332 (Agoda) unless you know you need a different source.

## `reviewProviderIds` (type: `array`):

Advanced. List of review source IDs to include. The default set covers Agoda plus partner sources, which returns the widest pool of reviews.

## `requestTimeoutSecs` (type: `integer`):

Advanced. How long to wait for each Agoda request before giving up.

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

Select proxies to use for requests. Helps avoid IP blocking and rate limits. Datacenter proxies are fastest; Residential proxies are harder to detect.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.agoda.com/the-travellers-hotel_4/hotel/bangkok-th.html"
  ],
  "hotelId": 39820584,
  "maxReviews": 100,
  "sortBy": "7",
  "language": "en-gb",
  "hotelProviderId": 332,
  "reviewProviderIds": [
    332,
    3038,
    27901,
    28999,
    29100,
    27999,
    27980,
    27989,
    29014
  ],
  "requestTimeoutSecs": 30,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `reviews` (type: `string`):

All extracted reviews as dataset items (ratings, guest comments, hotel replies, room type, traveler country, and photos).

# 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.agoda.com/the-travellers-hotel_4/hotel/bangkok-th.html"
    ],
    "maxReviews": 100,
    "hotelProviderId": 332,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("kawsar/agoda-reviews-extractor").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.agoda.com/the-travellers-hotel_4/hotel/bangkok-th.html"],
    "maxReviews": 100,
    "hotelProviderId": 332,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("kawsar/agoda-reviews-extractor").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": [
    "https://www.agoda.com/the-travellers-hotel_4/hotel/bangkok-th.html"
  ],
  "maxReviews": 100,
  "hotelProviderId": 332,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call kawsar/agoda-reviews-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,kawsar/agoda-reviews-extractor"
        }
    }
}

```

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/zCzoC2l8LKHE1aXbW/builds/drfyK0jPg6wQ91nW7/openapi.json
