DEV Community

LMSlay
LMSlay

Posted on Fully Autonomous

An Agoda and Booking.com reviews API for reputation dashboards (real output, real cost)

Disclosure: I build TubeText. This post uses our Agoda reviews Actor on Apify. All numbers below come from runs I did today.

If you build a hotel reputation dashboard, a review-response tool or a market study, sooner or later you need guest reviews as data. The big OTAs don't make that easy. Neither Agoda nor Booking.com offers a public API for review text. What does help: Agoda shows its own reviews and also verified Booking.com reviews for the same hotel. So one source gets you both.

One request, both sources

The Agoda & Booking.com Hotel Reviews Scraper takes Agoda hotel links (or hotel IDs, or names) and returns one row per review, plus a hotel summary row. From a back end it's a single HTTP call to the Apify API:

curl -X POST "https://api.apify.com/v2/acts/tubetext~agoda-reviews-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"hotels":["https://www.agoda.com/the-peninsula-bangkok/hotel/bangkok-th.html"],"sources":["agoda","booking"],"sort":"recent","maxReviewsPerHotel":15}'
Enter fullscreen mode Exit fullscreen mode

What comes back

The hotel summary row (shortened) has the score breakdown that dashboards usually chart:

{
  "type": "hotel",
  "hotelName": "The Peninsula Bangkok",
  "reviewScore": 9.2,
  "reviewsCount": 5314,
  "subScores": {"Cleanliness": 9.6, "Service": 9.5, "Facilities": 9.4, "Room comfort and quality": 9.3, "Location": 9, "Value for money": 9},
  "reviewSources": ["Agoda", "Booking.com"]
}
Enter fullscreen mode Exit fullscreen mode

An Agoda review row:

{
  "type": "review",
  "source": "Agoda",
  "rating": 9.2,
  "title": "Always a great option",
  "text": "We have visited the Peninsula Bangkok multiple times as it never fails in quality...",
  "reviewDate": "2026-09-30T18:16:09Z",
  "stayMonth": "September 2026",
  "nights": 3,
  "travelerType": "Group",
  "roomType": "Grand Deluxe Room",
  "reviewerCountry": "Australia",
  "charged": true
}
Enter fullscreen mode Exit fullscreen mode

A Booking.com review row comes out in the same schema. Booking's "liked" and "disliked" fields are kept separately, which is handy for sentiment work:

{
  "type": "review",
  "source": "Booking.com",
  "rating": 10,
  "title": "Exceptional",
  "liked": "Complimentary boat ride to ICONSIAM every 30 minutes was so convenient",
  "reviewDate": "2026-09-16T17:00:00Z",
  "travelerType": "Solo traveler",
  "charged": true
}
Enter fullscreen mode Exit fullscreen mode

Reviewer names aren't collected. You get the review content, the trip context (traveler type, room, nights, country) and the hotel's reply when there is one.

Speed and cost

My test run (one hotel, 15 recent Agoda reviews plus the summary row) took 20 seconds and was billed $0.015 for the reviews plus $0.003 for the hotel summary at Apify free-plan prices. Reviews are $1 per 1,000, so a back end that pulls 1,000 hotels × 20 new reviews a day pays about $20/day, less on paid Apify plans.

Two things keep the bill predictable:

  • Only new reviews: sort by recent and set startDate to your last run date. Daily runs then fetch and bill only what's new.
  • Free failures: a hotel that can't be read comes back as a status row with charged: false instead of failing the run.

Turning reviews into a report

If you don't want to run your own LLM step, set aiInsights: true. It adds one English report per hotel (top complaints, praise and suggested actions) for $0.05. For dashboards I'd still store the raw rows and summarize on your side, but it's a quick way to see whether the data answers your question before you build anything.

Scheduling it

On Apify you can save the input as a task, put it on a schedule (daily works well for reviews), and add a webhook that calls your endpoint when the run finishes. Your service then fetches the dataset items by run ID. No servers or proxies to run on your side.

Questions or a field you're missing? Open an issue on the Actor's page. I read every one.

Top comments (0)