# Agoda Scraper - Hotels, Prices, Reviews & Ratings (`scrapesage/agoda-scraper`) Actor

Scrape Agoda hotels: full property details, star ratings, amenities, location, category review scores and complete guest reviews with reviewer demographics and hotel responses. Search by hotel name or paste hotel URLs. No browser needed. Export to JSON, CSV or Excel.

- **URL**: https://apify.com/scrapesage/agoda-scraper.md
- **Developed by:** [Scrape Sage](https://apify.com/scrapesage) (community)
- **Categories:** Travel, Lead generation, Automation
- **Stats:** 3 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 hotel scrapeds

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 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 Scraper — Hotels, Ratings, Amenities & Guest Reviews

Extract **complete hotel data from [Agoda](https://www.agoda.com)** — the full property profile (star rating, location, geo-coordinates, 100+ amenities, room types, photos), the **category review scores** guests actually care about (cleanliness, location, service, room comfort, value for money — each with the city average), and **every guest review** with reviewer demographics, traveler type, stay dates and the hotel's own response.

No login, no cookies, no browser — fast, reliable JSON extraction that works on **any Agoda hotel**, in any country.

### Why this Agoda scraper?

Most hotel scrapers return a name, a price and a single review score. This actor reads Agoda's public property and review endpoints directly and ships the **richest dataset in the category** — one clean record per hotel and one per review, with nothing dropped.

| Data | Typical scrapers | This actor |
|---|---|---|
| Hotel name, star rating, property type | ✅ | ✅ |
| Full address + **latitude/longitude** | partial | ✅ |
| Overall review score + **review count** | ✅ | ✅ |
| **Category scores** (cleanliness, location, service, comfort, value) | ❌ | ✅ + city average |
| **Score distribution** (Exceptional / Excellent / Good …) | ❌ | ✅ histogram |
| All amenities, grouped (107+ on a big hotel) | partial | ✅ |
| Room types, photos (100+), video, awards | ❌ | ✅ |
| Nearby attractions with distances | ❌ | ✅ |
| **Full guest reviews** (text, positives/negatives) | partial | ✅ |
| Reviewer **country, traveler type, room, stay dates** | ❌ | ✅ |
| **Hotel's response** to each review | ❌ | ✅ |
| New-/changed-only monitoring | ❌ | ✅ |

### Use cases

- **Reputation & review intelligence** — pull every guest review for your property (and your competitors') with category scores, traveler types and your published responses. Track sentiment and category weak spots over time.
- **Competitive benchmarking** — compare star rating, review score and per-category scores against the **city average** that Agoda publishes for each grade.
- **Travel content & aggregation** — power hotel directories, comparison sites and apps with structured property data: amenities, room types, photos, geo, descriptions and ratings for any destination.
- **Market research** — analyse amenities, accommodation types and rating distributions across a market.
- **Monitoring** — schedule recurring runs to capture new reviews and score changes the moment they happen.

### How to use

1. [Sign up for Apify](https://console.apify.com/sign-up) — the free plan is enough to try this actor.
2. Open the **Agoda Scraper**, then either search by hotel name, paste Agoda hotel URLs, or enter hotel IDs.
3. Click **Start** and watch results stream into the dataset table.
4. **Export** as JSON, CSV, Excel, XML, or RSS — or pull results programmatically via the [Apify API](https://docs.apify.com/api/v2).

### Input

```json
{
    "searchTerms": ["Marina Bay Sands Singapore"],
    "hotelUrls": ["https://www.agoda.com/marina-bay-sands/hotel/singapore-sg.html"],
    "outputType": "all",
    "includeReviews": true,
    "maxReviewsPerHotel": 100,
    "reviewsSort": "most_helpful"
}
```

- **searchTerms** — hotel names to look up via Agoda's suggest API (e.g. `Marina Bay Sands Singapore`, `The Ritz-Carlton, Bangkok`). Every matching hotel is scraped.
- **hotelUrls** — direct Agoda hotel page URLs (any country domain). The most reliable way to scrape a known list of properties.
- **hotelIds** — numeric Agoda hotel IDs (e.g. `185945`).
- **startUrls** — advanced: an alternative way to pass hotel page URLs as a URL list.
- **outputType** *(default `hotels`)* — `hotels` or `reviews` give one clean, dense table; `all` returns both in one dataset, each row tagged with a `type`.
- **includeReviews** *(default true)* — fetch each hotel's guest reviews (applies when output is `reviews` or `all`).
- **maxReviewsPerHotel** *(default 100, 0 = all)* — cap reviews per hotel.
- **reviewsSort** — `most_helpful` (default), `newest`, `highest`, `lowest`.
- **maxHotels** — cap the number of hotels this run (0 = no limit).
- **monitorMode / monitorKey / onlyChangedInMonitor** — see *Monitoring* below.
- **proxyConfiguration** — proxy settings (Apify Residential by default).

> **Scope note:** the actor scrapes specific properties (by URL, ID, or hotel-name search). A bare city name resolves to a destination only — to cover a whole city, feed the hotel URLs you want (Agoda's per-city result pages are JavaScript-rendered and intentionally out of scope for this fast, no-browser actor).

### Output

By default you get **one clean, dense table of hotels**. Set `outputType` to `reviews` for guest reviews, or `all` to combine both (each row tagged with a `type` of `hotel` or `review`).

A hotel record (`type: "hotel"`):

```json
{
    "type": "hotel",
    "hotelId": 185945,
    "name": "Marina Bay Sands",
    "url": "https://www.agoda.com/marina-bay-sands/hotel/singapore-sg.html",
    "accommodationType": "Hotel",
    "starRating": 5,
    "fullAddress": "10 Bayfront Avenue, Marina Bay, Singapore, 018956",
    "area": "Marina Bay",
    "city": "Singapore",
    "country": "Singapore",
    "latitude": 1.2836,
    "longitude": 103.8607,
    "reviewScore": 8.9,
    "reviewScoreText": "Excellent",
    "reviewCount": 48766,
    "categoryScores": { "cleanliness": 9.3, "facilities": 9.3, "location": 9.2, "roomComfort": 8.6, "service": 9.0, "valueForMoney": 8.0 },
    "categoryCityAverages": { "cleanliness": 8.7, "location": 8.8, "service": 8.6 },
    "scoreDistribution": [ { "label": "9+ Exceptional", "count": 19566 }, { "label": "8-9 Excellent", "count": 6649 } ],
    "facilities": ["Fitness center", "Outdoor pool", "Free Wi-Fi", "Spa", "Casino", "..."],
    "facilityGroups": [ { "group": "Things to do, ways to relax", "items": ["Spa", "Sauna", "Massage", "..."] } ],
    "roomTypes": [ { "name": "Sands Family Suite", "bedType": null, "sizeSqm": null } ],
    "nearbyAttractions": [ { "name": "ArtScience Museum", "distance": "350 m from property" } ],
    "images": ["https://pix8.agoda.net/hotelImages/185945/..."],
    "imageCount": 112,
    "videos": ["https://pix5.agoda.net/video/185945.mp4"],
    "checkInTime": "03:00 PM",
    "checkOutTime": "11:00 AM",
    "awards": ["Gold Circle Award Winner 2025"],
    "description": "Experience Luxury and Elegance at Marina Bay Sands…",
    "scrapedAt": "2026-06-19T12:00:00.000Z"
}
```

A review record (`type: "review"`) carries `rating` (0–10), `ratingText`, `title`, `text`, `positives`, `negatives`, `reviewDate`, `checkInDate`/`checkOutDate`, `lengthOfStay`, `reviewerName`, `reviewerCountry`, `travelerType` (e.g. *Family with young children*), `roomType`, `helpfulVotes`, the hotel's `hotelResponse`, and any reviewer `images`.

#### What to expect (field coverage)

Agoda is organizer/host-entered data, so a few fields appear only when the property published them. Verified across multiple hotels, you can typically expect:

| Entity | Always present | Usually present | Present when published |
|---|---|---|---|
| **Hotel** | name, star rating, accommodation type, location, review score & count | category scores, facilities, photos, description, geo | awards, videos, room types, nearby attractions |
| **Review** | rating, review date, reviewer country, traveler type | title, text, room type, stay dates | positives/negatives, hotel response, reviewer images |

A blank field means the property didn't publish it for that record — not that scraping failed. Nothing is dropped.

### Monitoring (only new / changed)

Turn on **Monitor mode** to remember each hotel's review score and review count between runs (in a named key-value store) and output only hotels that are **new or have changed** on later runs — perfect for tracking new reviews and score movements.

- It works **with** [Apify Schedules](https://docs.apify.com/platform/schedules), not against them: the Schedule triggers the run on your cadence (hourly/daily/weekly), and Monitor mode makes each run emit only fresh data. There is no conflict between the two.
- Use a distinct **monitorKey** per watchlist so their states stay separate.
- Set **onlyChangedInMonitor** to `false` to always output every hotel but still tag each as `new` / `changed` / `unchanged` (with `newReviewsSinceLastRun`).

### Automate & schedule

Run this actor on autopilot and pull results into your own stack:

- **[Apify API](https://docs.apify.com/api/v2)** — start runs, fetch datasets, and manage schedules over REST.
- **[apify-client for JavaScript](https://docs.apify.com/api/client/js/)** and **[apify-client for Python](https://docs.apify.com/api/client/python/)** — official SDKs.
- **[Schedules](https://docs.apify.com/platform/schedules)** — run it daily/weekly to capture new reviews and score changes; pair with Monitor mode for a clean new-only feed.
- **[Webhooks](https://docs.apify.com/platform/integrations/webhooks)** — trigger downstream actions (Slack alert, CRM import, dashboard refresh) the moment a run finishes.

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

const client = new ApifyClient({ token: 'MY_APIFY_TOKEN' });

const run = await client.actor('scrapesage/agoda-scraper').call({
    searchTerms: ['Marina Bay Sands Singapore'],
    outputType: 'all',
    maxReviewsPerHotel: 200,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Got ${items.length} hotels & reviews`);
```

### Integrate with any app

Connect the dataset to 5,000+ apps — no code required:

- **[Make](https://docs.apify.com/platform/integrations/make)** — multi-step automation scenarios.
- **[Zapier](https://docs.apify.com/platform/integrations/zapier)** — push new reviews straight into Slack, Sheets or your CRM.
- **[Slack](https://docs.apify.com/platform/integrations/slack)** — get notified when a monitored hotel gets new reviews.
- **[Google Drive / Sheets](https://docs.apify.com/platform/integrations/drive)** — auto-export every run to a spreadsheet.
- **[Airbyte](https://docs.apify.com/platform/integrations/airbyte)** — pipe results into your data warehouse.
- **[GitHub](https://docs.apify.com/platform/integrations/github)** — trigger runs from commits or releases.

### Use with AI assistants (MCP)

The output is clean, LLM-ready JSON. Call this actor from Claude, ChatGPT, or any agent framework through the **[Apify MCP server](https://docs.apify.com/platform/integrations/mcp)** — ask your assistant to "pull the latest reviews and category scores for this Agoda hotel" and let it run the scraper for you.

### Agent-ready: autonomous payments (x402 & Skyfire)

This actor is **agent-ready** — AI agents can discover it, run it, and **pay for it autonomously**, with no Apify account and no human in the loop. It uses [pay-per-event](https://docs.apify.com/platform/actors/publishing/monetize/pay-per-event) pricing and [limited permissions](https://docs.apify.com/platform/actors/development/permissions), so it qualifies for Apify's agentic-payment standards:

- **[x402](https://docs.apify.com/platform/integrations/x402)** — an open, HTTP-native payment protocol. Agents pay per run in USDC on the Base network directly through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp) — no account, no API key.
- **[Skyfire](https://docs.apify.com/platform/integrations/skyfire)** — agent-to-service payments for fully autonomous AI-agent workflows.

Building an AI agent, MCP tool, or autonomous data pipeline? This scraper is ready to plug in and pay as it goes.

### More scrapers from scrapesage

Build a complete **travel & hospitality intelligence stack**:

- **[Booking.com Scraper](https://apify.com/scrapesage/booking-scraper)** — hotel prices, availability, discounts and room data.
- **[Trip.com Scraper](https://apify.com/scrapesage/trip-com-scraper)** — hotel prices, reviews and amenities.
- **[Google Flights Scraper](https://apify.com/scrapesage/google-flights-scraper)** — airfares and price-drop monitoring.
- **[GetYourGuide Scraper](https://apify.com/scrapesage/getyourguide-scraper)** — tours, activities and supplier data.
- **[Tours & Activities Scraper](https://apify.com/scrapesage/tours-activities-scraper)** — multi-platform tours and experiences.
- **[Airbnb Scraper](https://apify.com/scrapesage/airbnb-scraper)** — short-stay listings, prices and availability.
- **[Resident Advisor Scraper](https://apify.com/scrapesage/resident-advisor-scraper)** — electronic-music events and venues.
- **[Eventbrite Scraper](https://apify.com/scrapesage/eventbrite-scraper)** — events plus organizer leads.

### Tips

- **Bulk runs**: paste many hotel URLs at once — they're scraped in parallel. Use `hotelIds` if you already have IDs from a previous run.
- **Reviews cost**: keep `maxReviewsPerHotel` modest for big chains (Marina Bay Sands has 48k+ reviews). Reviews are billed per review.
- **Sorting**: use `newest` for monitoring fresh reviews; `most_helpful` for the highest-signal feedback.
- **Proxies**: keep the default Residential proxy — Agoda serves cleanly on it. Datacenter may work for lighter volumes at lower cost.

### FAQ

**How do I scrape a specific hotel?** Put its name in `searchTerms` (e.g. `Marina Bay Sands Singapore`) or paste its Agoda page URL in `hotelUrls`. You can mix both and pass many at once.

**Does it need the Agoda API or a key?** No. Agoda's partner API requires approval and a key; this actor reads the same (and richer) data from Agoda's public property and review endpoints — no key or login needed.

**Can I scrape every hotel in a city?** This actor targets specific properties (by URL, ID or hotel name). Agoda's per-city result pages are JavaScript-rendered, so for city coverage feed the hotel URLs you want. Hotel-name and URL inputs are fully reliable.

**Can I export to Google Sheets, CSV, or Excel?** Yes — one click in the dataset view, or automatically on every run via the [Google Drive integration](https://docs.apify.com/platform/integrations/drive).

**How do I monitor a hotel for new reviews?** Turn on Monitor mode and create a [Schedule](https://docs.apify.com/platform/schedules). Each scheduled run outputs only hotels with new reviews or changed scores.

**A field is empty — why?** Some hotels don't publish a video, awards, or room sizing, and some reviews have no written comment. Fields are blank only when the property/guest didn't publish that data — never because the scraper skipped it.

**Is scraping Agoda legal?** This actor collects publicly available data only. You're responsible for using the data in compliance with applicable laws (e.g. GDPR/CCPA for personal data) and Agoda's terms.

### Need help?

Open an issue on the actor's **Issues** tab, or visit the [Apify help center](https://help.apify.com/). Feature requests are welcome — this actor is actively maintained.

# Actor input Schema

## `searchTerms` (type: `array`):

Hotel names to look up on Agoda, e.g. `Marina Bay Sands` or `The Ritz-Carlton, Bangkok`. Each term is resolved through Agoda's suggest API and every matching hotel is scraped. Tip: a specific hotel name resolves directly; a bare city name only returns the destination (use hotel URLs/names for individual properties — see README).

## `hotelUrls` (type: `array`):

Direct Agoda hotel page URLs (any country domain), e.g. `https://www.agoda.com/marina-bay-sands/hotel/singapore-sg.html`. The most reliable way to scrape a known list of properties.

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

Numeric Agoda hotel IDs (e.g. `185945`). Useful when you already have IDs from a previous run.

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

Alternative way to pass Agoda hotel page URLs (accepts a list of URL objects). Equivalent to Hotel page URLs.

## `outputType` (type: `string`):

What to put in the dataset. `Hotels` (default) gives one clean, dense table of properties — ideal for direct export. `Reviews` gives one row per guest review. `All` returns hotels + reviews together, each row tagged with a `type` field (the 'All fields' grid will then show columns that only apply to the other type as blank — by design).

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

Fetch each hotel's guest reviews (rating, title, text, positives/negatives, reviewer country & traveler type, room, stay dates, helpful votes and the hotel's response). Applies when Output is Reviews or All.

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

Cap the number of reviews fetched per hotel (0 = all available). Reviews are paginated 25 per request.

## `reviewsSort` (type: `string`):

Order in which reviews are fetched.

## `maxHotels` (type: `integer`):

Limit the total number of hotels scraped this run (0 = no limit). Handy for quick test runs.

## `monitorMode` (type: `boolean`):

Remember each hotel's review score and review count between runs (in a named key-value store) and, on later runs, output only hotels that are new or have changed. Designed to run on an Apify Schedule — Schedules trigger the runs, monitor mode makes each run emit only fresh data. Does not conflict with the scheduler.

## `monitorKey` (type: `string`):

Name for this monitoring watchlist. Use different keys for different watchlists so their states don't mix.

## `onlyChangedInMonitor` (type: `boolean`):

When Monitor mode is on, skip hotels whose review score and count are unchanged since the last run. Turn off to always output every hotel but still tag it as new/changed/unchanged.

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

Maximum number of parallel requests.

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

Proxy settings. Agoda serves cleanly on Apify Residential proxy (the default). You can switch to datacenter to lower cost if it works for your volume.

## Actor input object example

```json
{
  "searchTerms": [
    "Marina Bay Sands Singapore"
  ],
  "outputType": "hotels",
  "includeReviews": true,
  "maxReviewsPerHotel": 100,
  "reviewsSort": "most_helpful",
  "maxHotels": 0,
  "monitorMode": false,
  "monitorKey": "default",
  "onlyChangedInMonitor": true,
  "maxConcurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

All scraped records in the default dataset. Each row is tagged with a `type` (hotel or review); use the Hotels / Reviews views to filter the columns.

# 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 = {
    "searchTerms": [
        "Marina Bay Sands Singapore"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapesage/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 = { "searchTerms": ["Marina Bay Sands Singapore"] }

# Run the Actor and wait for it to finish
run = client.actor("scrapesage/agoda-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 '{
  "searchTerms": [
    "Marina Bay Sands Singapore"
  ]
}' |
apify call scrapesage/agoda-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/umCeoAQg4S5q3wpLZ/builds/JldyNDjbBqCH2pG86/openapi.json
