kestrel actors docs

kestrel actors › Guest & customer reviews

Hostelworld Reviews Scraper — Hostel Guest Reviews

This hostelworld reviews scraper turns any hostel on Hostelworld into structured hostel guest reviews: the 0-100 overall score with its seven sub-ratings, the guest's own words, the hostel's public reply, who was travelling and where they came from. Point it at Hostelworld URLs or property ids and it returns every review the site lists, newest first — hostel reviews as rows you can filter, chart and diff, not a page you have to read. Because it reads Hostelworld's own public JSON API there is no browser, no login and no key, so budget travel reviews arrive at a few hundred rows a second and review monitoring on a daily schedule costs cents.

Run Hostelworld Reviews Scraper on Apify →

Hostelworld reviews scraper pricing: what one row costs

EventWhat it isPriceCharged for
reviewReview row$0.003One Hostelworld guest review: the 0-100 overall score with its seven sub-ratings (value, safety, location, staff, atmosphere, cleanliness, facilities), the text, the owner's reply, group type, age band, trip types, reviewer nickname and nationality. Hostels with no reviews, unknown property ids, property rows and filtered reviews are free.

$0.003 per review row. Hostel rows, status rows, duplicate targets, unknown ids and every review a filter dropped are free. A thousand reviews is $3; a daily 30-day watch over ten hostels is usually a few cents a day. Compute is included in the event price.

Hostelworld reviews scraper input reference

Every field of Hostelworld Reviews, straight from the actor's input schema.

FieldTypeDefaultWhat it does
startUrlsarray[]Hostelworld property pages, e.g. https://www.hostelworld.com/hostels/p/15529/home-lisbon-hostel/ or the older https://www.hostelworld.com/pwa/hosteldetails.php/Home-Lisbon-Hostel/Lisbon/15529 — every URL form Hostelworld serves carries the numeric property id, so no page has to be loaded first. Any query string is fine.
propertyIdsarray[]Hostelworld's numeric property ids, e.g. 15529 — the number in /hostels/p/<id>/ and the last path segment of a hosteldetails.php URL, and what an earlier run's property_id gives you. The fastest path: no lookup at all.
maxReviewsPerPropertyinteger1000 = every review the hostel has (Hostelworld pages them 50 at a time; a busy hostel runs to a few thousand). N = the first N in the order below. The main cost control. Range 0-20000.
reviewsSortstring (enum)"-date"The order Hostelworld returns reviews in. -date = newest first (the default, and the only order in which sinceDate can stop paging early), date = oldest first, rating = lowest rated first (a complaints feed), -rating = highest rated first. These four are the only values the API really honours — anything else is silently served as newest first. One of: -date, date, rating, -rating.
minRatinginteger0Hostelworld scores each review 0-100 (100 = perfect); every row also carries the same score on the 0-5 scale as rating_5. 0 = no floor. 90 keeps only the raves. Filtered reviews are never charged. Range 0-100.
maxRatinginteger0The other end of the same 0-100 overall score: 0 = no ceiling, 70 gives a complaints feed. Combine with reviewsSort = lowest rated first so the worst reviews arrive on page one. Filtered reviews are never charged. Range 0-100.
requireTextbooleanfalseDrop score-only reviews (an empty notes field) before billing. Hostelworld reviews nearly always carry a sentence or two, so this rarely removes much.
groupTypesarray[]Keep only reviews from these group types: MALE and FEMALE (solo travellers), COUPLE, ALLFEMALEGROUP, ALLMALEGROUP, MIXEDGROUP, FAMILY. Friendly spellings work too (solo_female, female_group, mixed_group). Empty = all. Hostelworld's API has no server-side filter for this, so the filter runs here in the actor — the pages are still read, the filtered reviews are simply never charged.
sinceDatestring""YYYY-MM-DD, or relative so schedules never go stale: "30 days", "2 weeks", "6 months". With the default newest-first order the run stops reading once a whole page predates the date, so a daily schedule reads one page per hostel. Empty = no date limit.
includePropertyRowbooleantrueAlso emit one free row per hostel with its name, type, city, country, address, coordinates, star rating, the aggregate 0-100 ratings, total ratings, facilities, what it is best for and its lowest nightly price. The hostel record is read either way — it is what gives review rows their hostel name and URL — and is never charged.
sessionsinteger2How many proxy sessions (egress IPs) run in parallel. More is faster; each is paced separately. Range 1-16.
perIpnumber1Pace for each session. Hostelworld's API answered 10 of 10 requests at 1 req/s from a single datacenter IP with no throttling at all; 1-2 is comfortable. Range 0.1-5.
proxyConfigurationobject{"useApifyProxy": true}Apify Proxy with the datacenter group is enough: the API answers plain HTTP requests from datacenter ranges with no key, no auth and no bot gate. Residential works too and costs more. Keep the default.

Example input

{
  "propertyIds": ["15529"],
  "reviewsSort": "rating",
  "maxRating": 70,
  "requireText": true,
  "sinceDate": "30 days",
  "maxReviewsPerProperty": 0,
  "includePropertyRow": true,
  "proxyConfiguration": { "useApifyProxy": true }
}
{
  "startUrls": [
    "https://www.hostelworld.com/hostels/p/15529/home-lisbon-hostel/",
    "https://www.hostelworld.com/pwa/hosteldetails.php/Yes-Lisbon-Hostel/Lisbon/45010"
  ],
  "maxReviewsPerProperty": 0,
  "reviewsSort": "-date",
  "includePropertyRow": true,
  "sessions": 4,
  "perIp": 1
}

Hostelworld reviews scraper output fields

One row per hostel guest review (charged), plus a free hostel context row and a free status row per target.

Dataset views in the Apify Console: Overview, Reviews, Complaints, Hostels, Status.

FieldTypeWhat it holds
typestringreview | property | status
targetstringThe input value (URL or property id) this row came from
property_idstringHostelworld's numeric property id (the number in /hostels/p/<id>/)
property_namestringHostel name as Hostelworld lists it
property_urlstringThe hostel's page on hostelworld.com
review_idstringHostelworld's numeric review id
review_datestringPublication date, YYYY-MM-DD
textstringThe review text (Hostelworld's notes field); null when the guest scored without writing
languagestringLanguage code of the text Hostelworld serves (always en today)
machine_translatedbooleantrue when Hostelworld machine-translated the review into the served language
ratingintegerOverall score on Hostelworld's 0-100 scale (100 = perfect); on property rows, the hostel's aggregate score
rating_5numberThe same score converted to the 0-5 star scale, e.g. 94 -> 4.7
sub_ratingsobjectThe seven 0-100 sub-scores: value, safety, location, staff, atmosphere, cleanliness, facilities
likedstringWhat the guest liked, when Hostelworld splits the review that way (legacy field, usually null)
dislikedstringWhat the guest disliked, when Hostelworld splits the review that way (legacy field, usually null)
recommendedbooleanWhether the guest recommends the hostel (legacy field, usually null)
owner_commentstringThe hostel's public reply to the review, if any
group_typestringMALE | FEMALE (solo travellers) | COUPLE | ALLFEMALEGROUP | ALLMALEGROUP | MIXEDGROUP | FAMILY
age_groupstringReviewer age band: 18-24, 25-30, 31-40 or 41+
trip_typesarrayWhy they were travelling: REGULARVACATION, WEEKENDAWAY, GAPYEAR, RTWTRIP, COLLEGEBREAK, OTHER
reviewer_idstringHostelworld's numeric user id
reviewer_nicknamestringReviewer display name ("Anonymous" when they hid it)
reviewer_genderstringMale | Female when the reviewer published it
reviewer_countrystringReviewer nationality, e.g. "Ireland"
reviewer_country_codestringHostelworld's nationality code, e.g. IE
reviewer_reviewsintegerHow many reviews this guest has written on Hostelworld
reviewer_imagestringReviewer avatar URL, when there is one
property_typestringHOSTEL | GUESTHOUSE | HOTEL | APARTMENT | CAMPSITE (property rows)
star_ratingintegerStar rating where the property has one, else 0 (property rows)
citystringCity (property rows)
countrystringCountry (property rows)
regionstringRegion or district Hostelworld files the property under (property rows)
addressstringStreet address (property rows)
latitudenumberLatitude (property rows)
longitudenumberLongitude (property rows)
total_ratingsintegerHow many guests have rated the hostel in total, scores without text included (property rows)
currencystringCurrency the hostel prices in (property rows)
lowest_price_per_nightnumberHostelworld's lowest advertised nightly price (property rows)
best_forarrayWhat Hostelworld says the hostel is best for, e.g. ["Home Cooking", "Meeting People"] (property rows)
facilitiesarrayEvery facility Hostelworld lists for the hostel (property rows)
descriptionstringHostelworld's own write-up of the hostel, else the hostel's description (property rows)
positive_countintegerReviews Hostelworld counts as positive (property rows)
negative_countintegerReviews Hostelworld counts as negative (property rows)
solo_percentagenumberShare of reviewers travelling solo (property rows)
couples_percentagenumberShare of reviewers travelling as a couple (property rows)
groups_percentagenumberShare of reviewers travelling in a group (property rows)
reviews_listedintegerReviews Hostelworld lists for the hostel (property rows)
reviews_fetchedintegerReviews read in this run for the hostel before filters (property rows)
statusstringok | no_reviews | not_found | duplicate | error (status rows)
reviewsintegerReviews delivered and charged for this target (status rows)
filteredintegerReviews dropped by the filters, never charged (status rows)
pagesintegerReview pages read (status rows)
totalintegerReviews Hostelworld lists for the hostel (status rows)
duplicatesinteger1 when this target resolved to a hostel another target already covers (status rows)
errorstringWhy a target failed (status rows)
fetched_atstringUTC timestamp of the request

Hostelworld reviews scraper in Python, JavaScript and curl

Python

from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("kestrel/hostelworld-reviews-scraper").call(run_input={
    "propertyIds": ["15529"],
    "maxReviewsPerProperty": 200,
    "reviewsSort": "-date",
})
rows = list(client.dataset(run["defaultDatasetId"]).iterate_items())
reviews = [r for r in rows if r["type"] == "review"]
print(len(reviews), "reviews", sum(r["rating"] for r in reviews) / len(reviews))

JavaScript (Node)

import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('kestrel/hostelworld-reviews-scraper').call({
    startUrls: ['https://www.hostelworld.com/hostels/p/15529/home-lisbon-hostel/'],
    maxReviewsPerProperty: 0,
    maxRating: 70,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((r) => r.type === 'review').length);

curl

curl -X POST "https://api.apify.com/v2/acts/kestrel~hostelworld-reviews-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"propertyIds":["15529"],"maxReviewsPerProperty":50,"reviewsSort":"-date"}'

The same three calls are runnable files in the examples repository: examples/hostelworld-reviews-scraper.py|.js|.sh.

Limits and honest notes

  • One language. Hostelworld serves a single machine-translated English set. It accepts a languages parameter and then ignores it, so this actor deliberately offers no language filter rather than one that does nothing. language and machine_translated are on every row so you can see exactly what you got.
  • liked, disliked and recommended are legacy. Hostelworld's schema still carries them; the data no longer fills them. They are kept so nothing is lost if the site starts writing them again.
  • groupTypes, minRating, maxRating, requireText and sinceDate are actor-side. The API has no server-side filter, so the pages are read and the rows are then dropped before billing.
  • Page size is capped at 50 by the API, which is what the actor asks for.
  • sinceDate only stops paging early on a date sort. With -date a run stops as soon as a whole page predates the cut; with a rating sort the dates are not ordered, so the filter still applies but every page is read.
  • Scores are 0-100, not 1-5. rating_5 is there for joins with other review sources.

FAQ

Does it need a Hostelworld API key or login?

No. This is hostelworld reviews without an api key: the endpoint is public and unauthenticated, and the actor sends no cookie, token or Origin header.

Can I download Hostelworld reviews as CSV or Excel?

Yes. Every Apify dataset exports to CSV, Excel, JSON, XML or JSONL from the run's Storage tab or the API, and the run-sync-get-dataset-items call above takes &format=csv directly.

How do I get only the bad reviews?

Set reviewsSort to rating and maxRating to about 70. The worst arrive first and everything above the ceiling is filtered before it is charged.

Can I get Hostelworld reviews by property id instead of URL?

Yes — that is propertyIds, and it is the fastest path because nothing has to be resolved. Get hostelworld reviews by property id straight from an earlier run's property_id column.

How many reviews can one hostel return?

All of them. A busy city hostel carries one to three thousand; the actor pages through the lot at 50 per request and stops on its own at the end of the list.

Does it include the hostel's reply?

Yes — owner_comment. Hostelworld owner replies are common on hostels that manage their reputation and absent on the ones that do not, which is itself a signal.

Can I scrape Hostelworld reviews without an API of my own?

Yes. That is what this actor is: no infrastructure, no proxies to buy, no browser to keep alive. Run it from the Console, the API, a schedule or an agent.

Is the reviewer data really that detailed?

Yes. Group type, age band, trip type and nationality come from Hostelworld itself, which is why backpacker reviews here support demand analysis and not only sentiment.

What do bulk hostel reviews cost?

$0.003 each, filters applied first. Bulk hostel reviews across a fifty-hostel city at 200 reviews per hostel is 10,000 rows, or $30.

Can I use it for hostel sentiment analysis?

Yes. text is clean, review_date is exact and rating gives you a numeric label to train or evaluate against, per hostel and per group type.

How to use Hostelworld Reviews Scraper

Run Hostelworld 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/hostelworld-reviews-scraper