kestrel actors › Guest & customer reviews
Despegar Hotel Ratings Scraper — Guest Scores & Summary
Scrape despegar hotel ratings from any hotel page on Latin America's largest online travel agency: the 0-10 overall guest score, the number of reviews behind it, six category scores, the AI-written hotel review summary Despegar publishes, and the individual comments the page shows. One request per hotel, no browser, no login, no API key. If you have been looking for despegar hotel reviews, hotel guest ratings or guest scores for the LatAm market in a machine-readable form, this is the fastest path to them.
Run Despegar Hotel Ratings Scraper on Apify →
Despegar hotel ratings pricing: what one row costs
| Event | What it is | Price | Charged for |
|---|---|---|---|
hotel | Hotel rating row | $0.004 | One Despegar hotel: the 0-10 guest rating with the review count it is based on, the six category scores (service, staff, location, Wi-Fi, cleanliness, value), Despegar's own AI-written summary of what guests say, stars, city, country and coordinates. The individual comments (at most four per hotel, whatever the review count says), hotels with no rating, unknown ids, hotels dropped by minRating and status rows are all free. |
Despegar hotel ratings input reference
Every field of Despegar Hotel Ratings, straight from the actor's input schema.
| Field | Type | Default | What it does |
|---|---|---|---|
startUrls | array | [] | Despegar hotel pages, e.g. https://www.despegar.com.ar/hoteles/h-265543/riu-cancun — any country domain works (.com, .com.ar, .com.mx, .com.co, .cl, .com.pe, us.despegar.com/hotels/…) and each URL is fetched on the domain you give it, so you can mix countries in one run. The slug does not matter: Despegar redirects any slug to the canonical one. |
hotelIds | array | [] | Despegar's numeric hotel ids, e.g. 265543 — the number in /h-<id>/ and what an earlier run's hotel_id gives you. Ids are fetched on the country domain chosen below. This is the cheapest input: no lookup, one request per hotel. |
country | string (enum) | "com" | Which Despegar domain to read hotel ids from. Every domain publishes the same hotel, the same 0-10 rating, the same review count and the same comments — the domain decides the language of the AI summary, the category labels and the review dates, and the currency of the page. "com" lets Despegar pick by the proxy's exit country. Brazil (decolar.com) is listed for completeness but refused every request we made, so avoid it. One of: com, us, ar, mx, co, cl, pe, uy, ec, bo, py, pa, cr, gt, br. |
locale | string (enum) | "auto" | Which language you want the AI summary, the category labels and the review dates in. Despegar has no language switch of its own — Accept-Language and ?language= are both ignored — so the language is the domain: "en" reads us.despegar.com, "es" reads despegar.com.ar. Only used when the country above is left at "com"; an explicit country always wins. One of: auto, es, en. |
includeComments | boolean | true | Also emit the individual guest comments the hotel page publishes — at most four per hotel, whatever the review count says. They are free rows: a hotel costs the same with or without them. Each comment carries its 0-10 score, the good half, the bad half, the month it was written, the traveller type and the reviewer's country. |
minRating | number | 0 | Despegar scores hotels 0-10 (every row also carries the same score on the 0-5 scale as rating_5). 0 = no floor. 8 keeps only the well-rated ones. Hotels below the floor are dropped before billing and never charged; hotels with no rating at all are reported as no_reviews and are always free. Range 0-10. |
sessions | integer | 2 | How many proxy sessions (egress IPs) run in parallel. More is faster; each is paced separately and each keeps its own DataDome cookie, which is what makes a session work at all. Range 1-16. |
perIp | number | 0.5 | Pace for each session. Measured on Despegar: one session served four hotel pages at 1 req/s and was then refused for the rest of the minute, so the default is deliberately slow. 0.3-0.5 is comfortable; above 1 expect blocks and retries, which cost residential traffic without going faster. Range 0.1-3. |
proxyConfiguration | object | {"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]} | Apify Proxy with the RESIDENTIAL group is required and is the default: Despegar's DataDome gate refuses every datacenter range outright (403 on every attempt, both TLS profiles), and only residential IPs with a Chrome TLS fingerprint are served. Keep the default. |
Example input
{
"hotelIds": ["265543", "4382832", "6599128"],
"country": "mx",
"includeComments": true,
"minRating": 8,
"sessions": 2,
"perIp": 0.5,
"proxyConfiguration": {"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]}
}
Despegar hotel ratings output fields
One row per hotel with its guest rating, category scores and Despegar's own AI summary (charged), plus the up-to-four published comments and a status row per target (both free).
Dataset views in the Apify Console: Overview, Hotel ratings, Category scores, Comments, Map, Status.
| Field | Type | What it holds |
|---|---|---|
type | string | hotel | review | status |
target | string | The input value (URL or hotel id) this row came from |
hotel_id | string | Despegar's numeric hotel id (the number in /h-<id>/); the same id on every Despegar country domain |
hotel_name | string | Hotel name as the chosen Despegar site writes it |
hotel_url | string | Canonical hotel page URL on the domain that was read |
city | string | City, from the location line under the hotel name (hotel rows) |
country | string | Country of the hotel, in the page's language (hotel rows) |
address | string | Street address as printed in the map section (hotel rows) |
latitude | number | Latitude of the hotel marker (hotel rows) |
longitude | number | Longitude of the hotel marker (hotel rows) |
stars | integer | Star rating, counted from the stars printed above the hotel name (hotel rows) |
rating | number | Overall guest rating on Despegar's 0-10 scale, e.g. 8.4 |
rating_scale | integer | The scale the rating is on: always 10 (hotel rows) |
rating_5 | number | The same score converted to the 0-5 star scale, e.g. 8.4 -> 4.2 |
rating_label | string | Despegar's word for the score, e.g. "Muy bueno" / "Very good" (hotel rows) |
review_count | integer | How many guest reviews the rating is based on, as Despegar counts them (e.g. 4511) — not how many this actor can deliver (hotel rows) |
reviews_shown | integer | How many individual comments the page actually publishes: at most four (hotel rows) |
score_service | number | Category score 0-10: services and installations (hotel rows) |
score_staff | number | Category score 0-10: accommodation staff (hotel rows) |
score_location | number | Category score 0-10: location (hotel rows) |
score_internet | number | Category score 0-10: internet / Wi-Fi (hotel rows) |
score_cleanliness | number | Category score 0-10: cleaning (hotel rows) |
score_value | number | Category score 0-10: price/quality (hotel rows) |
category_scores | object | The same six scores keyed by Despegar's own codes: service, servicePersonal, location, internetAccessAndQuality, cleaning, qualityprice (hotel rows) |
summary | string | Despegar's own AI-written summary of what guests say about the hotel, generated by Despegar from all its reviews and published on the page — their text, not ours (hotel rows) |
verified_note | string | Despegar's provenance note for the sample, e.g. "Clientes verificados por Grupo Despegar." (hotel rows) |
providers | array | Which review providers the published comments come from; DESPEGAR on every hotel we have seen (hotel rows) |
trip_types | array | Traveller profiles Despegar offers to filter the comments by: couple, friends, singles, family (hotel rows) |
page_language | string | Language the domain served, e.g. es or en (hotel rows) |
page_country | string | Country code of the Despegar site that was read, e.g. AR (hotel rows) |
review_id | string | Despegar's id for the comment (review rows) |
review_date | string | The month the guest wrote the comment, in the page's language, e.g. "Agosto 2023" — Despegar publishes no day (review rows) |
review_month | string | The same date normalised to YYYY-MM (review rows) |
text | string | The comment: the good half and the bad half joined; Despegar reviews have no title (review rows) |
good | string | What the guest liked (review rows) |
bad | string | What the guest disliked; absent when they only wrote praise (review rows) |
reviewer | string | Guest's first name, when they published one (review rows) |
reviewer_country | string | Guest's country, when published (review rows) |
reviewer_country_code | string | Two-letter code for that country (review rows) |
trip_type | string | Who was travelling: couple | friends | singles | family (review rows) |
trip_type_label | string | The same, as the page words it, e.g. "En familia" (review rows) |
language | string | Language the comment was written in (review rows) |
provider | string | Which provider supplied the comment, e.g. DESPEGAR (review rows) |
provider_label | string | Despegar's badge for that provider, e.g. "Huésped verificado" (review rows) |
helpful_votes | integer | How many readers marked the comment useful (review rows) |
status | string | ok | no_reviews | not_found | filtered | duplicate | blocked | limited | error (status rows) |
hotels | integer | 1 when a hotel row was delivered and charged for this target (status rows) |
comments | integer | How many published comments were delivered for this target, free (status rows) |
filtered | integer | 1 when minRating dropped this hotel before billing (status rows) |
duplicates | integer | 1 when this target is the same hotel as an earlier one (status rows) |
error | string | Why a target produced nothing (status rows) |
fetched_at | string | UTC timestamp of the request |
Example row from a real run
Taken from the actor's README — this is the shape your dataset holds.
{
"type": "hotel",
"target": "265543",
"hotel_id": "265543",
"hotel_name": "Riu Cancun",
"hotel_url": "https://www.despegar.com.ar/hoteles/h-265543/riu-cancun-cancun",
"city": "Cancún",
"country": "México",
"address": "Blvd. Kukulcan, Km 9, Manzana 50, Lote 5, Zona Hotelera Cancún - Quintana Roo",
"latitude": 21.1370565,
"longitude": -86.7485229,
"stars": 5,
"rating": 8.4,
"rating_scale": 10,
"rating_5": 4.2,
"rating_label": "Muy bueno",
"review_count": 4511,
"reviews_shown": 4,
"score_service": 8.3,
"score_staff": 9.1,
"score_location": 9.6,
"score_internet": 8.9,
"score_cleanliness": 8.9,
"score_value": 8.6,
"category_scores": {"service": 8.3, "servicePersonal": 9.1, "location": 9.6, "internetAccessAndQuality": 8.9, "cleaning": 8.9, "qualityprice": 8.6},
"summary": "El Riu Cancún es un lugar increíble para relajarse y disfrutar…",
"verified_note": "Clientes verificados por Grupo Despegar.",
"providers": ["DESPEGAR"],
"trip_types": ["couple", "friends", "singles", "family"],
"page_language": "es",
"page_country": "AR",
"fetched_at": "2026-08-29T18:20:11+00:00"
}
{
"type": "review",
"review_id": "661ec3c8fe92b10bfdade9ca",
"hotel_id": "265543",
"hotel_name": "Riu Cancun",
"rating": 9.7,
"rating_5": 4.85,
"review_date": "Abril 2024",
"review_month": "2024-04",
"text": "Hospitalidad de parte de todo el personal… — No alcance a darme cuenta que faltara algo.",
"good": "Hospitalidad de parte de todo el personal…",
"bad": "No alcance a darme cuenta que faltara algo.",
"reviewer": "Lisbeth",
"reviewer_country": "Chile",
"reviewer_country_code": "CL",
"trip_type": "couple",
"trip_type_label": "En pareja",
"language": "es",
"provider": "DESPEGAR",
"provider_label": "Huésped verificado",
"helpful_votes": 25
}
Despegar hotel ratings in Python, JavaScript and curl
Python
from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("kestrel/despegar-hotel-ratings").call(run_input={
"hotelIds": ["265543", "4382832"], "country": "ar", "minRating": 8})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
if row["type"] == "hotel":
print(row["hotel_name"], row["rating"], row["review_count"], row["score_value"])
JavaScript (Node)
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<APIFY_TOKEN>' });
const run = await client.actor('kestrel/despegar-hotel-ratings').call({
startUrls: ['https://www.despegar.com.ar/hoteles/h-265543/riu-cancun'], includeComments: true });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((i) => i.type === 'hotel'));
curl
curl -X POST "https://api.apify.com/v2/acts/kestrel~despegar-hotel-ratings/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"hotelIds":["265543"],"country":"us","includeComments":true}'
The same three calls are runnable files in the examples repository: examples/despegar-hotel-ratings.py|.js|.sh.
Limits, and what this actor will never do
- Four comments per hotel, maximum. Not a setting, not a paging bug: the ceiling of the public page.
reviews_showntells you the exact number every time. - No day-level review dates. The source publishes month and year only;
review_monthgives youYYYY-MM. - No management replies, no photos. They are not on the page.
- No search. Give the actor hotels; it does not crawl destinations. That keeps costs predictable on a residential proxy.
- No Brazilian domain.
decolar.comis hard-blocked, as described above. - Residential proxy required. Datacenter ranges are refused by the source, so a run without residential proxy will produce
blockedrows. It is the default in the input form; leave it alone.
Everything above was measured on 2026-08-29 against the live site through Apify's residential proxy, and the actor's fixtures are the captured pages themselves, so the next time the source changes shape the tests fail before your run does.
FAQ
Why only four comments per hotel?
Because that is all the page publishes. review_count can say 4,511 while reviews_shown says 4. The site's own tracking call reports total_comments: 4, and a headed browser session found no endpoint that returns more — no XHR, no "see all reviews" route, no provider feed. Adding dates to the URL (the booking funnel) changes nothing: still four, still one provider. We would rather sell you the rating honestly than a review scraper that quietly returns four rows.
Is review_count the number of rows I get?
No, and this is the single most important line in this readme. review_count is Despegar's own total; reviews_shown is how many comments came back (0-4). You are billed once per hotel either way — the comments are free.
Does the country site change the numbers?
No. We fetched the same hotel on nine domains: identical id, identical 0-10 score, identical review count, identical four comments. What changes is the language of the AI summary, the category labels and the review dates, plus the page currency. Pick us for English, any LatAm code for Spanish.
Can I get Brazilian hotel ratings?
Brazil is served by decolar.com, and it refused every request we made (six attempts across three residential sessions, all DataDome 403). The domain is in the input list for completeness, but expect blocked status rows. Brazilian hotels are of course covered by every other site — the id is global.
What exactly is the AI review summary?
An ai review summary written by Despegar, not by us and not by an LLM we run. It is one paragraph distilling every review a hotel has, printed above the comments. It arrives in the summary field verbatim.
What does a hotel with no reviews look like?
Its page simply has no ratings module. You get a status row with no_reviews, no hotel row, and no charge. That is an honest empty answer, and it is never confused with a block: a block is an HTTP 403 with a DataDome body, and it is reported as blocked with the reason in error.
How much does a run cost?
$0.004 per hotel row delivered, plus Apify platform usage (compute and residential proxy traffic; a hotel page is roughly 0.45 MB). Comments, status rows, unknown ids, unrated hotels and hotels dropped by minRating are all free. Ten thousand hotels is $40 of events.
Is scraping this legal?
You are reading a public page that requires no login, and taking facts from it — scores, counts, dates — which are not themselves copyrightable in most jurisdictions. That is generally lawful, and hiQ v. LinkedIn is the usual reference for public data. The legal caveats are real, though: the site's terms of use, the personal data in a reviewer's name and country (GDPR/LGPD apply if you store it), and the AI summary, which is Despegar's own creative text — quote it with attribution rather than republishing it as your own. Ask your own counsel before you build a product on it.
Can I use it from n8n, Make.com or an AI agent?
Yes. The actor is a standard Apify actor, so it appears in the Apify nodes for n8n and Make.com, and through Apify's MCP server it can be called directly by an AI agent or by Claude. The dataset is available as JSON, CSV, Excel or an API URL, and the run summary is a single record in the key-value store under SUMMARY.
What happens when I hit my spending limit?
Nothing is delivered that was not paid for. Every hotel is charged before its row is pushed; if the platform refuses the charge, the row is not pushed and the target is marked limited. Charged always equals delivered — that invariant is covered by the actor's own test suite across every input mode and budget.
Can I fetch despegar hotel ratings by id, with no API key?
Yes — that is the normal way to run it. There is no public API here, so despegar hotel ratings by id is exactly what this actor does: you pass hotelIds, it reads the page. Using despegar without an api key is the point; the source publishes no key-based endpoint at all, and none is needed.
How do I find hotel ids in the first place?
Any hotel URL contains one. Beyond that, the site's sitemaps in robots.txt all 404, so harvesting means reading city and home pages, which inline a dozen or two /h-<id>/ links each. If you already have a list of properties, the fastest route is to search the site once by hand and keep the ids: they never change and they work on every country domain.
How to use Despegar Hotel Ratings Scraper
Related scrapers
Run Despegar Hotel Ratings 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/despegar-hotel-ratings