kestrel actors › Guest & customer reviews
Agoda Reviews Scraper — Hotel Guest Reviews & Ratings
An agoda reviews scraper that returns every guest review a property has, as structured rows: agoda ratings on both the 0–10 and 5-star scales, the rating word, title, review text, separate positives and negatives, stay dates and length, room type, reviewer name and country, and the hotel's public reply. It turns agoda hotel reviews into hotel review data you can query — a hotel review scraper built for bulk work rather than one page at a time.
Run Agoda Reviews Scraper on Apify →
Agoda reviews scraper pricing: what one row costs
| Event | What it is | Price | Charged for |
|---|---|---|---|
review | Review row | $0.005 | One guest review: rating on both the 0-10 and 5-star scales, title, comment, positives and negatives, stay dates, reviewer country and the hotel's reply. Properties with no reviews are free. |
Pay per event, one event per delivered review row. Free: hotel rows, status rows, every review removed by maxRating or requireText, properties with no reviews, and failed properties. A property is harvested once per run whether you give its name, its URL, its id, or all three.
A mid-size hotel is a few hundred reviews; a busy hostel can be over a thousand — 1,457 from a single property was verified in testing. maxReviewsPerHotel and the two filters make that a deliberate choice. Verified runs behind this listing cost $0.0002–$0.0026 each in platform compute. Exact per-row pricing is on this page's pricing tab.
Agoda reviews scraper input reference
Every field of Agoda Reviews, straight from the actor's input schema.
| Field | Type | Default | What it does |
|---|---|---|---|
startUrls | array | [] | Agoda property pages, e.g. https://www.agoda.com/tivoli-avenida-liberdade-lisboa/hotel/lisbon-pt.html — the run reads the numeric hotel id from the page for you. |
hotelIds | array | [] | Agoda's numeric ids, e.g. 63820 — the fastest input, and what an earlier run's hotel_id gives you. |
hotelNames | array | [] | Property names as you would type them into Agoda's search box, e.g. "Park Hyatt Tokyo". The run resolves each to the exact property through Agoda's own autocomplete — no URL or id needed. |
maxReviewsPerHotel | integer | 200 | 0 = every review the property has (Agoda pages them ~200 at a time; large hotels run into the thousands). N = the first N in the order below. The main cost control. Range 0-20000. |
reviewsSort | string (enum) | "most_recent" | Which reviews come first. "Lowest rated" is the fastest way to find complaints; "Most recent" is the one to schedule. One of: most_recent, highest_rated, lowest_rated, most_relevant. |
maxRating | number | 0 | 0 = keep every review. 1-10 on Agoda's scale (5 is a poor stay) = keep only reviews at or below it, so a complaints feed costs nothing for the happy ones. Filtered reviews are never charged. Range 0-10. |
requireText | boolean | false | Many Agoda reviews are a score with no words. Turn this on to deliver and pay for only the ones that actually say something. |
locale | string | "en-us" | Agoda locale for the request, e.g. en-us, es-es, de-de. Every review also carries the language it was written in. |
includeHotelRow | boolean | true | Also emit one row per property with its id, name and how many reviews were taken. Never charged. |
sessions | integer | 4 | How many proxy sessions (egress IPs) run in parallel. More is faster; each is paced separately. Range 1-16. |
perIp | number | 1 | Pace for each session. Agoda tolerates about 1/s per IP; faster causes retries, not speed. Range 0.1-3. |
proxyConfiguration | object | {"useApifyProxy": true} | Apify Proxy is required: Agoda throttles datacentre traffic that is not rotated. The default group works. |
Example input
{ "hotelNames": ["Park Hyatt Tokyo"], "maxReviewsPerHotel": 0, "reviewsSort": "lowest_rated", "maxRating": 5, "requireText": true }
{ "startUrls": ["https://www.agoda.com/the-central-house-lisbon-baixa/hotel/lisbon-pt.html"], "maxReviewsPerHotel": 0 }
Agoda reviews scraper output fields
Three row types share one dataset: review (one guest review, charged), hotel (context for a property, free) and status (per property, free).
Dataset views in the Apify Console: Overview, Reviews, Low scores, Run status.
| Field | Type | What it holds |
|---|---|---|
type | string | Row type: review, hotel or status. |
hotel_id | string | Agoda's numeric property id. |
hotel_name | string | Property name, as the hotel signs its own replies. |
url | string | The Agoda property page, when the run was given one. |
locale | string | Agoda locale the request used. |
reviews_fetched | integer | Hotel rows: how many reviews were taken for the property. |
review_id | string | Agoda's id for the review. |
rating | number | Guest score on Agoda's 0-10 scale. |
rating_5 | number | The same score out of five, for comparing with five-star sources. |
rating_text | string | Agoda's word for the score, e.g. "Exceptional". |
title | string | Review headline the guest wrote. |
text | string | The review body. Many Agoda reviews are a score with no words: this is then empty. |
positives | string | What the guest liked, when they filled that field separately. |
negatives | string | What the guest disliked, when they filled that field separately. |
original_title | string | Untranslated headline, when Agoda translated the review. |
original_text | string | Untranslated body, when Agoda translated the review. |
language | string | Language the review was written in. |
translated_to | string | Language the review was shown in. |
review_date | string | When the review was posted. |
review_date_text | string | Review date as Agoda prints it. |
check_in | string | Start of the stay being reviewed. |
check_out | string | End of the stay being reviewed. |
stay_month | string | Month and year of the stay, as Agoda prints it. |
stay_length | integer | Nights stayed, when Agoda reports it. |
room_type | string | Room the guest stayed in, when Agoda reports it. |
reviewer_name | string | Display name of the guest. |
reviewer_country | string | Country the guest booked from. |
reviewer_type | string | Agoda's label for the reviewer, when present. |
group_type | string | Traveller group Agoda assigns the stay, when present. |
helpful_votes | integer | How many readers marked the review helpful. |
unhelpful_votes | integer | How many readers marked it unhelpful. |
source | string | Which source the review came from — Agoda aggregates partners alongside its own. |
provider_id | string | Numeric id of that source. |
responder | string | Who replied, normally the property itself. |
response | string | The property's public reply, when there is one. |
response_date | string | When the property replied. |
images | array | Photos the guest attached, when any. |
status | string | Status rows: ok, no_reviews or error. |
target | string | Status rows: the URL or id this job was given. |
reviews | integer | Status rows: review rows delivered. |
filtered | integer | Status rows: reviews dropped by maxRating or requireText, never charged. |
pages | integer | Status rows: pages of reviews read. |
duplicates | integer | Status rows: 1 when another input already covered this property. |
error | string | Status rows: why the property failed, null when it did not. |
fetched_at | string | UTC timestamp when the row was fetched. |
Example row from a real run
Taken from the actor's README — this is the shape your dataset holds.
{
"type": "review", "hotel_id": "63820",
"hotel_name": "Tivoli Avenida Liberdade", "url": null, "locale": "en-us",
"review_id": "1059514024", "rating": 10.0, "rating_5": 5.0, "rating_text": "Exceptional",
"title": "Nice Hotel", "text": "Beautiful hotel in the center!", "positives": null, "negatives": null,
"original_title": null, "original_text": null, "language": "en", "translated_to": "en",
"review_date": "2025-12-15T10:54:00+07:00", "review_date_text": "December 15, 2025",
"check_in": "2025-12-08T00:00:00+07:00", "check_out": "2025-12-14T00:00:00+07:00",
"stay_month": "December 2025", "stay_length": null, "room_type": null, "group_type": null,
"reviewer_name": "VARDAN", "reviewer_country": "Mozambique", "reviewer_type": null,
"helpful_votes": 0, "unhelpful_votes": 0, "images": null,
"source": "Agoda", "provider_id": "332",
"responder": "Tivoli Avenida Liberdade", "response": null, "response_date": null
}
{ "type": "hotel", "hotel_id": "63820", "hotel_name": "Tivoli Avenida Liberdade", "url": null, "reviews_fetched": 108, "locale": "en-us" }
Agoda reviews scraper in Python, JavaScript and curl
Python
from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("kestrel/agoda-reviews-scraper").call(run_input={
"hotelNames": ["Park Hyatt Tokyo"], "maxReviewsPerHotel": 0,
"reviewsSort": "lowest_rated", "maxRating": 5, "requireText": True,
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
if row["type"] == "review":
print(row["rating"], row["reviewer_country"], row["text"][:80])
JavaScript (Node)
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('kestrel/agoda-reviews-scraper').call({
hotelIds: ['63820'], maxReviewsPerHotel: 200, reviewsSort: 'most_recent',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((i) => i.type === 'review').length, 'reviews');
curl
curl -X POST "https://api.apify.com/v2/acts/kestrel~agoda-reviews-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
-H 'Content-Type: application/json' \
-d '{"hotelIds":["63820"],"maxReviewsPerHotel":100}'
The same three calls are runnable files in the examples repository: examples/agoda-reviews-scraper.py|.js|.sh.
Limits and honest notes
- Agoda rates 0–10, not 1–5.
ratingis Agoda's own number;rating_5is the same score halved so you can compare against five-star sources. Do not mix them. - Many reviews are a score with no words. That is Agoda, not a parsing gap —
requireTextdrops them if you only want written feedback. positivesandnegativesare only present when the guest used those fields. Older reviews often put everything intext.- A throttled request answers
200with no reviews at all, rather than an error. The run detects that and retries on a fresh IP, so a busy property is never reported as having none. stay_length,room_typeandgroup_typeare frequently null — Agoda only shows them for some reviews.- HTTP/2 is required by Agoda's endpoint; over HTTP/1.1 it silently returns nothing. The actor handles this, but it is why a naive script fails.
FAQ
Does it need an Agoda API key or login?
No. There is no public agoda api for reviews to hold a key for. This calls the same endpoint agoda.com's own review widget uses, with no session and no account.
Can I download Agoda reviews as CSV or Excel?
Yes. Every run writes an Apify dataset, exportable to CSV, Excel, JSON or XML from the Console or over the API with ?format=csv. That is the quick path to download agoda reviews for one property or a whole competitor set.
How do I get only Agoda negative reviews?
Set maxRating to your ceiling — 5 on Agoda's 0–10 scale is a poor stay — and reviewsSort to lowest_rated. Add requireText: true so you only pay for reviews with actual words. Everything above the ceiling is dropped before billing.
Do I need the hotel id, or can I use the name?
Either. hotelNames resolves a plain name through Agoda's own autocomplete: Park Hyatt Tokyo became id 910 in testing, and Tivoli Avenida Liberdade became 63820. Use startUrls if you already have the page, or hotelIds if a previous run gave you the number.
How many reviews can one property return?
All of them. Agoda pages about 200 at a time and the run follows the pages, de-duplicating as it goes — 1,457 unique reviews from a single property was verified. maxReviewsPerHotel bounds it when you want a cheaper run.
Are reviews translated, and which languages come back?
Reviews arrive in the language they were written in, tagged in language, and translated_to records what Agoda showed them as. original_text holds the untranslated body when Agoda translated one. Multi language hotel reviews are the normal case here, not an edge case — one property returned 18 languages.
Does it include the hotel's replies?
Yes — responder, response and response_date when the property answered publicly. responder is also how the run recovers the hotel's name, because Agoda ships its property pages with an empty <title>.
Can I use it as a general hotel review aggregator?
For Agoda's corpus, yes — and note that Agoda itself aggregates some partner reviews, which is why each row carries source and provider_id. For a true hotel review aggregator across several OTAs you would run this alongside scrapers for the other sites and join on the property.
Can I scrape Agoda reviews without an API?
That is what this is — agoda reviews without api access, no key to apply for, no approval process. You call an Apify actor and read rows back.
What does bulk work cost?
Bulk hotel reviews are billed per delivered row, so cost scales with data, not time. The two filters and the per-hotel cap cut it directly, because filtered rows are never charged.
How to use Agoda Reviews Scraper
Ready-made runs you can open and start
Each one is a saved input on the Apify Store — open it, press Start, and it runs with the fields already filled in. All 163 across the suite.
| Ready-made run | What it does |
|---|---|
| Agoda Negative Reviews for Any Hotel | Lowest-scoring reviews with a written complaint, six and below on Agoda scale: what actually goes wrong at a property, and how often. |
| Multi-Language Hotel Reviews from Agoda | Agoda's Asian properties are reviewed in a dozen languages; every row carries the language it was written in, so you can split the corpus by market. |
| Hotel Reputation Monitoring on Agoda | Fifty newest reviews for each of three properties by hotel id - small enough to schedule daily and route to Slack when a score drops. |
| Download Agoda Reviews to CSV | Five hundred reviews of one property with scores, titles, positives, negatives, room type and stay dates, exportable as CSV or JSON. |
| Bulk Hotel Reviews by Agoda Hotel ID | Eight properties across Asia, Europe and the Gulf in one run, addressed by numeric id: the fastest input and the cheapest per review. |
| Guest Feedback Data with Text Only | Many Agoda reviews are a score and nothing else. requireText drops them before billing, so you pay only for feedback that says something. |
| Agoda Competitor Reviews in Bangkok | Five Bangkok riverside competitors, a hundred written reviews each: where the comp set is losing points, in the guests own words. |
| Agoda Ratings: Highest Rated Reviews | The reviews guests wrote when everything went right, sorted highest first - quotable testimonials with reviewer country and stay dates. |
| Agoda Hotel Reviews in German (de-de) | Ask Agoda in German and the reviews come back for a German-speaking audience, with the original language still recorded on every row. |
| Agoda Reviews Without API Access | Agoda has no public review API. This is the smallest replacement: one property by name, fifty recent reviews, no key and no partner contract. |
| Hotel Review Data by Room Type | Every Agoda review names the room type booked and the stay dates, so complaints can be traced to a room category rather than the property. |
| Agoda Reviews by Hotel, Most Relevant | Agoda's own most-relevant ordering surfaces the reviews future guests actually read - sixty of them is enough to summarise a property. |
Related scrapers
Run Agoda Reviews Scraper
The actor lives on the Apify Store, where the pricing tab carries the live per-row price and the input form has every field above: apify.com/kestrel/agoda-reviews-scraper