# Agoda API Scraper (`rl1987/agoda-scraper`) Actor

Scrapes Agoda accommodation search results, pricing and property details via Agoda's public GraphQL endpoints (requests-based, no browser).

- **URL**: https://apify.com/rl1987/agoda-scraper.md
- **Developed by:** [R.L.](https://apify.com/rl1987) (community)
- **Categories:** Travel
- **Features:** Limited permissions
- **Stats:** 7 total users, 5 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 dataset rows

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

### What does Agoda API Scraper do?

**Agoda API Scraper** extracts hotel and accommodation data — live pricing, review scores, photos, facilities and static property details — from [Agoda](https://www.agoda.com) without a browser. It talks directly to the same public GraphQL search endpoints `www.agoda.com/search` itself calls, so runs are fast and don't need to render pages. Give it a destination (or a list of property IDs) and your stay dates, and get back structured JSON, ready for the Apify API, scheduling and integrations.

See `agoda_api_scraping.md` for the underlying endpoint reverse-engineering notes.

### Why use Agoda API Scraper?

- **Price monitoring** — track nightly/total rates for specific properties or a whole city over time.
- **Market research** — pull review scores, star ratings and facility data across a destination for competitor analysis.
- **Lead generation / travel apps** — feed structured accommodation data into your own product without maintaining a browser-based scraper.

### How to use Agoda API Scraper

1. Enter a **Destination** (e.g. `"Bangkok"`) — it's resolved to Agoda's internal city ID automatically. Or paste specific **Property IDs** to skip search entirely.
2. Set **Check-in** / **Check-out** dates, **Rooms**/**Adults**/**Children ages** and a **Currency**.
3. Optionally turn on **Include static details** for address/review-breakdown/useful-info per property.
4. Run the Actor and download results from the **Dataset** tab (JSON, CSV, Excel, …).

### Input

See the **Input** tab for the full schema. Key fields:

| Field | Description |
|---|---|
| `search` | Free-text destination, e.g. `"Bangkok"` |
| `cityId` | Exact numeric Agoda city ID (skips destination resolution) |
| `propertyIds` | Specific property IDs (bypasses search; static content only, no live pricing) |
| `checkin` / `checkout` | Stay dates (`YYYY-MM-DD`) |
| `adults` / `rooms` / `childrenAges` | Occupancy |
| `currency` | Display currency |
| `sortBy` | `Ranking`, `Price` or `AllGuestsReviewScore` |
| `includeDetails` | Adds a `details` object per property |
| `maxItems` | Result cap |

### Output

Each dataset item is one accommodation:

```json
{
  "propertyId": 14654101,
  "name": "Solaria Nishitetsu Hotel Bangkok",
  "url": "https://www.agoda.com/solaria-nishitetsu-hotel-bangkok/hotel/bangkok-th.html",
  "propertyType": "Hotel",
  "starRating": 4,
  "addressCountry": "Thailand",
  "addressCountryCode": "TH",
  "addressCity": "Bangkok",
  "addressArea": "Sukhumvit",
  "latitude": 13.74, "longitude": 100.56,
  "reviewScore": 9.2,
  "reviewCount": 1523,
  "facilityHighlights": ["Free Wi-Fi", "Swimming pool", "Airport transfer"],
  "images": ["https://pix8.agoda.net/hotelImages/..."],
  "priceCurrency": "USD",
  "pricePerNight": 125.83,
  "pricePerNightBeforeDiscount": 125.83,
  "pricePerStay": 251.65,
  "priceFreeCancellation": false,
  "pricePayLaterEligible": false
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

#### Main data fields

| Field | Meaning |
|---|---|
| `propertyId` | Agoda's internal numeric property ID |
| `name` / `url` | Display name and canonical Agoda page |
| `starRating`, `reviewScore`, `reviewCount` | Rating summary |
| `addressCountry`, `addressCity`, `addressArea`, `latitude`, `longitude` | Location |
| `pricePerNight`, `pricePerStay`, `priceCurrency`, `priceFreeCancellation`, ... | The rate on Agoda's search card for those dates/occupancy, taxes and fees included |
| `images`, `facilityHighlights` | Media and top amenities |
| `checkInFrom`, `numberOfRooms`, `yearOpened`, `addressLine1`, ... (optional) | Added when "Include static details" is on |

Every column holds a scalar or a list of strings — nothing nested — so a CSV or
Excel export has one column per field rather than an expanded object. The column
set is fixed per run: a field Agoda does not publish for a property comes back
`null` rather than missing, and the static-detail columns appear only when that
option is on, because a search alone can never fill them.

**On the price.** Agoda's search endpoint returns exactly one offer per
property, and that is what these columns carry: the rate shown on the search
card, taxes and fees included. It is not the minimum across every room type.
Checked against the property pages on 2026-10-20, those list many more offers -
10 and 80 for two of the hotels sampled - and their cheapest came out both below
and above the search-card rate, because the two surfaces price different things.
Treat it as "what a searcher is quoted", not "the best rate available".

Where the search and the property-details endpoints disagree — they report
different review counts for the same hotel, measured on 23 of 25 Bangkok
properties — the row carries the **search** figures, which are the ones matching
the dates and occupancy the run asked for.

### Pricing / cost estimation

This Actor makes 1 request per page of ~25 results (plus 1 request per 20 properties if "Include static details" is on) — no browser rendering, so compute-unit usage per item is very low compared to browser-based scrapers. Check the **Actor pricing** tab for the current pricing model.

### Languages

Agoda's API serves `en-us`, `en-gb`, `pt-br`, `zh-cn` and `zh-tw`. The other
values in the `language` dropdown are kept so existing saved tasks keep loading,
but Agoda returns no data for them, so a run that asks for one stops immediately
and says so rather than failing. The property "useful info" labels (check-in
time, room count, fees) are published in English only.

### Tips

- Leave `includeDetails` off for the fastest, cheapest runs when you only need pricing/ratings.
- Use `propertyIds` directly if you already know which properties you want — it skips destination resolution and search pagination entirely.
- Prices reflect Agoda's live availability at request time; re-run periodically for price-tracking use cases (see the Apify **Scheduler**).

### Travel & booking toolkit

Part of the **Travel & booking toolkit** — search and pricing data across accommodation, transport, and travel-planning sites worldwide:

- [Booking.com API Scraper](https://apify.com/rl1987/booking-api-scraper) — Scrape Booking.com properties, live prices and full room-rate tables.
- [Airbnb API Scraper](https://apify.com/rl1987/airbnb-api-scraper) — Airbnb listings, details, and reviews via GraphQL API.
- [Hostelworld API Scraper](https://apify.com/rl1987/hostelworld-api-scraper) — Hostelworld hostels & properties with full listing + property detail.
- [FlixBus API Scraper](https://apify.com/rl1987/flixbus-api-scraper) — FlixBus trips between cities — times, stations, duration, prices.
- [Changi Airport Timetable Scraper](https://apify.com/rl1987/sin-airport-timetable) — Arrival and departure flight timetables from Changi Airport (SIN).
- [eSIMDB Travel eSIM Scraper](https://apify.com/rl1987/esimdb-scraper) — Travel eSIM data plans from esimdb.com by country/region.

### Did you find this useful?

Rate this actor on Apify! Your feedback helps other users find it and helps us keep improving it.

### FAQ, disclaimers and support

This Actor scrapes publicly available data from Agoda for personal or business research purposes; use it in accordance with Agoda's Terms of Service and applicable law. Agoda may change its API at any time, which can affect this Actor's behavior — please report issues on the Issues tab. Need something custom? Reach out for tailored scraping solutions.

# Actor input Schema

## `search` (type: `string`):

Place name (city, region, landmark) resolved via Agoda's own destination autocomplete. The easiest way to start — e.g. "Bangkok". Leave City ID empty if you use this.

## `cityId` (type: `integer`):

Advanced: exact numeric Agoda city id, e.g. 9395 for Bangkok. Use only if you already know the id; otherwise just fill in Destination above.

## `propertyIds` (type: `array`):

Scrape specific properties by their numeric Agoda property ID (bypasses search, returns static details only — no live pricing). Add one ID per line, e.g. 10636. When set, Destination/City ID is ignored.

## `checkin` (type: `string`):

Arrival date, as 2026-11-20. A relative form like "7 days" also works, which is handy when calling the API. Defaults to 30 days from the run date.

## `checkout` (type: `string`):

Departure date, as 2026-11-25, or a relative form like "10 days". Must be after check-in. Defaults to check-in + 1 night.

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

Number of rooms to book for.

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

Number of adult guests.

## `childrenAges` (type: `array`):

Add one child age (in years) per line, e.g. 5 then 9 for two children. Leave empty for no children.

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

Currency for displayed prices.

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

Locale for localized text (names, facilities). Agoda's API only serves en-us, en-gb, pt-br, zh-cn, zh-tw; the other values are listed because existing saved tasks may store them, but Agoda answers them with no data, so a run that asks for one finishes immediately with an explanation instead of scraping. Property 'useful info' labels are published in English only, so those columns fill for the en-\* locales.

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

Order of the returned accommodations.

## `includeDetails` (type: `boolean`):

Add a `details` object per property: address, review breakdown and useful info (check-in/out times, property age, extras). Costs one extra request per batch of 20 properties in search mode.

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

Maximum number of accommodations to return.

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

Proxy settings. Apify Proxy recommended.

## Actor input object example

```json
{
  "search": "Bangkok",
  "propertyIds": [],
  "rooms": 1,
  "adults": 2,
  "childrenAges": [],
  "currency": "USD",
  "language": "en-us",
  "sortBy": "Ranking",
  "includeDetails": false,
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `accommodations` (type: `string`):

All scraped accommodation rows as JSON.

## `accommodationsTable` (type: `string`):

The same rows through the 'overview' view: name, link, stars, review score, price and city.

## `propertyDetails` (type: `string`):

Static per-property columns through the 'propertyDetails' view - address, check-in times, room and floor counts. Populated when "Include static details" is on, or in propertyIds mode; otherwise only the identifying columns are present.

## `accommodationsCsv` (type: `string`):

Same rows exported as CSV.

## `input` (type: `string`):

The input this run was started with.

## `consoleRun` (type: `string`):

Open this run in the Apify Console.

# 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 = {
    "search": "Bangkok",
    "propertyIds": [],
    "rooms": 1,
    "adults": 2,
    "childrenAges": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("rl1987/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 = {
    "search": "Bangkok",
    "propertyIds": [],
    "rooms": 1,
    "adults": 2,
    "childrenAges": [],
}

# Run the Actor and wait for it to finish
run = client.actor("rl1987/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 '{
  "search": "Bangkok",
  "propertyIds": [],
  "rooms": 1,
  "adults": 2,
  "childrenAges": []
}' |
apify call rl1987/agoda-scraper --silent --output-dataset

```

## MCP server setup

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