If you manage a hotel, run a reputation-management tool or analyse a city's hotel market, Agoda is one of the review sources you can't skip in Asia. A single hotel page there mixes two review pools: reviews from Agoda's own guests and reviews from Booking.com guests that Agoda republishes. Each pool has its own score, its own review count and its own six sub-scores (cleanliness, facilities, location, room comfort, service, value for money).
Reading that by hand works for one property. For a competitive set of 20 hotels, checked every morning, it doesn't. This post pulls the reviews and scores into a CSV in Python and shows a daily "new reviews only" setup.
Disclosure: I'm Aurelix, and I built Agoda API, an Agoda reviews scraper. It's a paid tool (prices below).
What each row holds
One row per review, from the hotel's public Agoda review page:
-
source(Agoda or Booking.com),ratingout of 10,rating_text,title,text, and for Booking.com-style reviewspositivesandnegatives. -
language, plusoriginal_titleandoriginal_textwhen Agoda shows an English translation, so you keep the guest's own words. -
review_date(the date the page shows),stay_month,nights,room_type,traveller_type(couple, solo, family, group, business). -
reviewer_nameandreviewer_countryas Agoda displays them,helpful_votes,photos. -
owner_response,owner_response_dateandresponder_namewhen the hotel replied. - The hotel on every row:
hotel_name,star_rating,address,city,country,agoda_score,agoda_review_count,agoda_sub_scores,agoda_score_distribution,booking_score,booking_review_count,booking_sub_scores.
Hotels can be given as Agoda links (any language version), Agoda hotel IDs, or a hotel name with its city.
A competitive set in one run
pip install apify-client
import csv
import os
from collections import defaultdict
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("aurelix/agoda-reviews-scraper").call(
run_input={
"hotels": [
"https://www.agoda.com/the-peninsula-bangkok/hotel/bangkok-th.html",
"Mandarin Oriental Bangkok",
"Shangri-La Bangkok",
],
"maxReviewsPerHotel": 300,
"reviewsNewerThan": "90 days",
}
)
reviews = list(client.dataset(run["defaultDatasetId"]).iterate_items())
fields = ["hotel_name", "source", "rating", "title", "text", "negatives", "traveller_type",
"reviewer_country", "review_date", "owner_response"]
with open("reviews.csv", "w", newline="", encoding="utf-8") as f:
w = csv.DictWriter(f, fieldnames=fields, extrasaction="ignore")
w.writeheader()
w.writerows(reviews)
hotels = {}
by_type = defaultdict(list)
for r in reviews:
hotels[r["hotel_name"]] = r
by_type[(r["hotel_name"], r["traveller_type"])].append(r["rating"])
for name, h in hotels.items():
subs = h["agoda_sub_scores"] or {}
print(f"{name}: Agoda {h['agoda_score']} ({h['agoda_review_count']} ratings), "
f"Booking.com {h['booking_score']}; cleanliness {subs.get('Cleanliness')}, "
f"value {subs.get('Value for money')}")
for (name, kind), ratings in sorted(by_type.items()):
if kind and len(ratings) >= 5:
print(f" {name} / {kind}: {sum(ratings) / len(ratings):.1f} over {len(ratings)} reviews")
The hotel name in the second line is matched through Agoda's own search box; the run's status message says which property each name matched, so check it once and switch to the link if it picked the wrong one.
Ideas for the same data:
-
Complaint mining:
"maxRating": 6, "sortBy": "lowest"gives the unhappy reviews first; feednegativesandtextto an LLM and ask for recurring themes per hotel. -
Reply rate: count rows with
owner_responseper hotel. It's a quick read on how actively each competitor manages its reviews. -
Who stays where: group by
traveller_typeandreviewer_countryto see which segments each hotel attracts and how each segment rates it.
New reviews every morning
run_input = {
"hotels": ["https://www.agoda.com/the-peninsula-bangkok/hotel/bangkok-th.html", "..."],
"maxReviewsPerHotel": 500,
"onlyNewReviews": True,
"trackingName": "my-compset-daily",
"slackWebhookUrl": "https://hooks.slack.com/services/...",
}
With onlyNewReviews on, the first run returns the newest reviews up to your limit, and later runs with the same trackingName return only reviews newer than the ones you already have: reading newest first, each review source stops at the first review you already received. A daily run over 20 hotels takes seconds and bills $0.0003 per hotel plus the new reviews. Save the input as a task in the Apify Console, schedule it daily, and the Slack URL gets the count and the top 10.
Why this tool
- $0.50 per 1,000 reviews ($0.40 on paid plans), cheaper than the leading tools.
- Any number of hotels in one run, including by hotel name.
- The original text next to the translation.
- An only-new-reviews mode.
- What it doesn't cover: room prices and availability.
Limits worth knowing
- Rows exist only for written reviews. The review counts next to the scores include rating-only reviews, so they are higher than the number of rows.
- Agoda's review service answers part of its requests with an empty page; the tool asks again before it decides a hotel has no more reviews, so long hotels take a little longer.
- "Highest" and "lowest rated first" follow Agoda's own order page by page; sort the CSV if you need a strict order across both review sources.
The tool reads only what a logged-out visitor sees on Agoda's public review pages, never logs in, and returns reviewer names and countries exactly as Agoda shows them. Agoda's terms discourage automated access, so keep your use to analysing public reviews.
Top comments (0)